int SLNFilterCopyURI(SLNFilterRef const filter, uint64_t const fileID, bool const meta, DB_txn *const txn, str_t **const out) { DB_val fileID_key[1], file_val[1]; SLNFileByIDKeyPack(fileID_key, txn, fileID); int rc = db_get(txn, fileID_key, file_val); if(rc < 0) return rc; strarg_t const hash = db_read_string(file_val, txn); db_assert(hash); str_t *URI = NULL; if(!meta) { URI = SLNFormatURI(SLN_INTERNAL_ALGO, hash); if(!URI) return DB_ENOMEM; } else { DB_val key[1], val[1]; SLNMetaFileByIDKeyPack(key, txn, fileID); rc = db_get(txn, key, val); if(rc < 0) return rc; uint64_t f; strarg_t target = NULL; SLNMetaFileByIDValUnpack(val, txn, &f, &target); db_assert(target); URI = aasprintf("hash://%s/%s -> %s", SLN_INTERNAL_ALGO, hash, target); if(!URI) return DB_ENOMEM; } *out = URI; URI = NULL; return 0; }
static uint64_t add_metafile(DB_txn *const txn, uint64_t const fileID, strarg_t const targetURI) { uint64_t const metaFileID = fileID; uint64_t const latestMetaFileID = db_next_id(SLNMetaFileByID, txn); if(metaFileID < latestMetaFileID) return 0; // If it's not a new file, then it's not a new meta-file. // Note that ordinary files can't be "promoted" to meta-files later // because that would break the ordering. DB_val null = { 0, NULL }; DB_cursor *cursor = NULL; int rc = db_txn_cursor(txn, &cursor); assert(rc >= 0); DB_val metaFileID_key[1]; SLNMetaFileByIDKeyPack(metaFileID_key, txn, metaFileID); DB_val metaFile_val[1]; SLNMetaFileByIDValPack(metaFile_val, txn, fileID, targetURI); rc = db_put(txn, metaFileID_key, metaFile_val, DB_NOOVERWRITE_FAST); assert(rc >= 0); DB_range alts[1]; SLNTargetURIAndMetaFileIDRange1(alts, txn, targetURI); rc = db_cursor_firstr(cursor, alts, NULL, NULL, +1); assert(rc >= 0 || DB_NOTFOUND == rc); if(DB_NOTFOUND == rc) { DB_val unique[1]; SLNFirstUniqueMetaFileIDKeyPack(unique, txn, metaFileID); rc = db_put(txn, unique, &null, DB_NOOVERWRITE_FAST); assert(rc >= 0); } DB_val targetURI_key[1]; SLNTargetURIAndMetaFileIDKeyPack(targetURI_key, txn, targetURI, metaFileID); rc = db_put(txn, targetURI_key, &null, DB_NOOVERWRITE_FAST); assert(rc >= 0); return metaFileID; }