mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-23 15:02:27 +00:00
Issue #69: continue work on multi-bind varargs
Revise sqlite_prepare() macro et al and underlying functions to use bind varargs instead of sprintf(3)-style varargs. Convert all SQL function calls in rhizome_database.c
This commit is contained in:
parent
772e1bf9d6
commit
8f7d600216
74
rhizome.h
74
rhizome.h
@ -294,34 +294,60 @@ int (*sqlite_set_tracefunc(int (*newfunc)()))();
|
|||||||
int is_debug_rhizome();
|
int is_debug_rhizome();
|
||||||
int is_debug_rhizome_ads();
|
int is_debug_rhizome_ads();
|
||||||
|
|
||||||
sqlite3_stmt *_sqlite_prepare_loglevel(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqltext);
|
enum sqlbind_type {
|
||||||
|
END = 0xbabecafe,
|
||||||
|
NUL = 0xbeef, // int index
|
||||||
|
INT, // int index, int value
|
||||||
|
INT64, // int index, int64_t value
|
||||||
|
STATIC_TEXT, // int index, const char *text,
|
||||||
|
STATIC_TEXT_LEN, // int index, const char *text, int bytes
|
||||||
|
STATIC_BLOB, // int index, const void *blob, int bytes
|
||||||
|
SID_T, // int index, const sid_t *sidp
|
||||||
|
BUNDLE_ID_T, // int index, const unsigned char bid_binary[RHIZOME_BUNDLE_ID_BYTES]
|
||||||
|
FILEHASH_T, // int index, const unsigned char hash_binary[RHIZOME_FILEHASH_BYTES]
|
||||||
|
TOHEX, // int index, const unsigned char *binary, unsigned bytes
|
||||||
|
TEXT_TOUPPER, // int index, const char *text,
|
||||||
|
TEXT_LEN_TOUPPER, // int index, const char *text, unsigned bytes
|
||||||
|
INDEX = 0xfade0000, // INDEX|INT, int index, ...
|
||||||
|
NAMED = 0xdead0000 // NAMED|INT, const char *label, ...
|
||||||
|
};
|
||||||
|
|
||||||
|
sqlite3_stmt *_sqlite_prepare_bind_loglevel(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqltext, ...);
|
||||||
|
int _sqlite_bind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement, ...);
|
||||||
|
int _sqlite_vbind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement, va_list ap);
|
||||||
int _sqlite_retry(struct __sourceloc, sqlite_retry_state *retry, const char *action);
|
int _sqlite_retry(struct __sourceloc, sqlite_retry_state *retry, const char *action);
|
||||||
void _sqlite_retry_done(struct __sourceloc, sqlite_retry_state *retry, const char *action);
|
void _sqlite_retry_done(struct __sourceloc, sqlite_retry_state *retry, const char *action);
|
||||||
int _sqlite_step_retry(struct __sourceloc, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement);
|
int _sqlite_step_retry(struct __sourceloc, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement);
|
||||||
int _sqlite_exec_void(struct __sourceloc, const char *sqlformat, ...);
|
int _sqlite_exec_void(struct __sourceloc, const char *sqltext, ...);
|
||||||
int _sqlite_exec_void_loglevel(struct __sourceloc, int log_level, const char *sqlformat, ...);
|
int _sqlite_exec_void_loglevel(struct __sourceloc, int log_level, const char *sqltext, ...);
|
||||||
int _sqlite_exec_void_retry(struct __sourceloc, sqlite_retry_state *retry, const char *sqlformat, ...);
|
int _sqlite_exec_void_retry(struct __sourceloc, sqlite_retry_state *retry, const char *sqltext, ...);
|
||||||
int _sqlite_exec_void_retry_loglevel(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqlformat, ...);
|
int _sqlite_exec_void_retry_loglevel(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqltext, ...);
|
||||||
int _sqlite_exec_int64(struct __sourceloc, int64_t *result, const char *sqlformat, ...);
|
int _sqlite_exec_int64(struct __sourceloc, int64_t *result, const char *sqltext, ...);
|
||||||
int _sqlite_exec_int64_retry(struct __sourceloc, sqlite_retry_state *retry, int64_t *result, const char *sqlformat, ...);
|
int _sqlite_exec_int64_retry(struct __sourceloc, sqlite_retry_state *retry, int64_t *result, const char *sqltext, ...);
|
||||||
int _sqlite_exec_strbuf(struct __sourceloc, strbuf sb, const char *sqlformat, ...);
|
int _sqlite_exec_strbuf(struct __sourceloc, strbuf sb, const char *sqltext, ...);
|
||||||
int _sqlite_exec_strbuf_retry(struct __sourceloc, sqlite_retry_state *retry, strbuf sb, const char *sqlformat, ...);
|
int _sqlite_exec_strbuf_retry(struct __sourceloc, sqlite_retry_state *retry, strbuf sb, const char *sqltext, ...);
|
||||||
int _sqlite_vexec_strbuf_retry(struct __sourceloc, sqlite_retry_state *retry, strbuf sb, const char *sqlformat, va_list ap);
|
int _sqlite_vexec_strbuf_retry(struct __sourceloc, sqlite_retry_state *retry, strbuf sb, const char *sqltext, va_list ap);
|
||||||
|
|
||||||
#define sqlite_prepare(rs,text) _sqlite_prepare_loglevel(__WHENCE__, LOG_LEVEL_ERROR, (rs), (text))
|
// The 'arg' arguments in the following macros appear to be unnecessary, but
|
||||||
#define sqlite_prepare_loglevel(ll,rs,text) _sqlite_prepare_loglevel(__WHENCE__, (ll), (rs), (text))
|
// they serve a very useful purpose, so don't remove them! They ensure that
|
||||||
#define sqlite_retry(rs,action) _sqlite_retry(__WHENCE__, (rs), (action))
|
// programmers do not forget the bind args, of which there must be at least
|
||||||
#define sqlite_retry_done(rs,action) _sqlite_retry_done(__WHENCE__, (rs), (action))
|
// one, even if it is only 'END' to make no bindings at all.
|
||||||
#define sqlite_step(stmt) _sqlite_step_retry(__WHENCE__, LOG_LEVEL_ERROR, NULL, (stmt))
|
#define sqlite_prepare(rs,sql) _sqlite_prepare_bind_loglevel(__WHENCE__, LOG_LEVEL_ERROR, (rs), (sql), END)
|
||||||
#define sqlite_step_retry(rs,stmt) _sqlite_step_retry(__WHENCE__, LOG_LEVEL_ERROR, (rs), (stmt))
|
#define sqlite_prepare_loglevel(ll,rs,sql) _sqlite_prepare_bind_loglevel(__WHENCE__, (ll), (rs), (sql), END)
|
||||||
#define sqlite_exec_void(fmt,...) _sqlite_exec_void(__WHENCE__, (fmt), ##__VA_ARGS__)
|
#define sqlite_prepare_bind(rs,sql,arg,...) _sqlite_prepare_bind_loglevel(__WHENCE__, LOG_LEVEL_ERROR, (rs), (sql), arg, ##__VA_ARGS__)
|
||||||
#define sqlite_exec_void_loglevel(ll,fmt,...) _sqlite_exec_void_loglevel(__WHENCE__, (ll), (fmt), ##__VA_ARGS__)
|
#define sqlite_prepare_bind_loglevel(ll,rs,sql,arg,...) _sqlite_prepare_bind_loglevel(__WHENCE__, (ll), (rs), (sql), arg, ##__VA_ARGS__)
|
||||||
#define sqlite_exec_void_retry(rs,fmt,...) _sqlite_exec_void_retry(__WHENCE__, (rs), (fmt), ##__VA_ARGS__)
|
#define sqlite_retry(rs,action) _sqlite_retry(__WHENCE__, (rs), (action))
|
||||||
#define sqlite_exec_void_retry_loglevel(ll,rs,fmt,...) _sqlite_exec_void_retry_loglevel(__WHENCE__, (ll), (rs), (fmt), ##__VA_ARGS__)
|
#define sqlite_retry_done(rs,action) _sqlite_retry_done(__WHENCE__, (rs), (action))
|
||||||
#define sqlite_exec_int64(res,fmt,...) _sqlite_exec_int64(__WHENCE__, (res), (fmt), ##__VA_ARGS__)
|
#define sqlite_step(stmt) _sqlite_step_retry(__WHENCE__, LOG_LEVEL_ERROR, NULL, (stmt))
|
||||||
#define sqlite_exec_int64_retry(rs,res,fmt,...) _sqlite_exec_int64_retry(__WHENCE__, (rs), (res), (fmt), ##__VA_ARGS__)
|
#define sqlite_step_retry(rs,stmt) _sqlite_step_retry(__WHENCE__, LOG_LEVEL_ERROR, (rs), (stmt))
|
||||||
#define sqlite_exec_strbuf(sb,fmt,...) _sqlite_exec_strbuf(__WHENCE__, (sb), (fmt), ##__VA_ARGS__)
|
#define sqlite_exec_void(sql,arg,...) _sqlite_exec_void(__WHENCE__, (sql), ##__VA_ARGS__)
|
||||||
#define sqlite_exec_strbuf_retry(rs,sb,fmt,...) _sqlite_exec_strbuf_retry(__WHENCE__, (rs), (sb), (fmt), ##__VA_ARGS__)
|
#define sqlite_exec_void_loglevel(ll,sql,arg,...) _sqlite_exec_void_loglevel(__WHENCE__, (ll), (sql), arg, ##__VA_ARGS__)
|
||||||
|
#define sqlite_exec_void_retry(rs,sql,arg,...) _sqlite_exec_void_retry(__WHENCE__, (rs), (sql), arg, ##__VA_ARGS__)
|
||||||
|
#define sqlite_exec_void_retry_loglevel(ll,rs,sql,arg,...) _sqlite_exec_void_retry_loglevel(__WHENCE__, (ll), (rs), (sql), arg, ##__VA_ARGS__)
|
||||||
|
#define sqlite_exec_int64(res,sql,arg,...) _sqlite_exec_int64(__WHENCE__, (res), (sql), arg, ##__VA_ARGS__)
|
||||||
|
#define sqlite_exec_int64_retry(rs,res,sql,arg,...) _sqlite_exec_int64_retry(__WHENCE__, (rs), (res), (sql), arg, ##__VA_ARGS__)
|
||||||
|
#define sqlite_exec_strbuf(sb,sql,arg,...) _sqlite_exec_strbuf(__WHENCE__, (sb), (sql), arg, ##__VA_ARGS__)
|
||||||
|
#define sqlite_exec_strbuf_retry(rs,sb,sql,arg,...) _sqlite_exec_strbuf_retry(__WHENCE__, (rs), (sb), (sql), arg, ##__VA_ARGS__)
|
||||||
|
|
||||||
double rhizome_manifest_get_double(rhizome_manifest *m,char *var,double default_value);
|
double rhizome_manifest_get_double(rhizome_manifest *m,char *var,double default_value);
|
||||||
int rhizome_manifest_extract_signature(rhizome_manifest *m,int *ofs);
|
int rhizome_manifest_extract_signature(rhizome_manifest *m,int *ofs);
|
||||||
|
@ -81,11 +81,11 @@ int rhizome_manifest_priority(sqlite_retry_state *retry, const char *id)
|
|||||||
{
|
{
|
||||||
int64_t result = 0;
|
int64_t result = 0;
|
||||||
if (sqlite_exec_int64_retry(retry, &result,
|
if (sqlite_exec_int64_retry(retry, &result,
|
||||||
"select max(grouplist.priorty) from grouplist,manifests,groupmemberships"
|
"SELECT max(grouplist.priorty) FROM GROUPLIST,MANIFESTS,GROUPMEMBERSHIPS"
|
||||||
" where manifests.id='%s'"
|
" WHERE MANIFESTS.id = ?"
|
||||||
" and grouplist.id=groupmemberships.groupid"
|
" AND GROUPLIST.id = GROUPMEMBERSHIPS.groupid"
|
||||||
" and groupmemberships.manifestid=manifests.id;",
|
" AND GROUPMEMBERSHIPS.manifestid = MANIFESTS.id;",
|
||||||
id
|
TEXT_TOUPPER, id, END
|
||||||
) == -1
|
) == -1
|
||||||
)
|
)
|
||||||
return -1;
|
return -1;
|
||||||
@ -166,7 +166,7 @@ void verify_bundles(){
|
|||||||
}
|
}
|
||||||
if (ret!=0){
|
if (ret!=0){
|
||||||
DEBUGF("Removing invalid manifest entry @%lld", rowid);
|
DEBUGF("Removing invalid manifest entry @%lld", rowid);
|
||||||
sqlite_exec_void_retry(&retry, "DELETE FROM MANIFESTS WHERE ROWID=%lld;", rowid);
|
sqlite_exec_void_retry(&retry, "DELETE FROM MANIFESTS WHERE ROWID = ?;", INT64, rowid, END);
|
||||||
}
|
}
|
||||||
rhizome_manifest_free(m);
|
rhizome_manifest_free(m);
|
||||||
}
|
}
|
||||||
@ -234,47 +234,47 @@ int rhizome_opendb()
|
|||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
|
|
||||||
int64_t version;
|
int64_t version;
|
||||||
if (sqlite_exec_int64_retry(&retry, &version, "PRAGMA user_version;") == -1)
|
if (sqlite_exec_int64_retry(&retry, &version, "PRAGMA user_version;", END) == -1)
|
||||||
RETURN(-1);
|
RETURN(-1);
|
||||||
|
|
||||||
if (version<1){
|
if (version<1){
|
||||||
/* Create tables as required */
|
/* Create tables as required */
|
||||||
sqlite_exec_void_loglevel(loglevel, "PRAGMA auto_vacuum=2;");
|
sqlite_exec_void_loglevel(loglevel, "PRAGMA auto_vacuum=2;", END);
|
||||||
if ( sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS GROUPLIST(id text not null primary key, closed integer,ciphered integer,priority integer);") == -1
|
if ( sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS GROUPLIST(id text not null primary key, closed integer,ciphered integer,priority integer);", END) == -1
|
||||||
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS MANIFESTS(id text not null primary key, version integer,inserttime integer, filesize integer, filehash text, author text, bar blob, manifest blob);") == -1
|
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS MANIFESTS(id text not null primary key, version integer,inserttime integer, filesize integer, filehash text, author text, bar blob, manifest blob);", END) == -1
|
||||||
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS FILES(id text not null primary key, length integer, highestpriority integer, datavalid integer, inserttime integer);") == -1
|
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS FILES(id text not null primary key, length integer, highestpriority integer, datavalid integer, inserttime integer);", END) == -1
|
||||||
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS FILEBLOBS(id text not null primary key, data blob);") == -1
|
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS FILEBLOBS(id text not null primary key, data blob);", END) == -1
|
||||||
|| sqlite_exec_void_retry(&retry, "DROP TABLE IF EXISTS FILEMANIFESTS;") == -1
|
|| sqlite_exec_void_retry(&retry, "DROP TABLE IF EXISTS FILEMANIFESTS;", END) == -1
|
||||||
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS GROUPMEMBERSHIPS(manifestid text not null, groupid text not null);") == -1
|
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS GROUPMEMBERSHIPS(manifestid text not null, groupid text not null);", END) == -1
|
||||||
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS VERIFICATIONS(sid text not null, did text, name text, starttime integer, endtime integer, signature blob);") == -1
|
|| sqlite_exec_void_retry(&retry, "CREATE TABLE IF NOT EXISTS VERIFICATIONS(sid text not null, did text, name text, starttime integer, endtime integer, signature blob);", END) == -1
|
||||||
) {
|
) {
|
||||||
RETURN(WHY("Failed to create schema"));
|
RETURN(WHY("Failed to create schema"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create indexes if they don't already exist */
|
/* Create indexes if they don't already exist */
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS bundlesizeindex ON manifests (filesize);");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS bundlesizeindex ON manifests (filesize);", END);
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS IDX_MANIFESTS_HASH ON MANIFESTS(filehash);");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS IDX_MANIFESTS_HASH ON MANIFESTS(filehash);", END);
|
||||||
|
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=1;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=1;", END);
|
||||||
}
|
}
|
||||||
if (version<2){
|
if (version<2){
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN service text;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN service text;", END);
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN name text;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN name text;", END);
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN sender text collate nocase;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN sender text collate nocase;", END);
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN recipient text collate nocase;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN recipient text collate nocase;", END);
|
||||||
// if more bundle verification is required in later upgrades, move this to the end, don't run it more than once.
|
// if more bundle verification is required in later upgrades, move this to the end, don't run it more than once.
|
||||||
verify_bundles();
|
verify_bundles();
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=2;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=2;", END);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version<3){
|
if (version<3){
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS IDX_MANIFESTS_ID_VERSION ON MANIFESTS(id, version);");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS IDX_MANIFESTS_ID_VERSION ON MANIFESTS(id, version);", END);
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=3;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=3;", END);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version<4){
|
if (version<4){
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN tail integer;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "ALTER TABLE MANIFESTS ADD COLUMN tail integer;", END);
|
||||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=4;");
|
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=4;", END);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO recreate tables with collate nocase on hex columns
|
// TODO recreate tables with collate nocase on hex columns
|
||||||
@ -298,7 +298,7 @@ int rhizome_close_db()
|
|||||||
|
|
||||||
if (!sqlite3_get_autocommit(rhizome_db)){
|
if (!sqlite3_get_autocommit(rhizome_db)){
|
||||||
WHY("Uncommitted transaction!");
|
WHY("Uncommitted transaction!");
|
||||||
sqlite_exec_void("ROLLBACK;");
|
sqlite_exec_void("ROLLBACK;", END);
|
||||||
}
|
}
|
||||||
sqlite3_stmt *stmt = NULL;
|
sqlite3_stmt *stmt = NULL;
|
||||||
while ((stmt = sqlite3_next_stmt(rhizome_db, stmt))) {
|
while ((stmt = sqlite3_next_stmt(rhizome_db, stmt))) {
|
||||||
@ -418,10 +418,11 @@ void _sqlite_retry_done(struct __sourceloc __whence, sqlite_retry_state *retry,
|
|||||||
* methods, because those are susceptible to SQL injection attacks. Instead, use bound parameters
|
* methods, because those are susceptible to SQL injection attacks. Instead, use bound parameters
|
||||||
* and bind them using the sqlite_bind() function below.
|
* and bind them using the sqlite_bind() function below.
|
||||||
*
|
*
|
||||||
* IN PARTICULAR, do not add sprintf(3)-like functionality to this method. It used to take
|
* ALSO! Do not add sprintf(3)-like functionality to this method. It used to take sprintf(3)-style
|
||||||
* sprintf(3)-style varargs and these were deliberately removed. It is vital to discourage bad
|
* varargs and these were deliberately removed. It is vital to discourage bad practice, and adding
|
||||||
* practice, and adding sprintf(3)-style args to this function would be a step in the wrong
|
* sprintf(3)-style args to this function would be a step in the wrong direction.
|
||||||
* direction.
|
*
|
||||||
|
* See GitHub issue #69.
|
||||||
*
|
*
|
||||||
* @author Andrew Bettison <andrew@servalproject.com>
|
* @author Andrew Bettison <andrew@servalproject.com>
|
||||||
*/
|
*/
|
||||||
@ -449,90 +450,101 @@ sqlite3_stmt *_sqlite_prepare_loglevel(struct __sourceloc __whence, int log_leve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum sqlbind_type {
|
int _sqlite_vbind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement, va_list ap)
|
||||||
END = 0,
|
|
||||||
NUL,
|
|
||||||
INT, // int value
|
|
||||||
INT64, // int64_t value
|
|
||||||
STATIC_TEXT, // const char *text,
|
|
||||||
STATIC_TEXT_LEN, // const char *text, int bytes
|
|
||||||
STATIC_BLOB, // const void *blob, int bytes
|
|
||||||
SID_T, // const sid_t *sidp
|
|
||||||
BUNDLE_ID_T, // const unsigned char bid_binary[RHIZOME_BUNDLE_ID_BYTES]
|
|
||||||
FILEHASH_T, // const unsigned char hash_binary[RHIZOME_FILEHASH_BYTES]
|
|
||||||
TOHEX, // const unsigned char *binary, unsigned bytes
|
|
||||||
TEXT_TOUPPER, // const char *text,
|
|
||||||
TEXT_LEN_TOUPPER, // const char *text, unsigned bytes
|
|
||||||
|
|
||||||
NAMED = (1 << 12)
|
|
||||||
};
|
|
||||||
|
|
||||||
int _sqlite_bind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement, ...)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
const int index_limit = 50; // for safety checks
|
||||||
va_list ap;
|
|
||||||
va_start(ap, statement);
|
|
||||||
enum sqlbind_type typ;
|
enum sqlbind_type typ;
|
||||||
|
int index_counter = 0;
|
||||||
do {
|
do {
|
||||||
typ = va_arg(ap, int);
|
typ = va_arg(ap, int);
|
||||||
const char *name = NULL;
|
|
||||||
int index;
|
int index;
|
||||||
if (typ & NAMED) {
|
if ((typ & 0xffff0000) == INDEX) {
|
||||||
typ |= ~NAMED;
|
typ &= 0xffff;
|
||||||
name = va_arg(ap, const char *);
|
index = va_arg(ap, int);
|
||||||
|
if (index < 1 || index > index_limit) {
|
||||||
|
LOGF(log_level, "illegal index %d: %s", index, sqlite3_sql(statement));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if ((typ & 0xffff0000) == NAMED) {
|
||||||
|
typ &= 0xffff;
|
||||||
|
const char *name = va_arg(ap, const char *);
|
||||||
index = sqlite3_bind_parameter_index(statement, name);
|
index = sqlite3_bind_parameter_index(statement, name);
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
LOGF(log_level, "no parameter %s in query: %s", alloca_str_toprint(name), sqlite3_sql(statement));
|
LOGF(log_level, "no parameter %s in query: %s", alloca_str_toprint(name), sqlite3_sql(statement));
|
||||||
ret = -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
index = va_arg(ap, int);
|
index = ++index_counter;
|
||||||
|
#define BIND_RETRY(FUNC, ...) \
|
||||||
|
do { \
|
||||||
|
switch (FUNC(statement, index, ##__VA_ARGS__)) { \
|
||||||
|
case SQLITE_OK: \
|
||||||
|
break; \
|
||||||
|
case SQLITE_BUSY: \
|
||||||
|
case SQLITE_LOCKED: \
|
||||||
|
if (retry && _sqlite_retry(__whence, retry, #FUNC "()")) \
|
||||||
|
continue; \
|
||||||
|
default: \
|
||||||
|
LOGF(log_level, #FUNC "(%d) failed, %s: %s", index, sqlite3_errmsg(rhizome_db), sqlite3_sql(statement)); \
|
||||||
|
sqlite3_finalize(statement); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
} while (1)
|
||||||
switch (typ) {
|
switch (typ) {
|
||||||
case END: break;
|
case END: break;
|
||||||
case NUL:
|
case NUL:
|
||||||
ret = sqlite3_bind_null(statement, index);
|
BIND_RETRY(sqlite3_bind_null);
|
||||||
break;
|
break;
|
||||||
case INT:
|
case INT: {
|
||||||
ret = sqlite3_bind_int(statement, index, va_arg(ap, int));
|
int value = va_arg(ap, int);
|
||||||
|
BIND_RETRY(sqlite3_bind_int, value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case INT64:
|
case INT64: {
|
||||||
ret = sqlite3_bind_int64(statement, index, va_arg(ap, int64_t));
|
int64_t value = va_arg(ap, int64_t);
|
||||||
|
BIND_RETRY(sqlite3_bind_int64, value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case STATIC_TEXT:
|
case STATIC_TEXT: {
|
||||||
ret = sqlite3_bind_text(statement, index, va_arg(ap, const char *), -1, SQLITE_STATIC);
|
const char *text = va_arg(ap, const char *);
|
||||||
|
BIND_RETRY(sqlite3_bind_text, text, -1, SQLITE_STATIC);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case STATIC_TEXT_LEN: {
|
case STATIC_TEXT_LEN: {
|
||||||
const char *text = va_arg(ap, const char *);
|
const char *text = va_arg(ap, const char *);
|
||||||
int bytes = va_arg(ap, int);
|
int bytes = va_arg(ap, int);
|
||||||
ret = sqlite3_bind_text(statement, index, text, bytes, SQLITE_STATIC);
|
BIND_RETRY(sqlite3_bind_text, text, bytes, SQLITE_STATIC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATIC_BLOB: {
|
case STATIC_BLOB: {
|
||||||
const void *blob = va_arg(ap, const void *);
|
const void *blob = va_arg(ap, const void *);
|
||||||
int bytes = va_arg(ap, int);
|
int bytes = va_arg(ap, int);
|
||||||
ret = sqlite3_bind_blob(statement, index, blob, bytes, SQLITE_STATIC);
|
BIND_RETRY(sqlite3_bind_blob, blob, bytes, SQLITE_STATIC);
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case SID_T: {
|
case SID_T: {
|
||||||
const sid_t *sidp = va_arg(ap, const sid_t *);
|
const sid_t *sidp = va_arg(ap, const sid_t *);
|
||||||
const char *sid_hex = alloca_tohex_sid_t(*sidp);
|
const char *sid_hex = alloca_tohex_sid_t(*sidp);
|
||||||
ret = sqlite3_bind_text(statement, index, sid_hex, SID_STRLEN, SQLITE_TRANSIENT);
|
BIND_RETRY(sqlite3_bind_text, sid_hex, SID_STRLEN, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BUNDLE_ID_T: {
|
case BUNDLE_ID_T: {
|
||||||
const char *bid_hex = alloca_tohex(va_arg(ap, const unsigned char *), RHIZOME_MANIFEST_ID_BYTES);
|
const char *bid_hex = alloca_tohex(va_arg(ap, const unsigned char *), RHIZOME_MANIFEST_ID_BYTES);
|
||||||
ret = sqlite3_bind_text(statement, index, bid_hex, RHIZOME_MANIFEST_ID_STRLEN, SQLITE_TRANSIENT);
|
BIND_RETRY(sqlite3_bind_text, bid_hex, RHIZOME_MANIFEST_ID_STRLEN, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FILEHASH_T: {
|
case FILEHASH_T: {
|
||||||
const char *hash_hex = alloca_tohex(va_arg(ap, const unsigned char *), RHIZOME_FILEHASH_BYTES);
|
const char *hash_hex = alloca_tohex(va_arg(ap, const unsigned char *), RHIZOME_FILEHASH_BYTES);
|
||||||
ret = sqlite3_bind_text(statement, index, hash_hex, RHIZOME_FILEHASH_STRLEN, SQLITE_TRANSIENT);
|
BIND_RETRY(sqlite3_bind_text, hash_hex, RHIZOME_FILEHASH_STRLEN, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOHEX: {
|
case TOHEX: {
|
||||||
const unsigned char *binary = va_arg(ap, const unsigned char *);
|
const unsigned char *binary = va_arg(ap, const unsigned char *);
|
||||||
unsigned bytes = va_arg(ap, unsigned);
|
unsigned bytes = va_arg(ap, unsigned);
|
||||||
ret = sqlite3_bind_text(statement, index, alloca_tohex(binary, bytes), bytes * 2, SQLITE_TRANSIENT);
|
char hex[bytes * 2];
|
||||||
|
tohex(hex, binary, bytes);
|
||||||
|
BIND_RETRY(sqlite3_bind_text, hex, bytes * 2, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TEXT_TOUPPER: {
|
case TEXT_TOUPPER: {
|
||||||
@ -542,7 +554,7 @@ int _sqlite_bind(struct __sourceloc __whence, int log_level, sqlite_retry_state
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i != bytes; ++i)
|
for (i = 0; i != bytes; ++i)
|
||||||
upper[i] = toupper(text[i]);
|
upper[i] = toupper(text[i]);
|
||||||
ret = sqlite3_bind_text(statement, index, upper, bytes, SQLITE_TRANSIENT);
|
BIND_RETRY(sqlite3_bind_text, upper, bytes, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TEXT_LEN_TOUPPER: {
|
case TEXT_LEN_TOUPPER: {
|
||||||
@ -552,13 +564,21 @@ int _sqlite_bind(struct __sourceloc __whence, int log_level, sqlite_retry_state
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i != bytes; ++i)
|
for (i = 0; i != bytes; ++i)
|
||||||
upper[i] = toupper(text[i]);
|
upper[i] = toupper(text[i]);
|
||||||
ret = sqlite3_bind_text(statement, index, upper, bytes, SQLITE_TRANSIENT);
|
BIND_RETRY(sqlite3_bind_text, upper, bytes, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FATALF("unsupported bind code %d", typ);
|
FATALF("unsupported bind code %d", typ);
|
||||||
}
|
}
|
||||||
} while (typ != END);
|
} while (typ != END);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _sqlite_bind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, statement);
|
||||||
|
int ret = _sqlite_vbind(__whence, log_level, retry, statement, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -632,11 +652,14 @@ static int _sqlite_exec_prepared(struct __sourceloc __whence, int log_level, sql
|
|||||||
*
|
*
|
||||||
* @author Andrew Bettison <andrew@servalproject.com>
|
* @author Andrew Bettison <andrew@servalproject.com>
|
||||||
*/
|
*/
|
||||||
static int _sqlite_vexec_void(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqlformat, va_list ap)
|
static int _sqlite_vexec_void(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqltext, va_list ap)
|
||||||
{
|
{
|
||||||
strbuf stmt = strbuf_alloca(8192);
|
sqlite3_stmt *statement = _sqlite_prepare_loglevel(__whence, log_level, retry, sqltext);
|
||||||
strbuf_vsprintf(stmt, sqlformat, ap);
|
if (!statement)
|
||||||
int rowcount = _sqlite_exec_prepared(__whence, log_level, retry, _sqlite_prepare_loglevel(__whence, log_level, retry, stmt));
|
return -1;
|
||||||
|
if (_sqlite_vbind(__whence, log_level, retry, statement, ap) == -1)
|
||||||
|
return -1;
|
||||||
|
int rowcount = _sqlite_exec_prepared(__whence, log_level, retry, statement);
|
||||||
if (rowcount == -1)
|
if (rowcount == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if (rowcount)
|
if (rowcount)
|
||||||
@ -650,12 +673,12 @@ static int _sqlite_vexec_void(struct __sourceloc __whence, int log_level, sqlite
|
|||||||
*
|
*
|
||||||
* @author Andrew Bettison <andrew@servalproject.com>
|
* @author Andrew Bettison <andrew@servalproject.com>
|
||||||
*/
|
*/
|
||||||
int _sqlite_exec_void(struct __sourceloc __whence, const char *sqlformat, ...)
|
int _sqlite_exec_void(struct __sourceloc __whence, const char *sqltext, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, sqlformat);
|
va_start(ap, sqltext);
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
int ret = _sqlite_vexec_void(__whence, LOG_LEVEL_ERROR, &retry, sqlformat, ap);
|
int ret = _sqlite_vexec_void(__whence, LOG_LEVEL_ERROR, &retry, sqltext, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -664,12 +687,12 @@ int _sqlite_exec_void(struct __sourceloc __whence, const char *sqlformat, ...)
|
|||||||
*
|
*
|
||||||
* @author Andrew Bettison <andrew@servalproject.com>
|
* @author Andrew Bettison <andrew@servalproject.com>
|
||||||
*/
|
*/
|
||||||
int _sqlite_exec_void_loglevel(struct __sourceloc __whence, int log_level, const char *sqlformat, ...)
|
int _sqlite_exec_void_loglevel(struct __sourceloc __whence, int log_level, const char *sqltext, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, sqlformat);
|
va_start(ap, sqltext);
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
int ret = _sqlite_vexec_void(__whence, log_level, &retry, sqlformat, ap);
|
int ret = _sqlite_vexec_void(__whence, log_level, &retry, sqltext, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -681,11 +704,11 @@ int _sqlite_exec_void_loglevel(struct __sourceloc __whence, int log_level, const
|
|||||||
*
|
*
|
||||||
* @author Andrew Bettison <andrew@servalproject.com>
|
* @author Andrew Bettison <andrew@servalproject.com>
|
||||||
*/
|
*/
|
||||||
int _sqlite_exec_void_retry(struct __sourceloc __whence, sqlite_retry_state *retry, const char *sqlformat, ...)
|
int _sqlite_exec_void_retry(struct __sourceloc __whence, sqlite_retry_state *retry, const char *sqltext, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, sqlformat);
|
va_start(ap, sqltext);
|
||||||
int ret = _sqlite_vexec_void(__whence, LOG_LEVEL_ERROR, retry, sqlformat, ap);
|
int ret = _sqlite_vexec_void(__whence, LOG_LEVEL_ERROR, retry, sqltext, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -694,22 +717,22 @@ int _sqlite_exec_void_retry(struct __sourceloc __whence, sqlite_retry_state *ret
|
|||||||
*
|
*
|
||||||
* @author Andrew Bettison <andrew@servalproject.com>
|
* @author Andrew Bettison <andrew@servalproject.com>
|
||||||
*/
|
*/
|
||||||
int _sqlite_exec_void_retry_loglevel(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqlformat, ...)
|
int _sqlite_exec_void_retry_loglevel(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqltext, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, sqlformat);
|
va_start(ap, sqltext);
|
||||||
int ret = _sqlite_vexec_void(__whence, log_level, retry, sqlformat, ap);
|
int ret = _sqlite_vexec_void(__whence, log_level, retry, sqltext, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sqlite_vexec_int64(struct __sourceloc __whence, sqlite_retry_state *retry, int64_t *result, const char *sqlformat, va_list ap)
|
static int _sqlite_vexec_int64(struct __sourceloc __whence, sqlite_retry_state *retry, int64_t *result, const char *sqltext, va_list ap)
|
||||||
{
|
{
|
||||||
strbuf stmt = strbuf_alloca(8192);
|
sqlite3_stmt *statement = _sqlite_prepare_loglevel(__whence, LOG_LEVEL_ERROR, retry, sqltext);
|
||||||
strbuf_vsprintf(stmt, sqlformat, ap);
|
|
||||||
sqlite3_stmt *statement = _sqlite_prepare_loglevel(__whence, LOG_LEVEL_ERROR, retry, stmt);
|
|
||||||
if (!statement)
|
if (!statement)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (_sqlite_vbind(__whence, LOG_LEVEL_ERROR, retry, statement, ap) == -1)
|
||||||
|
return -1;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int rowcount = 0;
|
int rowcount = 0;
|
||||||
int stepcode;
|
int stepcode;
|
||||||
@ -793,13 +816,13 @@ int _sqlite_exec_strbuf_retry(struct __sourceloc __whence, sqlite_retry_state *r
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _sqlite_vexec_strbuf_retry(struct __sourceloc __whence, sqlite_retry_state *retry, strbuf sb, const char *sqlformat, va_list ap)
|
int _sqlite_vexec_strbuf_retry(struct __sourceloc __whence, sqlite_retry_state *retry, strbuf sb, const char *sqltext, va_list ap)
|
||||||
{
|
{
|
||||||
strbuf stmt = strbuf_alloca(8192);
|
sqlite3_stmt *statement = _sqlite_prepare_loglevel(__whence, LOG_LEVEL_ERROR, retry, sqltext);
|
||||||
strbuf_vsprintf(stmt, sqlformat, ap);
|
|
||||||
sqlite3_stmt *statement = _sqlite_prepare_loglevel(__whence, LOG_LEVEL_ERROR, retry, stmt);
|
|
||||||
if (!statement)
|
if (!statement)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (_sqlite_vbind(__whence, LOG_LEVEL_ERROR, retry, statement, ap) == -1)
|
||||||
|
return -1;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int rowcount = 0;
|
int rowcount = 0;
|
||||||
int stepcode;
|
int stepcode;
|
||||||
@ -821,9 +844,9 @@ int64_t rhizome_database_used_bytes()
|
|||||||
int64_t db_page_size;
|
int64_t db_page_size;
|
||||||
int64_t db_page_count;
|
int64_t db_page_count;
|
||||||
int64_t db_free_page_count;
|
int64_t db_free_page_count;
|
||||||
if ( sqlite_exec_int64(&db_page_size, "PRAGMA page_size;") == -1LL
|
if ( sqlite_exec_int64(&db_page_size, "PRAGMA page_size;", END) == -1LL
|
||||||
|| sqlite_exec_int64(&db_page_count, "PRAGMA page_count;") == -1LL
|
|| sqlite_exec_int64(&db_page_count, "PRAGMA page_count;", END) == -1LL
|
||||||
|| sqlite_exec_int64(&db_free_page_count, "PRAGMA free_count;") == -1LL
|
|| sqlite_exec_int64(&db_free_page_count, "PRAGMA free_count;", END) == -1LL
|
||||||
)
|
)
|
||||||
return WHY("Cannot measure database used bytes");
|
return WHY("Cannot measure database used bytes");
|
||||||
return db_page_size * (db_page_count - db_free_page_count);
|
return db_page_size * (db_page_count - db_free_page_count);
|
||||||
@ -849,15 +872,25 @@ static int rhizome_delete_external(const char *fileid)
|
|||||||
|
|
||||||
static int rhizome_delete_orphan_fileblobs_retry(sqlite_retry_state *retry)
|
static int rhizome_delete_orphan_fileblobs_retry(sqlite_retry_state *retry)
|
||||||
{
|
{
|
||||||
return sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry, "DELETE FROM FILEBLOBS WHERE NOT EXISTS( SELECT 1 FROM FILES WHERE FILES.id = FILEBLOBS.id );");
|
return sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry,
|
||||||
|
"DELETE FROM FILEBLOBS WHERE NOT EXISTS( SELECT 1 FROM FILES WHERE FILES.id = FILEBLOBS.id );",
|
||||||
|
END);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rhizome_remove_file_datainvalid(sqlite_retry_state *retry, const char *fileid)
|
int rhizome_remove_file_datainvalid(sqlite_retry_state *retry, const char *fileid)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry, "DELETE FROM FILES WHERE id='%s' and datavalid=0;", fileid) == -1)
|
if (sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry,
|
||||||
|
"DELETE FROM FILES WHERE id = ? and datavalid = 0;",
|
||||||
|
TEXT_TOUPPER, fileid, END
|
||||||
|
) == -1
|
||||||
|
)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
if (sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry, "DELETE FROM FILEBLOBS WHERE id='%s' AND NOT EXISTS( SELECT 1 FROM FILES WHERE FILES.id=FILEBLOBS.id );", fileid) == -1)
|
if (sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry,
|
||||||
|
"DELETE FROM FILEBLOBS WHERE id = ? AND NOT EXISTS( SELECT 1 FROM FILES WHERE FILES.id = FILEBLOBS.id );",
|
||||||
|
TEXT_TOUPPER, fileid, END
|
||||||
|
) == -1
|
||||||
|
)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -875,7 +908,9 @@ int rhizome_cleanup(struct rhizome_cleanup_report *report)
|
|||||||
int candidates=0;
|
int candidates=0;
|
||||||
if (report)
|
if (report)
|
||||||
report->deleted_orphan_fileblobs = 0;
|
report->deleted_orphan_fileblobs = 0;
|
||||||
sqlite3_stmt *statement = sqlite_prepare(&retry, "SELECT id FROM FILES WHERE inserttime < %lld AND datavalid=0;", insert_horizon);
|
sqlite3_stmt *statement = sqlite_prepare_bind(&retry,
|
||||||
|
"SELECT id FROM FILES WHERE inserttime < ? AND datavalid = 0;",
|
||||||
|
INT64, insert_horizon, END);
|
||||||
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
|
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
|
||||||
candidates++;
|
candidates++;
|
||||||
const char *id = (const char *) sqlite3_column_text(statement, 0);
|
const char *id = (const char *) sqlite3_column_text(statement, 0);
|
||||||
@ -884,7 +919,9 @@ int rhizome_cleanup(struct rhizome_cleanup_report *report)
|
|||||||
}
|
}
|
||||||
sqlite3_finalize(statement);
|
sqlite3_finalize(statement);
|
||||||
|
|
||||||
statement = sqlite_prepare(&retry, "SELECT id FROM FILES WHERE inserttime < %lld AND datavalid=1 AND NOT EXISTS( SELECT 1 FROM MANIFESTS WHERE MANIFESTS.filehash = FILES.id);", insert_horizon_no_manifest);
|
statement = sqlite_prepare_bind(&retry,
|
||||||
|
"SELECT id FROM FILES WHERE inserttime < ? AND datavalid = 1 AND NOT EXISTS( SELECT 1 FROM MANIFESTS WHERE MANIFESTS.filehash = FILES.id);",
|
||||||
|
INT64, insert_horizon_no_manifest, END);
|
||||||
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
|
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
|
||||||
candidates++;
|
candidates++;
|
||||||
const char *id = (const char *) sqlite3_column_text(statement, 0);
|
const char *id = (const char *) sqlite3_column_text(statement, 0);
|
||||||
@ -896,10 +933,14 @@ int rhizome_cleanup(struct rhizome_cleanup_report *report)
|
|||||||
int ret;
|
int ret;
|
||||||
if (candidates) {
|
if (candidates) {
|
||||||
// clean out unreferenced files
|
// clean out unreferenced files
|
||||||
ret = sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry, "DELETE FROM FILES WHERE inserttime < %lld AND datavalid=0;", insert_horizon);
|
ret = sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry,
|
||||||
|
"DELETE FROM FILES WHERE inserttime < ? AND datavalid = 0;",
|
||||||
|
INT64, insert_horizon, END);
|
||||||
if (report)
|
if (report)
|
||||||
report->deleted_stale_incoming_files = ret;
|
report->deleted_stale_incoming_files = ret;
|
||||||
ret = sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry, "DELETE FROM FILES WHERE inserttime < %lld AND datavalid=1 AND NOT EXISTS( SELECT 1 FROM MANIFESTS WHERE MANIFESTS.filehash = FILES.id);", insert_horizon_no_manifest);
|
ret = sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry,
|
||||||
|
"DELETE FROM FILES WHERE inserttime < ? AND datavalid=1 AND NOT EXISTS( SELECT 1 FROM MANIFESTS WHERE MANIFESTS.filehash = FILES.id);",
|
||||||
|
INT64, insert_horizon_no_manifest, END);
|
||||||
if (report)
|
if (report)
|
||||||
report->deleted_orphan_files = ret;
|
report->deleted_orphan_files = ret;
|
||||||
}
|
}
|
||||||
@ -929,7 +970,9 @@ int rhizome_make_space(int group_priority, long long bytes)
|
|||||||
|
|
||||||
/* Okay, not enough space, so free up some. */
|
/* Okay, not enough space, so free up some. */
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
sqlite3_stmt *statement = sqlite_prepare(&retry, "select id,length from files where highestpriority < %d order by descending length", group_priority);
|
sqlite3_stmt *statement = sqlite_prepare_bind(&retry,
|
||||||
|
"SELECT id,length FROM FILES WHERE highestpriority < ? ORDER BY DESCENDING LENGTH",
|
||||||
|
INT, group_priority, END);
|
||||||
if (!statement)
|
if (!statement)
|
||||||
return -1;
|
return -1;
|
||||||
while (bytes > (config.rhizome.database_size - 65536 - rhizome_database_used_bytes())
|
while (bytes > (config.rhizome.database_size - 65536 - rhizome_database_used_bytes())
|
||||||
@ -973,9 +1016,9 @@ int rhizome_make_space(int group_priority, long long bytes)
|
|||||||
int rhizome_drop_stored_file(const char *id,int maximum_priority)
|
int rhizome_drop_stored_file(const char *id,int maximum_priority)
|
||||||
{
|
{
|
||||||
if (!rhizome_str_is_file_hash(id))
|
if (!rhizome_str_is_file_hash(id))
|
||||||
return WHYF("invalid file hash id=%s", alloca_toprint(-1, id, strlen(id)));
|
return WHYF("invalid file hash id=%s", alloca_str_toprint(id));
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
sqlite3_stmt *statement = sqlite_prepare(&retry, "select id from manifests where filehash='%s'", id);
|
sqlite3_stmt *statement = sqlite_prepare_bind(&retry, "SELECT id FROM MANIFESTS WHERE filehash = ?", TEXT_TOUPPER, id, END);
|
||||||
if (!statement)
|
if (!statement)
|
||||||
return WHYF("Could not drop stored file id=%s", id);
|
return WHYF("Could not drop stored file id=%s", id);
|
||||||
int can_drop = 1;
|
int can_drop = 1;
|
||||||
@ -999,9 +1042,9 @@ int rhizome_drop_stored_file(const char *id,int maximum_priority)
|
|||||||
} else {
|
} else {
|
||||||
if (config.debug.rhizome)
|
if (config.debug.rhizome)
|
||||||
DEBUGF("removing stale manifests, groupmemberships");
|
DEBUGF("removing stale manifests, groupmemberships");
|
||||||
sqlite_exec_void_retry(&retry, "delete from manifests where id='%s';", manifestId);
|
sqlite_exec_void_retry(&retry, "delete from manifests where id = ?;", TEXT_TOUPPER, manifestId, END);
|
||||||
sqlite_exec_void_retry(&retry, "delete from keypairs where public='%s';", manifestId);
|
sqlite_exec_void_retry(&retry, "delete from keypairs where public = ?;", TEXT_TOUPPER, manifestId, END);
|
||||||
sqlite_exec_void_retry(&retry, "delete from groupmemberships where manifestid='%s';", manifestId);
|
sqlite_exec_void_retry(&retry, "delete from groupmemberships where manifestid = ?;", TEXT_TOUPPER, manifestId, END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3_finalize(statement);
|
sqlite3_finalize(statement);
|
||||||
@ -1072,7 +1115,7 @@ int rhizome_store_bundle(rhizome_manifest *m)
|
|||||||
const char *service = rhizome_manifest_get(m, "service", NULL, 0);
|
const char *service = rhizome_manifest_get(m, "service", NULL, 0);
|
||||||
|
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;") == -1)
|
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;", END) == -1)
|
||||||
return WHY("Failed to begin transaction");
|
return WHY("Failed to begin transaction");
|
||||||
|
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
@ -1161,7 +1204,7 @@ int rhizome_store_bundle(rhizome_manifest *m)
|
|||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
stmt = NULL;
|
stmt = NULL;
|
||||||
}
|
}
|
||||||
if (sqlite_exec_void_retry(&retry, "COMMIT;") != -1){
|
if (sqlite_exec_void_retry(&retry, "COMMIT;", END) != -1){
|
||||||
// This message used in tests; do not modify or remove.
|
// This message used in tests; do not modify or remove.
|
||||||
const char *service = rhizome_manifest_get(m, "service", NULL, 0);
|
const char *service = rhizome_manifest_get(m, "service", NULL, 0);
|
||||||
INFOF("RHIZOME ADD MANIFEST service=%s bid=%s version=%"PRId64,
|
INFOF("RHIZOME ADD MANIFEST service=%s bid=%s version=%"PRId64,
|
||||||
@ -1178,7 +1221,7 @@ rollback:
|
|||||||
if (stmt)
|
if (stmt)
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
WHYF("Failed to store bundle bid=%s", manifestid);
|
WHYF("Failed to store bundle bid=%s", manifestid);
|
||||||
sqlite_exec_void_retry(&retry, "ROLLBACK;");
|
sqlite_exec_void_retry(&retry, "ROLLBACK;", END);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1208,7 +1251,7 @@ int rhizome_list_manifests(struct cli_context *context, const char *service, con
|
|||||||
RETURN(WHYF("SQL command too long: %s", strbuf_str(b)));
|
RETURN(WHYF("SQL command too long: %s", strbuf_str(b)));
|
||||||
|
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
sqlite3_stmt *statement = sqlite_prepare(&retry, "%s", strbuf_str(b));
|
sqlite3_stmt *statement = sqlite_prepare(&retry, strbuf_str(b));
|
||||||
if (!statement)
|
if (!statement)
|
||||||
RETURN(-1);
|
RETURN(-1);
|
||||||
|
|
||||||
@ -1371,13 +1414,18 @@ int rhizome_update_file_priority(const char *fileid)
|
|||||||
int64_t highestPriority = -1;
|
int64_t highestPriority = -1;
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
if (sqlite_exec_int64_retry(&retry, &highestPriority,
|
if (sqlite_exec_int64_retry(&retry, &highestPriority,
|
||||||
"SELECT max(grouplist.priority) FROM MANIFESTS,GROUPMEMBERSHIPS,GROUPLIST"
|
"SELECT max(grouplist.priority) FROM MANIFESTS, GROUPMEMBERSHIPS, GROUPLIST"
|
||||||
" where manifests.filehash='%s'"
|
" WHERE MANIFESTS.filehash = ?"
|
||||||
" AND groupmemberships.manifestid=manifests.id"
|
" AND GROUPMEMBERSHIPS.manifestid = MANIFESTS.id"
|
||||||
" AND groupmemberships.groupid=grouplist.id;",
|
" AND GROUPMEMBERSHIPS.groupid = GROUPLIST.id;",
|
||||||
fileid) == -1)
|
TEXT_TOUPPER, fileid, END) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if (highestPriority >= 0 && sqlite_exec_void_retry(&retry, "UPDATE files set highestPriority=%lld WHERE id='%s';", highestPriority, fileid) == -1)
|
if ( highestPriority >= 0
|
||||||
|
&& sqlite_exec_void_retry(&retry,
|
||||||
|
"UPDATE files SET highestPriority = ? WHERE id = ?;",
|
||||||
|
INT, highestPriority, TEXT_TOUPPER, fileid, END
|
||||||
|
) == -1
|
||||||
|
)
|
||||||
return WHYF("cannot update priority for fileid=%s", fileid);
|
return WHYF("cannot update priority for fileid=%s", fileid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1417,7 +1465,7 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found)
|
|||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
|
||||||
sqlite3_stmt *statement = sqlite_prepare(&retry, "%s", strbuf_str(b));
|
sqlite3_stmt *statement = sqlite_prepare(&retry, strbuf_str(b));
|
||||||
if (!statement)
|
if (!statement)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user