int db_schema_verify(DB_txn *const txn) { char const magic[] = "DBDB schema layer v1"; size_t const len = sizeof(magic)-1; DB_val key[1]; DB_VAL_STORAGE(key, DB_VARINT_MAX*2); db_bind_uint64(key, DBSchema); db_bind_uint64(key, 0); DB_val val[1]; DB_cursor *cur; int rc = db_txn_cursor(txn, &cur); if(rc < 0) return rc; rc = db_cursor_first(cur, NULL, NULL, +1); if(rc < 0 && DB_NOTFOUND != rc) return rc; // If the database is completely empty // we can assume it's ours to play with if(DB_NOTFOUND == rc) { *val = (DB_val){ len, (char *)magic }; rc = db_put(txn, key, val, 0); if(rc < 0) return rc; return 0; } rc = db_get(txn, key, val); if(DB_NOTFOUND == rc) return DB_VERSION_MISMATCH; if(rc < 0) return rc; if(len != val->size) return DB_VERSION_MISMATCH; if(0 != memcmp(val->data, magic, len)) return DB_VERSION_MISMATCH; return 0; }
uint64_t db_next_id(dbid_t const table, DB_txn *const txn) { DB_cursor *cur = NULL; if(db_txn_cursor(txn, &cur) < 0) return 0; DB_range range[1]; DB_RANGE_STORAGE(range, DB_VARINT_MAX); db_bind_uint64(range->min, table+0); db_bind_uint64(range->max, table+1); DB_val prev[1]; int rc = db_cursor_firstr(cur, range, prev, NULL, -1); if(DB_NOTFOUND == rc) return 1; if(rc < 0) return 0; uint64_t const t = db_read_uint64(prev); assert(table == t); return db_read_uint64(prev)+1; }
int SLNSessionCopyLastSubmissionURIs(SLNSessionRef const session, str_t *const outFileURI, str_t *const outMetaURI) { DB_env *db = NULL; DB_txn *txn = NULL; int rc = SLNSessionDBOpen(session, SLN_RDWR, &db); if(rc < 0) goto cleanup; rc = db_txn_begin(db, NULL, DB_RDONLY, &txn); if(rc < 0) goto cleanup; if(outFileURI) { DB_val key[1], val[1]; DB_VAL_STORAGE(key, DB_VARINT_MAX*2); db_bind_uint64(key, SLNLastFileURIBySessionID); db_bind_uint64(key, session->sessionID); DB_VAL_STORAGE_VERIFY(key); rc = db_get(txn, key, val); if(rc >= 0) { strarg_t const URI = db_read_string(val, txn); strlcpy(outFileURI, URI, SLN_URI_MAX); } else if(DB_NOTFOUND == rc) { outFileURI[0] = '\0'; rc = 0; } else { goto cleanup; } } if(outMetaURI) { DB_val key[1], val[1]; DB_VAL_STORAGE(key, DB_VARINT_MAX*2); db_bind_uint64(key, SLNLastMetaURIBySessionID); db_bind_uint64(key, session->sessionID); DB_VAL_STORAGE_VERIFY(key); rc = db_get(txn, key, val); if(rc >= 0) { strarg_t const URI = db_read_string(val, txn); strlcpy(outMetaURI, URI, SLN_URI_MAX); } else if(DB_NOTFOUND == rc) { outMetaURI[0] = '\0'; rc = 0; } else { goto cleanup; } } cleanup: db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); return rc; }