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 SLNSessionGetFileInfo(SLNSessionRef const session, strarg_t const URI, SLNFileInfo *const info) { DB_env *db = NULL; int rc = SLNSessionDBOpen(session, SLN_RDONLY, &db); if(rc < 0) return rc; DB_txn *txn = NULL; rc = db_txn_begin(db, NULL, DB_RDONLY, &txn); if(rc < 0) { SLNSessionDBClose(session, &db); return rc; } DB_cursor *cursor; rc = db_txn_cursor(txn, &cursor); assert(!rc); DB_range fileIDs[1]; SLNURIAndFileIDRange1(fileIDs, txn, URI); DB_val URIAndFileID_key[1]; rc = db_cursor_firstr(cursor, fileIDs, URIAndFileID_key, NULL, +1); DB_val file_val[1]; if(rc >= 0) { strarg_t URI2; uint64_t fileID; SLNURIAndFileIDKeyUnpack(URIAndFileID_key, txn, &URI2, &fileID); assert(0 == strcmp(URI, URI2)); if(info) { DB_val fileID_key[1]; SLNFileByIDKeyPack(fileID_key, txn, fileID); rc = db_get(txn, fileID_key, file_val); } } if(rc < 0) { db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); return rc; } if(info) { // Clear padding for later assert_zeroed. memset(info, 0, sizeof(*info)); strarg_t const internalHash = db_read_string(file_val, txn); strarg_t const type = db_read_string(file_val, txn); uint64_t const size = db_read_uint64(file_val); info->hash = strdup(internalHash); info->path = SLNRepoCopyInternalPath(SLNSessionGetRepo(session), internalHash); info->type = strdup(type); info->size = size; if(!info->hash || !info->path || !info->type) { SLNFileInfoCleanup(info); db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); return DB_ENOMEM; } } db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); return 0; }
int SLNSubmissionStore(SLNSubmissionRef const sub, DB_txn *const txn) { assert(sub); assert(txn); assert(!sub->tmppath); // Session permissions were already checked when the sub was created. int64_t fileID = db_next_id(SLNFileByID, txn); int rc; DB_val dupFileID_val[1]; SLNFileIDByInfoValPack(dupFileID_val, txn, fileID); DB_val fileInfo_key[1]; SLNFileIDByInfoKeyPack(fileInfo_key, txn, sub->internalHash, sub->type); rc = db_put(txn, fileInfo_key, dupFileID_val, DB_NOOVERWRITE); if(rc >= 0) { DB_val fileID_key[1]; SLNFileByIDKeyPack(fileID_key, txn, fileID); DB_val file_val[1]; SLNFileByIDValPack(file_val, txn, sub->internalHash, sub->type, sub->size); rc = db_put(txn, fileID_key, file_val, DB_NOOVERWRITE_FAST); if(rc < 0) return rc; } else if(DB_KEYEXIST == rc) { fileID = db_read_uint64(dupFileID_val); } else return rc; for(size_t i = 0; sub->URIs[i]; ++i) { strarg_t const URI = sub->URIs[i]; DB_val null = { 0, NULL }; DB_val fwd[1]; SLNFileIDAndURIKeyPack(fwd, txn, fileID, URI); rc = db_put(txn, fwd, &null, DB_NOOVERWRITE_FAST); if(rc < 0 && DB_KEYEXIST != rc) return rc; DB_val rev[1]; SLNURIAndFileIDKeyPack(rev, txn, URI, fileID); rc = db_put(txn, rev, &null, DB_NOOVERWRITE_FAST); if(rc < 0 && DB_KEYEXIST != rc) return rc; } rc = SLNSubmissionParseMetaFile(sub, fileID, txn, &sub->metaFileID); if(rc < 0) { alogf("Submission meta-file error: %s\n", sln_strerror(rc)); return rc; } return 0; }