From 7cecdf7a3a971e21ee041e07606d9dd6644f184d Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Mon, 30 Dec 2013 14:56:08 +1030 Subject: [PATCH] Add Rhizome db blob primitive functions sqlite_blob_open_retry() sqlite_blob_write_retry() sqlite_blob_close() --- rhizome.h | 25 ++++++++++++++ rhizome_database.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/rhizome.h b/rhizome.h index 4f18fdbc..a60ce8e9 100644 --- a/rhizome.h +++ b/rhizome.h @@ -565,6 +565,27 @@ int _sqlite_exec_uint64_retry(struct __sourceloc, sqlite_retry_state *retry, uin 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 *sqltext, ...); int _sqlite_vexec_strbuf_retry(struct __sourceloc, sqlite_retry_state *retry, strbuf sb, const char *sqltext, va_list ap); +int _sqlite_blob_open_retry( + struct __sourceloc, + int log_level, + sqlite_retry_state *retry, + const char *dbname, + const char *tablename, + const char *colname, + sqlite3_int64 rowid, + int flags, + sqlite3_blob **blobp +); +int _sqlite_blob_write_retry( + struct __sourceloc, + int log_level, + sqlite_retry_state *retry, + sqlite3_blob *blob, + const void *buf, + int len, + int offset +); +int _sqlite_blob_close(struct __sourceloc, int log_level, sqlite3_blob *blob); // The 'arg' arguments in the following macros appear to be unnecessary, but // they serve a very useful purpose, so don't remove them! They ensure that @@ -591,6 +612,10 @@ int _sqlite_vexec_strbuf_retry(struct __sourceloc, sqlite_retry_state *retry, st #define sqlite_exec_uint64_retry(rs,res,sql,arg,...) _sqlite_exec_uint64_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__) +#define sqlite_blob_open_retry(rs,db,table,col,row,flags,blobp) \ + _sqlite_blob_open_retry(__WHENCE__, LOG_LEVEL_ERROR, (rs), (db), (table), (col), (row), (flags), (blobp)) +#define sqlite_blob_close(blob) _sqlite_blob_close(__WHENCE__, LOG_LEVEL_ERROR, (blob)); +#define sqlite_blob_write_retry(rs,blob,buf,siz,off) _sqlite_blob_write_retry(__WHENCE__, LOG_LEVEL_ERROR, (rs), (blob), (buf), (siz), (off)) double rhizome_manifest_get_double(rhizome_manifest *m,char *var,double default_value); int rhizome_manifest_extract_signature(rhizome_manifest *m, unsigned *ofs); diff --git a/rhizome_database.c b/rhizome_database.c index 7bc6a03c..fbf0dfd5 100644 --- a/rhizome_database.c +++ b/rhizome_database.c @@ -1075,6 +1075,88 @@ int _sqlite_vexec_strbuf_retry(struct __sourceloc __whence, sqlite_retry_state * return sqlite_code_ok(stepcode) && ret != -1 ? rowcount : -1; } +int _sqlite_blob_open_retry( + struct __sourceloc __whence, + int log_level, + sqlite_retry_state *retry, + const char *dbname, + const char *tablename, + const char *colname, + sqlite3_int64 rowid, + int flags, + sqlite3_blob **blobp +) +{ + IN(); + while (1) { + int code = sqlite3_blob_open(rhizome_db, dbname, tablename, colname, rowid, flags, blobp); + switch (code) { + case SQLITE_OK: + if (retry) + _sqlite_retry_done(__whence, retry, "sqlite3_blob_open()"); + RETURN(code); + case SQLITE_DONE: + case SQLITE_ROW: + LOGF(log_level, "sqlite3_blob_open() returned unexpected code (%d)", code); + RETURN(-1); + case SQLITE_BUSY: + case SQLITE_LOCKED: + if (retry && _sqlite_retry(__whence, retry, "sqlite3_blob_open()")) + break; // back to sqlite3_blob_open() + // fall through... + default: + LOGF(log_level, "sqlite3_blob_open() failed (%d), %s", code, sqlite3_errmsg(rhizome_db)); + RETURN(-1); + } + } + FATAL("not reached"); + OUT(); +} + +int _sqlite_blob_write_retry( + struct __sourceloc __whence, + int log_level, + sqlite_retry_state *retry, + sqlite3_blob *blob, + const void *buf, + int len, + int offset +) +{ + IN(); + while (1) { + int code = sqlite3_blob_write(blob, buf, len, offset); + switch (code) { + case SQLITE_OK: + if (retry) + _sqlite_retry_done(__whence, retry, "sqlite3_blob_write()"); + RETURN(code); + case SQLITE_DONE: + case SQLITE_ROW: + LOGF(log_level, "sqlite3_blob_write() returned unexpected code (%d)", code); + RETURN(-1); + case SQLITE_BUSY: + case SQLITE_LOCKED: + if (retry && _sqlite_retry(__whence, retry, "sqlite3_blob_write()")) + break; // back to sqlite3_blob_open() + // fall through... + default: + LOGF(log_level, "sqlite3_blob_write() failed (%d), %s", code, sqlite3_errmsg(rhizome_db)); + RETURN(-1); + } + } + FATAL("not reached"); + OUT(); +} + +int _sqlite_blob_close(struct __sourceloc __whence, int log_level, sqlite3_blob *blob) +{ + int code = sqlite3_blob_close(blob); + if (code != SQLITE_OK) + LOGF(log_level, "sqlite3_blob_close() failed: %s", sqlite3_errmsg(rhizome_db)); + return 0; +} + static uint64_t rhizome_database_used_bytes() { uint64_t db_page_size;