-/**
- * Context for the universal iterator.
- */
-struct NextContext;
-
-/**
- * Type of a function that will prepare
- * the next iteration.
- *
- * @param cls closure
- * @param nc the next context; NULL for the last
- * call which gives the callback a chance to
- * clean up the closure
- * @return GNUNET_OK on success, GNUNET_NO if there are
- * no more values, GNUNET_SYSERR on error
- */
-typedef int (*PrepareFunction)(void *cls,
- struct NextContext *nc);
-
-
-/**
- * Context we keep for the "next request" callback.
- */
-struct NextContext
-{
- /**
- * Internal state.
- */
- struct Plugin *plugin;
-
- /**
- * Function to call on the next value.
- */
- PluginIterator iter;
-
- /**
- * Closure for iter.
- */
- void *iter_cls;
-
- /**
- * Function to call to prepare the next
- * iteration.
- */
- PrepareFunction prep;
-
- /**
- * Closure for prep.
- */
- void *prep_cls;
-
- /**
- * Statement that the iterator will get the data
- * from (updated or set by prep).
- */
- sqlite3_stmt *stmt;
-
- /**
- * Row ID of the last result.
- */
- unsigned long long last_rowid;
-
- /**
- * Key of the last result.
- */
- GNUNET_HashCode lastKey;
-
- /**
- * Expiration time of the last value visited.
- */
- struct GNUNET_TIME_Absolute lastExpiration;
-
- /**
- * Priority of the last value visited.
- */
- unsigned int lastPriority;
-
- /**
- * Number of results processed so far.
- */
- unsigned int count;
-
- /**
- * Set to GNUNET_YES if we must stop now.
- */
- int end_it;
-};
-
-
-/**
- * Continuation of "sqlite_next_request".
- *
- * @param cls the next context
- * @param tc the task context (unused)
- */
-static void
-sqlite_next_request_cont (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct NextContext * nc = cls;
- struct Plugin *plugin;
- unsigned long long rowid;
- sqlite3_stmt *stmtd;
- int ret;
- unsigned int type;
- unsigned int size;
- unsigned int priority;
- unsigned int anonymity;
- struct GNUNET_TIME_Absolute expiration;
- const GNUNET_HashCode *key;
- const void *data;
-
- plugin = nc->plugin;
- plugin->next_task = GNUNET_SCHEDULER_NO_TASK;
- plugin->next_task_nc = NULL;
- if ( (GNUNET_YES == nc->end_it) ||
- (GNUNET_OK != (nc->prep(nc->prep_cls,
- nc))) )
- {
- END:
- nc->iter (nc->iter_cls,
- NULL, NULL, 0, NULL, 0, 0, 0,
- GNUNET_TIME_UNIT_ZERO_ABS, 0);
- nc->prep (nc->prep_cls, NULL);
- GNUNET_free (nc);
- return;
- }
-
- rowid = sqlite3_column_int64 (nc->stmt, 7);
- nc->last_rowid = rowid;
- type = sqlite3_column_int (nc->stmt, 1);
- size = sqlite3_column_bytes (nc->stmt, 6);
- if (sqlite3_column_bytes (nc->stmt, 5) != sizeof (GNUNET_HashCode))
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
- "sqlite",
- _("Invalid data in database. Trying to fix (by deletion).\n"));
- if (SQLITE_OK != sqlite3_reset (nc->stmt))
- LOG_SQLITE (nc->plugin, NULL,
- GNUNET_ERROR_TYPE_ERROR |
- GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
- if (sq_prepare
- (nc->plugin->dbh,
- "DELETE FROM gn080 WHERE NOT LENGTH(hash) = ?",
- &stmtd) != SQLITE_OK)
- {
- LOG_SQLITE (nc->plugin, NULL,
- GNUNET_ERROR_TYPE_ERROR |
- GNUNET_ERROR_TYPE_BULK,
- "sq_prepare");
- goto END;
- }
-
- if (SQLITE_OK != sqlite3_bind_int (stmtd, 1, sizeof (GNUNET_HashCode)))
- LOG_SQLITE (nc->plugin, NULL,
- GNUNET_ERROR_TYPE_ERROR |
- GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_int");
- if (SQLITE_DONE != sqlite3_step (stmtd))
- LOG_SQLITE (nc->plugin, NULL,
- GNUNET_ERROR_TYPE_ERROR |
- GNUNET_ERROR_TYPE_BULK, "sqlite3_step");
- if (SQLITE_OK != sqlite3_finalize (stmtd))
- LOG_SQLITE (nc->plugin, NULL,
- GNUNET_ERROR_TYPE_ERROR |
- GNUNET_ERROR_TYPE_BULK, "sqlite3_finalize");
- goto END;
- }
-
- priority = sqlite3_column_int (nc->stmt, 2);
- anonymity = sqlite3_column_int (nc->stmt, 3);
- expiration.value = sqlite3_column_int64 (nc->stmt, 4);
- key = sqlite3_column_blob (nc->stmt, 5);
- nc->lastPriority = priority;
- nc->lastExpiration = expiration;
- memcpy (&nc->lastKey, key, sizeof(GNUNET_HashCode));
- data = sqlite3_column_blob (nc->stmt, 6);
- nc->count++;
- ret = nc->iter (nc->iter_cls,
- nc,
- key,
- size,
- data,
- type,
- priority,
- anonymity,
- expiration,
- rowid);
- if (ret == GNUNET_SYSERR)
- {
- nc->end_it = GNUNET_YES;
- return;
- }
-#if DEBUG_SQLITE
- if (ret == GNUNET_NO)
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "sqlite",
- "Asked to remove entry %llu (%u bytes)\n",
- (unsigned long long) rowid,
- size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
-#endif
- if ( (ret == GNUNET_NO) &&
- (GNUNET_OK == delete_by_rowid (plugin, rowid)) )
- {
- if (plugin->payload >= size + GNUNET_DATASTORE_ENTRY_OVERHEAD)
- plugin->payload -= (size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
- else
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Datastore payload inaccurate, please fix and restart!\n"));
- plugin->lastSync++;
-#if DEBUG_SQLITE
- if (ret == GNUNET_NO)
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "sqlite",
- "Removed entry %llu (%u bytes), new payload is %llu\n",
- (unsigned long long) rowid,
- size + GNUNET_DATASTORE_ENTRY_OVERHEAD,
- plugin->payload);
-#endif
- if (plugin->lastSync >= MAX_STAT_SYNC_LAG)
- sync_stats (plugin);
- }
-}
-
-
-/**
- * Function invoked on behalf of a "PluginIterator"
- * asking the database plugin to call the iterator
- * with the next item.
- *
- * @param next_cls whatever argument was given
- * to the PluginIterator as "next_cls".
- * @param end_it set to GNUNET_YES if we
- * should terminate the iteration early
- * (iterator should be still called once more
- * to signal the end of the iteration).
- */
-static void
-sqlite_next_request (void *next_cls,
- int end_it)
-{
- struct NextContext * nc= next_cls;
-
- if (GNUNET_YES == end_it)
- nc->end_it = GNUNET_YES;
- nc->plugin->next_task_nc = nc;
- nc->plugin->next_task = GNUNET_SCHEDULER_add_now (nc->plugin->env->sched,
- &sqlite_next_request_cont,
- nc);
-}
-
-
-