Add random UUID to Rhizome database

This commit is contained in:
Andrew Bettison 2013-11-12 18:14:14 +10:30
parent 50bbb722d0
commit 64db53a092
4 changed files with 69 additions and 17 deletions

View File

@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <sqlite3.h> #include <sqlite3.h>
#include <limits.h> #include <limits.h>
#include "sha2.h" #include "sha2.h"
#include "uuid.h"
#include "str.h" #include "str.h"
#include "strbuf.h" #include "strbuf.h"
#include "http_server.h" #include "http_server.h"
@ -405,6 +406,7 @@ int create_rhizome_datastore_dir();
#define FORM_RHIZOME_IMPORT_PATH(buf,fmt,...) (form_rhizome_import_path((buf), sizeof(buf), (fmt), ##__VA_ARGS__)) #define FORM_RHIZOME_IMPORT_PATH(buf,fmt,...) (form_rhizome_import_path((buf), sizeof(buf), (fmt), ##__VA_ARGS__))
extern sqlite3 *rhizome_db; extern sqlite3 *rhizome_db;
uuid_t rhizome_db_uuid;
int rhizome_opendb(); int rhizome_opendb();
int rhizome_close_db(); int rhizome_close_db();
@ -517,6 +519,7 @@ enum sqlbind_type {
TOHEX, // const unsigned char *binary, unsigned bytes TOHEX, // const unsigned char *binary, unsigned bytes
TEXT_TOUPPER, // const char *text, TEXT_TOUPPER, // const char *text,
TEXT_LEN_TOUPPER, // const char *text, unsigned bytes TEXT_LEN_TOUPPER, // const char *text, unsigned bytes
UUID_T, // const uuid_t *uuidp
NUL = 1 << 15, // NUL (no arg) ; NUL|INT, ... NUL = 1 << 15, // NUL (no arg) ; NUL|INT, ...
INDEX = 0xfade0000, // INDEX|INT, int index, ... INDEX = 0xfade0000, // INDEX|INT, int index, ...
NAMED = 0xdead0000 // NAMED|INT, const char *label, ... NAMED = 0xdead0000 // NAMED|INT, const char *label, ...

View File

@ -75,7 +75,8 @@ int create_rhizome_datastore_dir()
return emkdirs(rhizome_datastore_path(), 0700); return emkdirs(rhizome_datastore_path(), 0700);
} }
sqlite3 *rhizome_db=NULL; sqlite3 *rhizome_db = NULL;
uuid_t rhizome_db_uuid;
/* XXX Requires a messy join that might be slow. */ /* XXX Requires a messy join that might be slow. */
int rhizome_manifest_priority(sqlite_retry_state *retry, const rhizome_bid_t *bidp) int rhizome_manifest_priority(sqlite_retry_state *retry, const rhizome_bid_t *bidp)
@ -207,7 +208,10 @@ void verify_bundles(){
int rhizome_opendb() int rhizome_opendb()
{ {
if (rhizome_db) return 0; if (rhizome_db) {
assert(uuid_is_valid(&rhizome_db_uuid));
return 0;
}
IN(); IN();
@ -257,11 +261,9 @@ int rhizome_opendb()
) { ) {
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);", END); 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);", END); 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;", END); sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=1;", END);
} }
if (version<2){ if (version<2){
@ -273,26 +275,52 @@ int rhizome_opendb()
verify_bundles(); verify_bundles();
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=2;", END); 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);", END); 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;", END); 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;", END); 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;", END); sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=4;", END);
} }
if (version<5){
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE TABLE IF NOT EXISTS IDENTITY(uuid text not null); ", END);
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "PRAGMA user_version=5;", END);
}
char buf[UUID_STRLEN + 1];
int r = sqlite_exec_strbuf_retry(&retry, strbuf_local(buf, sizeof buf), "SELECT uuid from IDENTITY LIMIT 1;", END);
if (r == -1)
RETURN(-1);
if (r) {
if (!str_to_uuid(buf, &rhizome_db_uuid, NULL)) {
WHYF("IDENTITY table contains malformed UUID %s -- overwriting", alloca_str_toprint(buf));
if (uuid_generate_random(&rhizome_db_uuid) == -1)
RETURN(WHY("Cannot generate new UUID for Rhizome database"));
if (sqlite_exec_void_retry(&retry, "UPDATE IDENTITY SET uuid = ? LIMIT 1;", UUID_T, &rhizome_db_uuid, END) == -1)
RETURN(WHY("Failed to update new UUID in Rhizome database"));
if (config.debug.rhizome)
DEBUGF("Updated Rhizome database UUID to %s", alloca_uuid_str(rhizome_db_uuid));
}
} else if (r == 0) {
if (uuid_generate_random(&rhizome_db_uuid) == -1)
RETURN(WHY("Cannot generate UUID for Rhizome database"));
if (sqlite_exec_void_retry(&retry, "INSERT INTO IDENTITY (uuid) VALUES (?);", UUID_T, &rhizome_db_uuid, END) == -1)
RETURN(WHY("Failed to insert UUID into Rhizome database"));
if (config.debug.rhizome)
DEBUGF("Set Rhizome database UUID to %s", alloca_uuid_str(rhizome_db_uuid));
}
// TODO recreate tables with collate nocase on hex columns // TODO recreate tables with collate nocase on hex columns
/* Future schema updates should be performed here. /* Future schema updates should be performed here.
The above schema can be assumed to exist. The above schema can be assumed to exist.
All changes should attempt to preserve any existing data */ All changes should attempt to preserve any existing data */
// We can't delete a file that is being transferred in another process at this very moment... // We can't delete a file that is being transferred in another process at this very moment...
if (config.rhizome.clean_on_open) if (config.rhizome.clean_on_open)
rhizome_cleanup(NULL); rhizome_cleanup(NULL);
INFOF("Opened Rhizome database %s, UUID=%s", dbpath, alloca_uuid_str(rhizome_db_uuid));
RETURN(0); RETURN(0);
OUT(); OUT();
} }
@ -740,6 +768,19 @@ int _sqlite_vbind(struct __sourceloc __whence, int log_level, sqlite_retry_state
} }
} }
break; break;
case UUID_T: {
const uuid_t *uuidp = va_arg(ap, const uuid_t *);
++argnum;
if (uuidp == NULL) {
BIND_NULL(UUID_T);
} else {
char uuid_str[UUID_STRLEN + 1];
uuid_to_str(uuidp, uuid_str);
BIND_DEBUG(UUID_T, sqlite3_bind_text, "%s,%u,SQLITE_TRANSIENT", uuid_str, UUID_STRLEN);
BIND_RETRY(sqlite3_bind_text, uuid_str, UUID_STRLEN, SQLITE_TRANSIENT);
}
}
break;
#undef BIND_RETRY #undef BIND_RETRY
default: default:
FATALF("at bind arg %u, unsupported bind code typ=0x%08x: %s", argnum, typ, sqlite3_sql(statement)); FATALF("at bind arg %u, unsupported bind code typ=0x%08x: %s", argnum, typ, sqlite3_sql(statement));

17
uuid.c
View File

@ -66,23 +66,26 @@ int uuid_generate_random(uuid_t *uuid)
return 0; return 0;
} }
void uuid_to_str(const uuid_t *uuid, char *dst) char *uuid_to_str(const uuid_t *uuid, char *const dst)
{ {
char *p = dst;
assert(uuid_is_valid(uuid)); assert(uuid_is_valid(uuid));
unsigned i; unsigned i;
for (i = 0; i != sizeof uuid->u.binary; ++i) { for (i = 0; i != sizeof uuid->u.binary; ++i) {
switch (i) { switch (i) {
case 4: case 6: case 8: case 10: case 4: case 6: case 8: case 10:
*dst++ = '-'; *p++ = '-';
default: default:
*dst++ = hexdigit[uuid->u.binary[i] >> 4]; *p++ = hexdigit[uuid->u.binary[i] >> 4];
*dst++ = hexdigit[uuid->u.binary[i] & 0xf]; *p++ = hexdigit[uuid->u.binary[i] & 0xf];
} }
} }
*dst = '\0'; *p = '\0';
assert(p == dst + UUID_STRLEN);
return dst;
} }
int str_to_uuid(const char *str, uuid_t *uuid, const char **afterp) int str_to_uuid(const char *const str, uuid_t *uuid, const char **afterp)
{ {
const char *end = str; const char *end = str;
int ret = 0; int ret = 0;
@ -96,7 +99,7 @@ int str_to_uuid(const char *str, uuid_t *uuid, const char **afterp)
&& *end == '-' && *end == '-'
&& strn_fromhex(uuid->u.binary + 10, 6, end + 1, &end) == 6 && strn_fromhex(uuid->u.binary + 10, 6, end + 1, &end) == 6
) { ) {
assert(end == str + 36); assert(end == str + UUID_STRLEN);
ret = uuid_is_valid(uuid); ret = uuid_is_valid(uuid);
} }
if (afterp) if (afterp)

7
uuid.h
View File

@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define __SERVALDNA_UUID_H #define __SERVALDNA_UUID_H
#include <stdint.h> #include <stdint.h>
#include <alloca.h>
#ifndef __SERVALDNA_UUID_H_INLINE #ifndef __SERVALDNA_UUID_H_INLINE
# if __GNUC__ && !__GNUC_STDC_INLINE__ # if __GNUC__ && !__GNUC_STDC_INLINE__
@ -93,9 +94,13 @@ int uuid_generate_random(uuid_t *dest_uuid);
* are filled with the representation shown above, and the 37th byte dst[36] is * are filled with the representation shown above, and the 37th byte dst[36] is
* set to NUL '\0'. * set to NUL '\0'.
* *
* Returns the 'dst' argument.
*
* @author Andrew Bettison <andrew@servalproject.com> * @author Andrew Bettison <andrew@servalproject.com>
*/ */
void uuid_to_str(const uuid_t *valid_uuid, char *dst); char *uuid_to_str(const uuid_t *valid_uuid, char *dst);
#define UUID_STRLEN 36
#define alloca_uuid_str(uuid) uuid_to_str(&(uuid), alloca(UUID_STRLEN + 1))
/* Parse a canonical UUID string (as generated by uuid_to_str()) into a valid /* Parse a canonical UUID string (as generated by uuid_to_str()) into a valid
* UUID, which may or not be supported. * UUID, which may or not be supported.