/* create indices */
sqlite3_exec (dbh,
"CREATE INDEX idx_hash ON gn090 (hash)", NULL, NULL, NULL);
- sqlite3_exec (dbh, "CREATE INDEX idx_prio ON gn090 (prio)", NULL, NULL,
- NULL);
- sqlite3_exec (dbh, "CREATE INDEX idx_expire_prio ON gn090 (expire,prio)", NULL, NULL,
- NULL);
sqlite3_exec (dbh,
"CREATE INDEX idx_hash_vhash ON gn090 (hash,vhash)", NULL,
NULL, NULL);
- sqlite3_exec (dbh, "CREATE INDEX idx_comb ON gn090 (prio,expire,anonLevel,hash)",
+ sqlite3_exec (dbh, "CREATE INDEX idx_expire_repl ON gn090 (expire ASC,repl DESC)", NULL, NULL,
+ NULL);
+ sqlite3_exec (dbh, "CREATE INDEX idx_comb ON gn090 (anonLevel ASC,expire ASC,prio,type,hash)",
+ NULL, NULL, NULL);
+ sqlite3_exec (dbh, "CREATE INDEX idx_expire ON gn090 (expire)",
+ NULL, NULL, NULL);
+ sqlite3_exec (dbh, "CREATE INDEX idx_repl ON gn090 (repl)",
NULL, NULL, NULL);
}
CHECK (SQLITE_OK ==
sqlite3_exec (plugin->dbh,
"PRAGMA synchronous=OFF", NULL, NULL, ENULL));
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA legacy_file_format=OFF", NULL, NULL, ENULL));
CHECK (SQLITE_OK ==
sqlite3_exec (plugin->dbh,
"PRAGMA auto_vacuum=INCREMENTAL", NULL, NULL, ENULL));
+ CHECK (SQLITE_OK ==
+ sqlite3_exec (plugin->dbh,
+ "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, ENULL));
CHECK (SQLITE_OK ==
sqlite3_exec (plugin->dbh,
"PRAGMA count_changes=OFF", NULL, NULL, ENULL));
sqlite3_finalize (stmt);
create_indices (plugin->dbh);
- CHECK (SQLITE_OK ==
- sq_prepare (plugin->dbh,
- "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn071'",
- &stmt));
- if ( (sqlite3_step (stmt) == SQLITE_DONE) &&
- (sqlite3_exec (plugin->dbh,
- "CREATE TABLE gn071 ("
- " key TEXT NOT NULL DEFAULT '',"
- " value INTEGER NOT NULL DEFAULT 0)", NULL, NULL,
- NULL) != SQLITE_OK) )
- {
- LOG_SQLITE (plugin, NULL,
- GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec");
- sqlite3_finalize (stmt);
- return GNUNET_SYSERR;
- }
- sqlite3_finalize (stmt);
-
if ((sq_prepare (plugin->dbh,
- "UPDATE gn090 SET prio = prio + ?, expire = MAX(expire,?) WHERE "
- "_ROWID_ = ?",
+ "UPDATE gn090 SET prio = prio + ?, expire = MAX(expire,?) WHERE _ROWID_ = ?",
&plugin->updPrio) != SQLITE_OK) ||
(sq_prepare (plugin->dbh,
- "UPDATE gn090 SET repl = MAX (0, repl - 1) WHERE "
- "_ROWID_ = ?",
+ "UPDATE gn090 SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?",
&plugin->updRepl) != SQLITE_OK) ||
(sq_prepare (plugin->dbh,
- "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire > ?1) "
+ "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090"
" ORDER BY repl DESC, Random() LIMIT 1",
&plugin->selRepl) != SQLITE_OK) ||
(sq_prepare (plugin->dbh,
- "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 WHERE (expire < ?1) "
- " OR NOT EXISTS (SELECT 1 from gn090 WHERE (expire < ?1)) "
+ "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 "
+ " WHERE NOT EXISTS (SELECT 1 FROM gn090 WHERE expire < ?1 LIMIT 1) OR expire < ?1 "
" ORDER BY prio ASC LIMIT 1",
&plugin->selExpi) != SQLITE_OK) ||
(sq_prepare (plugin->dbh,
"INSERT INTO gn090 (repl, type, prio, "
- "anonLevel, expire, hash, vhash, value) VALUES "
- "(?, ?, ?, ?, ?, ?, ?, ?)",
+ "anonLevel, expire, hash, vhash, value) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
&plugin->insertContent) != SQLITE_OK) ||
(sq_prepare (plugin->dbh,
"DELETE FROM gn090 WHERE _ROWID_ = ?",
now = GNUNET_TIME_absolute_get ();
GNUNET_asprintf (&q,
"SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 "
- "WHERE (prio = ?1 AND expire > %llu AND anonLevel = 0 AND type=%d AND hash < ?2) "
+ "WHERE (anonLevel = 0 AND expire > %llu AND prio = ?1 AND type=%d AND hash < ?2) "
"ORDER BY hash DESC LIMIT 1",
(unsigned long long) now.abs_value,
type);
GNUNET_free (q);
GNUNET_asprintf (&q,
"SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ FROM gn090 "
- "WHERE (prio < ?1 AND expire > %llu AND anonLevel = 0 AND type=%d) "
+ "WHERE (anonLevel = 0 AND expire > %llu AND prio < ?1 AND type=%d) "
"ORDER BY prio DESC, hash DESC LIMIT 1",
(unsigned long long) now.abs_value,
type);
/**
- * Get a random item for replication. Returns a single, not expired, random item
+ * Context for 'repl_iter' function.
+ */
+struct ReplCtx
+{
+
+ /**
+ * Plugin handle.
+ */
+ struct Plugin *plugin;
+
+ /**
+ * Function to call for the result (or the NULL).
+ */
+ PluginIterator iter;
+
+ /**
+ * Closure for iter.
+ */
+ void *iter_cls;
+};
+
+
+/**
+ * Wrapper for the iterator for 'sqlite_plugin_replication_get'.
+ * Decrements the replication counter and calls the original
+ * iterator.
+ *
+ * @param cls closure
+ * @param next_cls closure to pass to the "next" function.
+ * @param key key for the content
+ * @param size number of bytes in data
+ * @param data content stored
+ * @param type type of the content
+ * @param priority priority of the content
+ * @param anonymity anonymity-level for the content
+ * @param expiration expiration time for the content
+ * @param uid unique identifier for the datum;
+ * maybe 0 if no unique identifier is available
+ *
+ * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue
+ * (continue on call to "next", of course),
+ * GNUNET_NO to delete the item and continue (if supported)
+ */
+static int
+repl_iter (void *cls,
+ void *next_cls,
+ const GNUNET_HashCode *key,
+ uint32_t size,
+ const void *data,
+ enum GNUNET_BLOCK_Type type,
+ uint32_t priority,
+ uint32_t anonymity,
+ struct GNUNET_TIME_Absolute expiration,
+ uint64_t uid)
+{
+ struct ReplCtx *rc = cls;
+ struct Plugin *plugin = rc->plugin;
+ int ret;
+
+ ret = rc->iter (rc->iter_cls,
+ next_cls, key,
+ size, data,
+ type, priority, anonymity, expiration,
+ uid);
+ if (NULL != key)
+ {
+ sqlite3_bind_int64 (plugin->updRepl, 1, uid);
+ if (SQLITE_DONE != sqlite3_step (plugin->updRepl))
+ {
+ LOG_SQLITE (plugin, NULL,
+ GNUNET_ERROR_TYPE_ERROR |
+ GNUNET_ERROR_TYPE_BULK, "sqlite3_step");
+ if (SQLITE_OK != sqlite3_reset (plugin->updRepl))
+ LOG_SQLITE (plugin, NULL,
+ GNUNET_ERROR_TYPE_ERROR |
+ GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
+ return GNUNET_SYSERR;
+ }
+ if (SQLITE_OK != sqlite3_reset (plugin->delRow))
+ LOG_SQLITE (plugin, NULL,
+ GNUNET_ERROR_TYPE_ERROR |
+ GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
+ }
+ return ret;
+}
+
+
+/**
+ * Get a random item for replication. Returns a single random item
* from those with the highest replication counters. The item's
* replication counter is decremented by one IF it was positive before.
* Call 'iter' with all values ZERO or NULL if the datastore is empty.
PluginIterator iter, void *iter_cls)
{
struct Plugin *plugin = cls;
- sqlite3_stmt *stmt;
- struct GNUNET_TIME_Absolute now;
+ struct ReplCtx rc;
#if DEBUG_SQLITE
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
"sqlite",
"Getting random block based on replication order.\n");
#endif
- stmt = plugin->selRepl;
- now = GNUNET_TIME_absolute_get ();
- if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, now.abs_value))
- {
- LOG_SQLITE (plugin, NULL,
- GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX");
- if (SQLITE_OK != sqlite3_reset (stmt))
- LOG_SQLITE (plugin, NULL,
- GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset");
- iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0,
- GNUNET_TIME_UNIT_ZERO_ABS, 0);
- return;
- }
- execute_get (plugin, stmt, iter, iter_cls);
+ rc.plugin = plugin;
+ rc.iter = iter;
+ rc.iter_cls = iter_cls;
+ execute_get (plugin, plugin->selRepl, &repl_iter, &rc);
}
_("sqlite version to old to determine size, assuming zero\n"));
return 0;
}
- if (SQLITE_OK !=
- sqlite3_exec (plugin->dbh,
- "VACUUM", NULL, NULL, ENULL))
- abort ();
CHECK (SQLITE_OK ==
sqlite3_exec (plugin->dbh,
"VACUUM", NULL, NULL, ENULL));