list.name = (char *)names[i];
list.desc = (char *)descs[i];
- if (tmp = dblist_add(tx, db, &list)) {
+ if ((tmp = dblist_add(tx, db, &list))) {
if (tmp == MDB_KEYEXIST)
db->listid = find_next_id(tx, db->list);
else {
db = NULL;
}
- printf("index open: disk.id=%d list.id=%d file.id=%d\n", db->diskid, db->listid, db->fileid);
+ printf("index open: '%s' disk.id=%d list.id=%d file.id=%d\n", path, db->diskid, db->listid, db->fileid);
free(dpath);
return db;
MDB_val key, data;
int res;
- if (res = mdb_cursor_open(tx, secondary, &cursor))
+ if ((res = mdb_cursor_open(tx, secondary, &cursor)))
return res;
int op = MDB_FIRST;
return res;
}
-static int secondary_list_key(dbtxn *tx, MDB_dbi secondary, MDB_val key, ez_array *array) {
+static int secondary_list_key(dbtxn *tx, MDB_dbi secondary, MDB_val *key, ez_array *array) {
MDB_cursor *cursor;
MDB_val data;
int res;
- if (res = mdb_cursor_open(tx, secondary, &cursor))
+ if ((res = mdb_cursor_open(tx, secondary, &cursor)))
return res;
int op = MDB_SET_KEY;
- while ((res = mdb_cursor_get(cursor, &key, &data, op)) == 0) {
+ while ((res = mdb_cursor_get(cursor, key, &data, op)) == 0) {
if (!ez_array_add(array, data.mv_data, data.mv_size)) {
res = ENOMEM;
break;
ez_array_clear(array);
}
- printf("secondary list all: %s\n", mdb_strerror(res));
+ printf("secondary list key: %s\n", mdb_strerror(res));
mdb_cursor_close(cursor);
return res;
}
-
-// merge/replace with above?
-static uint32_t *scan_all(dbscan *scan, ssize_t *sizep) {
- int fid;
- int fids_size = 4096;
- int count = 0;
- uint32_t *fids = malloc(sizeof(*fids) * fids_size);
-
- if (!fids)
- goto fail;
-
- while ((fid = dbfile_scan_next(scan)) != ~0) {
- if (count >= fids_size) {
- uint32_t *tmp;
-
- fids_size *= 2;
- tmp = realloc(fids, sizeof(*fids) * fids_size);
- if (!tmp)
- goto fail;
- fids = tmp;
- }
- fids[count++] = fid;
- }
-
- *sizep = count;
- return fids;
-fail:
- free(fids);
- *sizep = -1;
- return NULL;
-}
-
int dbdisk_del(dbtxn *tx, dbindex *db, dbdisk *disk) {
- dbscan *scan = dbfile_scan_disk(tx, db, disk->id);
- uint32_t *fids = NULL;
- ssize_t count;
+ MDB_val key;
+ ez_array array = { 0 };
int res = 0;
- fids = scan_all(scan, &count);
- if (count == -1) {
- res = ENOMEM;
+ key.mv_data = &disk->id;
+ key.mv_size = sizeof(disk->id);
+ if ((res = secondary_list_key(tx, db->file_by_disk, &key, &array)))
goto fail;
- }
+
+ dbid_t *fids = array.ea_data;
+ size_t count = array.ea_size / sizeof(*fids);
for (int i=0;i<count;i++) {
printf(" file %d\n", fids[i]);
- if (res = dbfile_del_id(tx, db, fids[i]))
+ if ((res = dbfile_del_id(tx, db, fids[i])))
goto fail;
}
// secondary keys
- MDB_val key;
// -- by uuid
key.mv_data = disk->uuid;
key.mv_size = strlen(disk->uuid);
- if (res = mdb_del(tx, db->disk_by_uuid, &key, NULL))
+ if ((res = mdb_del(tx, db->disk_by_uuid, &key, NULL)))
goto fail;
// Remove disk
res = mdb_del(tx, db->disk, &key, NULL);
fail:
- free(fids);
+ ez_array_clear(&array);
return res;
}
if (!file->full_path) {
dbdisk *disk = dbdisk_get(tx, db, file->diskid);
- if (file->full_path = malloc(strlen(disk->mount) + strlen(file->path) + 1))
+ if ((file->full_path = malloc(strlen(disk->mount) + strlen(file->path) + 1)))
sprintf(file->full_path, "%s%s", disk->mount, file->path);
dbdisk_free(disk);
if ((db->res = mdb_cursor_open(tx, db->list_by_file, &cursor)))
goto fail1;
- if (db->res = mdb_cursor_get(cursor, &key, &dat, MDB_GET_BOTH_RANGE))
+ if ((db->res = mdb_cursor_get(cursor, &key, &dat, MDB_GET_BOTH_RANGE)))
goto fail;
is = ((struct dblistfile *)dat.mv_data)->listid == listid;
key.mv_data = dpath;
key.mv_size = strlen(dpath);
- if (res = mdb_del(tx, db->file_by_path, &key, NULL))
+ if ((res = mdb_del(tx, db->file_by_path, &key, &dat)))
goto fail;
// - by disk+dir
goto fail;
}
key.mv_size = tmp - dpath;
- if (res = mdb_del(tx, db->file_by_dir, &key, NULL))
+ if ((res = mdb_del(tx, db->file_by_dir, &key, &dat))) {
+ printf("fail: file_by_dir\n");
goto fail;
+ }
// - by diskid
key.mv_data = &f->diskid;
key.mv_size = sizeof(f->diskid);
- if (res = mdb_del(tx, db->file_by_disk, &key, &dat))
+ if ((res = mdb_del(tx, db->file_by_disk, &key, &dat))) {
+ printf("fail: file_by_disk\n");
goto fail;
+ }
// - by title
if (f->title) {
key.mv_data = f->title;
key.mv_size = strlen(f->title);
- if (res = mdb_del(tx, db->file_by_title, &key, &dat))
+ if ((res = mdb_del(tx, db->file_by_title, &key, &dat))) {
+ printf("fail: file_by_title\n");
goto fail;
+ }
}
// - by artist
if (f->artist) {
key.mv_data = f->artist;
key.mv_size = strlen(f->artist);
- if (res = mdb_del(tx, db->file_by_artist, &key, &dat))
+ if ((res = mdb_del(tx, db->file_by_artist, &key, &dat))) {
+ printf("fail: file_by_artist\n");
goto fail;
+ }
}
// Remove file
key.mv_data = &f->id;
key.mv_size = sizeof(f->id);
- if (res = mdb_del(tx, db->file, &key, NULL))
+ if ((res = mdb_del(tx, db->file, &key, NULL))) {
+ printf("fail: file\n");
goto fail;
+ }
// check lists, FIXME: cleanup
{
goto fail1;
res = mdb_cursor_get(cursor, &key, &dat, MDB_SET);
+ if (res == MDB_NOTFOUND) {
+ res = 0;
+ goto fail2;
+ }
while (res == 0) {
if (ez_array_add(&array, dat.mv_data, dat.mv_size))
res = mdb_cursor_get(cursor, &key, &dat, MDB_NEXT_DUP);
else
res = ENOMEM;
}
- printf("get list contents: res=%d\n", res);
+ printf("get list contents: res=%s\n", mdb_strerror(res));
mdb_cursor_close(cursor);
if (res != MDB_NOTFOUND)
- goto fail1;
+ goto fail2;
// delete the entry we just read
- if (res = mdb_del(tx, db->list_by_file, &key, NULL))
- goto fail1;
+ if ((res = mdb_del(tx, db->list_by_file, &key, NULL)))
+ goto fail2;
struct dblistfile *files = array.ea_data;
int count = array.ea_size / sizeof(*files);
key.mv_size = sizeof(files[i].listid);
dat.mv_data = &fdata;
dat.mv_size = sizeof(fdata);
- if (res = mdb_del(tx, db->file_by_list, &key, &dat))
- goto fail1;
+ if ((res = mdb_del(tx, db->file_by_list, &key, &dat)))
+ goto fail2;
}
// update all the list counts
struct hist_node hk = { .key = files[i].listid };
struct hist_node *hn;
- if (hn = ez_set_get(&counts, &hk))
+ if ((hn = ez_set_get(&counts, &hk)))
hn->count += 1;
- else if (hn = malloc(sizeof(*hn))) {
+ else if ((hn = malloc(sizeof(*hn)))) {
hn->key = hk.key;
hn->count = 1;
ez_set_put(&counts, hn);
ez_set_clear(&counts);
fail2:
-
+ mdb_cursor_close(cursor);
fail1:
ez_array_clear(&array);
}
if (o->artist) {
key.mv_data = o->artist;
key.mv_size = strlen(o->artist);
- if (res = mdb_del(tx, db->file_by_artist, &key, &data))
+ if ((res = mdb_del(tx, db->file_by_artist, &key, &data)))
goto fail;
}
if (f->artist) {
key.mv_data = f->artist;
key.mv_size = strlen(f->artist);
- if (res = mdb_put(tx, db->file_by_artist, &key, &data, 0))
+ if ((res = mdb_put(tx, db->file_by_artist, &key, &data, 0)))
goto fail;
}
}
if (o->title) {
key.mv_data = o->title;
key.mv_size = strlen(o->title);
- if (res = mdb_del(tx, db->file_by_title, &key, &data))
+ if ((res = mdb_del(tx, db->file_by_title, &key, &data)))
goto fail;
}
if (f->title) {
key.mv_data = f->title;
key.mv_size = strlen(f->title);
- if (res = mdb_put(tx, db->file_by_title, &key, &data, 0))
+ if ((res = mdb_put(tx, db->file_by_title, &key, &data, 0)))
goto fail;
}
}
key.mv_size = sizeof(f->id);
data.mv_size = ez_basic_size(DBFILE_DESC, f);
- if (res = mdb_put(tx, db->file, &key, &data, MDB_RESERVE))
+ if ((res = mdb_put(tx, db->file, &key, &data, MDB_RESERVE)))
goto fail;
ez_basic_encode_raw(DBFILE_DESC, f, (ez_blob *)&data);
dpath = dbfile_path(f);
key.mv_data = dpath;
key.mv_size = strlen(dpath);
- if (res = mdb_put(tx, db->file_by_path, &key, &data, MDB_NOOVERWRITE)) {
+ if ((res = mdb_put(tx, db->file_by_path, &key, &data, MDB_NOOVERWRITE))) {
fprintf(stderr, "UNIQUE: path on this disk exists\n");
goto fail;
}
goto fail;
}
key.mv_size = tmp - dpath;
- if (res = mdb_put(tx, db->file_by_dir, &key, &data, MDB_NODUPDATA)) {
+ if ((res = mdb_put(tx, db->file_by_dir, &key, &data, MDB_NODUPDATA))) {
fprintf(stderr, "UNIQUE: file on this path exists\n");
goto fail;
}
// - by diskid
key.mv_data = &f->diskid;
key.mv_size = sizeof(f->diskid);
- if (res = mdb_put(tx, db->file_by_disk, &key, &data, 0))
+ if ((res = mdb_put(tx, db->file_by_disk, &key, &data, 0)))
goto fail;
// - by title
if (f->title) {
key.mv_data = f->title;
key.mv_size = strlen(f->title);
- if (res = mdb_put(tx, db->file_by_title, &key, &data, 0))
+ if ((res = mdb_put(tx, db->file_by_title, &key, &data, 0)))
goto fail;
}
if (f->artist) {
key.mv_data = f->artist;
key.mv_size = strlen(f->artist);
- if (res = mdb_put(tx, db->file_by_artist, &key, &data, 0))
+ if ((res = mdb_put(tx, db->file_by_artist, &key, &data, 0)))
goto fail;
}
MDB_val dat = { .mv_data = NULL, .mv_size = ez_basic_size(DBLIST_DESC, list) };
int res;
- if (res = mdb_put(tx, db->list, &key, &dat, flags | MDB_RESERVE))
+ if ((res = mdb_put(tx, db->list, &key, &dat, flags | MDB_RESERVE)))
return res;
ez_basic_encode_raw(DBLIST_DESC, list, (ez_blob *)&dat);
// Store record
list->id = list_next_id(db);
- if (res = dblist_put(tx, db, list, MDB_NOOVERWRITE))
+ if ((res = dblist_put(tx, db, list, MDB_NOOVERWRITE)))
goto fail;
// secondary keys
// - by name
key.mv_data = list->name;
key.mv_size = strlen(list->name);
- if (res = mdb_put(tx, db->list_by_name, &key, &dat, MDB_NOOVERWRITE))
+ if ((res = mdb_put(tx, db->list_by_name, &key, &dat, MDB_NOOVERWRITE)))
goto fail;
return mdb_txn_commit(tx);
key.mv_data = &listid;
key.mv_size = sizeof(listid);
- res = secondary_list_key(tx, db->file_by_list, key, &array);
+ res = secondary_list_key(tx, db->file_by_list, &key, &array);
list = array.ea_data;
count = array.ea_size / sizeof(*list);
if (count) {
// delete list values
key.mv_data = &listid;
key.mv_size = sizeof(listid);
- if (res = mdb_del(tx, db->file_by_list, &key, NULL)) {
+ if ((res = mdb_del(tx, db->file_by_list, &key, NULL))) {
printf(" delete list fail\n");
goto fail;
}
entry.seq = list[i].seq;
- if (res = mdb_del(tx, db->list_by_file, &key, &data)) {
+ if ((res = mdb_del(tx, db->list_by_file, &key, &data))) {
printf(" delete fail fid=%d -> list=%d seq=%d\n", list[i].fileid, entry.listid, entry.seq);
if (res == MDB_NOTFOUND) {
printf(" db inconsistent, continuing\n");
key.mv_data = &listid;
key.mv_size = sizeof(listid);
- if (res = mdb_del(tx, db->list, &key, NULL))
+ if ((res = mdb_del(tx, db->list, &key, NULL)))
goto fail;
- if (res = mdb_del(tx, db->file_by_list, &key, NULL))
+ if ((res = mdb_del(tx, db->file_by_list, &key, NULL)))
goto fail;
res = mdb_cursor_open(tx, db->list_by_file, &cursor);
if (value->listid == listid) {
printf("delete\n");
- if (res = mdb_cursor_del(cursor, 0))
+ if ((res = mdb_cursor_del(cursor, 0)))
goto fail;
res = mdb_cursor_get(cursor, &key, &data, MDB_GET_CURRENT);
} else {
list.name = (char *)names[i];
list.desc = (char *)descs[i];
- if (tmp = dblist_add(tx, db, &list)) {
+ if ((tmp = dblist_add(tx, db, &list))) {
if (tmp == MDB_KEYEXIST)
db->listid = find_next_id(tx, db->list);
else
dbid_t *fids = NULL;
ez_array array = { 0 };
- if (res = secondary_list_all(tx, db->file_by_path, &array))
+ if ((res = secondary_list_all(tx, db->file_by_path, &array)))
goto fail;
fids = array.ea_data;
count = array.ea_size / sizeof(*fids);
// Create the all list
- if (res = dblist_update(tx, db, "all", fids, count))
+ if ((res = dblist_update(tx, db, "all", fids, count)))
goto fail;
// Create the all shuffled list
printf("list_del_file: lid=%4d seq=%4d fid=%4d\n", list->listid, list->seq, list->fileid);
- if (res = mdb_txn_begin(db->env, txn, 0, &tx))
+ if ((res = mdb_txn_begin(db->env, txn, 0, &tx)))
goto fail0;
int delcursor = 0;
if (list->seq == 0) {
// No sequence, lookup (first) fileid for the list
- if (res = mdb_cursor_open(tx, db->list_by_file, &cursor))
+ if ((res = mdb_cursor_open(tx, db->list_by_file, &cursor)))
goto fail;
key.mv_data = &list->fileid;
data.mv_data = &rvalue;
data.mv_size = sizeof(rvalue);
- if (res = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH_RANGE))
+ if ((res = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH_RANGE)))
goto fail;
fvalue.seq = list->seq = ((struct dblistfile *)data.mv_data)->seq;
delfile = 1;
} else if (list->fileid == 0) {
// Lookup fileid for list[seq]
- if (res = mdb_cursor_open(tx, db->file_by_list, &cursor))
+ if ((res = mdb_cursor_open(tx, db->file_by_list, &cursor)))
goto fail;
key.mv_data = &list->listid;
data.mv_data = &fvalue;
data.mv_size = sizeof(fvalue);
- if (res = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH))
+ if ((res = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH)))
goto fail;
list->fileid = ((struct dbfilelist *)data.mv_data)->fileid;
data.mv_data = &fvalue;
data.mv_size = sizeof(fvalue);
- if (res = mdb_del(tx, db->file_by_list, &key, &data))
+ if ((res = mdb_del(tx, db->file_by_list, &key, &data)))
goto fail;
}
data.mv_data = &rvalue;
data.mv_size = sizeof(rvalue);
- if (res = mdb_del(tx, db->list_by_file, &key, &data))
+ if ((res = mdb_del(tx, db->list_by_file, &key, &data)))
goto fail;
}
}
}
+/* new dbscan version for for loops*/
+// for (foo = dbscan_foo(); foo; foo = dbscan_foo_next()) {
+// }
+// dbscan_free();
+static void *dbscan_decode(dbscan *scan) {
+ void *memory = calloc(scan->DESC->bd_offset, 1);
-
-
-/* scan tables with int keys */
-// TBD
-static dbscan *dbscan_secondary(dbtxn *tx, dbindex *db, MDB_dbi table, int diskid) {
- dbscan *scan = calloc(1, sizeof(*scan));
- int res;
-
- scan->db = db;
- scan->table = table;
-
- scan->cursor = NULL;
-
- scan->keyval = diskid;
- scan->key.mv_data = &scan->keyval;
- scan->key.mv_size = sizeof(scan->keyval);
-
- if ((res = mdb_cursor_open(tx, table, &scan->cursor)))
- goto fail;
-
- if (diskid != -1)
- res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_SET);
- else
- res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_FIRST);
-
- if (res) {
- if (res == MDB_NOTFOUND) {
- scan->count = 0;
- scan->index = 0;
- return scan;
- }
- goto fail;
+ if (memory) {
+ scan->decode_raw((const ez_blob *)&scan->dat, memory);
+ *(dbid_t *)memory = *(dbid_t *)scan->key.mv_data;
+ } else {
+ scan->res = ENOMEM;
}
- if ((res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_GET_MULTIPLE)))
- goto fail;
-
- scan->count = scan->data.mv_size / sizeof(int);
- scan->index = 0;
-
- return scan;
-
- fail:
- fprintf(stderr, "db scan open fail: %s\n", mdb_strerror(res));
- dbfile_scan_close(scan);
- return NULL;
+ return memory;
}
-// TBD
-static uint32_t dbscan_secondary_next(dbscan *scan) {
- int res = 0;
-
- while (scan->count > 0) {
- if (scan->index < scan->count)
- return ((uint32_t *)scan->data.mv_data)[scan->index++];
-
- if (res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_NEXT_MULTIPLE)) {
- if (res == MDB_NOTFOUND && scan->keyval == -1) {
- res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_NEXT);
- if (res == 0)
- res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_GET_MULTIPLE);
- }
- if (res)
- goto fail;
- }
-
- scan->count = scan->data.mv_size / sizeof(uint32_t);
- scan->index = 0;
- }
-
- return ~0;
- fail:
- if (res != MDB_NOTFOUND)
- fprintf(stderr, "db scan fail: %s\n", mdb_strerror(res));
- return ~0;
+void dbscan_free(dbscan *scan) {
+ if (scan->cursor)
+ mdb_cursor_close(scan->cursor);
+ memset(scan, 0, sizeof(*scan));
}
-static dbscan *dbscan_primary(dbtxn *tx, dbindex *db, MDB_dbi table, int diskid) {
- dbscan *scan = calloc(1, sizeof(*scan));
- int res;
-
- scan->db = db;
- scan->table = table;
-
- scan->keyval = diskid;
- scan->key.mv_data = &scan->keyval;
- scan->key.mv_size = sizeof(scan->keyval);
+static void *dbscan_primary_first(dbtxn *tx, dbscan *scan, dbindex *db, MDB_dbi primary, ez_blob_desc *desc, void (*decode_raw)(const ez_blob *blob, void *p), MDB_cursor_op first) {
+ scan->tx = tx;
+ scan->primary = primary;
+ scan->DESC = desc;
+ scan->decode_raw = decode_raw;
+ scan->mode = 0;
- if ((res = mdb_cursor_open(tx, table, &scan->cursor))) {
- printf("cursor open failed for table %d\n", table);
+ if ((scan->res = mdb_cursor_open(tx, primary, &scan->cursor)))
goto fail;
- }
-
- if (diskid != -1)
- res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_SET);
- else
- res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_FIRST);
-
- if (res) {
- if (res == MDB_NOTFOUND) {
- scan->count = 0;
- scan->index = 0;
- return scan;
- }
+ if ((scan->res = mdb_cursor_get(scan->cursor, &scan->key, &scan->dat, first)))
goto fail;
- }
-
- scan->count = 1;
- scan->index = 0;
-
- return scan;
- fail:
- fprintf(stderr, "dbscan_primary fail: %s\n", mdb_strerror(res));
- dbfile_scan_close(scan);
+ return dbscan_decode(scan);
+fail:
return NULL;
}
-// return 1 if there's a value
-static int dbscan_primary_next(dbscan *scan) {
- int res = 0;
-
- while (scan->count > 0) {
- if (scan->index == 0) {
- scan->index += 1;
- return 1;
- }
-
- if (res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_NEXT))
- goto fail;
-
- scan->count = 1;
- scan->index = 0;
- }
-
- return 0;
- fail:
- if (res != MDB_NOTFOUND)
- fprintf(stderr, "db scan fail: %s\n", mdb_strerror(res));
- return 0;
-}
-
-void dbscan_close(dbscan *scan) {
- if (scan->cursor)
- mdb_cursor_close(scan->cursor);
- free(scan);
-}
-
-
-/* new dbscan version */
-/* copy libeze mode, return on init, next/prev calls */
-
-static __inline__ int dbscan_init(dbtxn *tx, dbscan *scan, dbindex *db, MDB_dbi primary, ez_blob_desc *desc, void (*decode_raw)(const ez_blob *blob, void *p)) {
- scan->db = db;
- scan->primary = primary;
+static void *dbscan_secondary_first(dbtxn *tx, dbscan *scan, dbindex *db, MDB_dbi primary, MDB_dbi secondary, ez_blob_desc *desc, void (*decode_raw)(const ez_blob *blob, void *p), MDB_cursor_op first) {
scan->tx = tx;
+ scan->primary = primary;
scan->DESC = desc;
scan->decode_raw = decode_raw;
+ scan->mode = 1;
- scan->res = mdb_cursor_open(tx, primary, &scan->cursor);
-
- return scan->res;
-}
-
-static __inline__ void dbscan_init_key(dbscan *scan, dbid_t keyid) {
- scan->keyid = keyid;
- scan->key.mv_data = &scan->keyid;
- scan->key.mv_size = sizeof(scan->keyid);
-}
-
-static void *dbscan_decode(dbscan *scan) {
- void *memory = calloc(scan->DESC->bd_offset, 1);
-
- if (memory) {
- scan->decode_raw((const ez_blob *)&scan->data, memory);
- *(dbid_t *)memory = *(dbid_t *)scan->key.mv_data;
- }
- return memory;
-}
-
-static void dbscan_close2(dbscan *scan) {
- if (scan->cursor)
- mdb_cursor_close(scan->cursor);
- memset(scan, 0, sizeof(*scan));
-}
-
-void dbscan_free(dbscan *scan) {
- dbscan_close2(scan);
-}
+ if ((scan->res = mdb_cursor_open(tx, secondary, &scan->cursor)))
+ goto fail;
+ if ((scan->res = mdb_cursor_get(scan->cursor, &scan->key, &scan->dat, first)))
+ goto fail;
+ scan->key = scan->dat;
+ if ((scan->res = mdb_get(tx, primary, &scan->key, &scan->dat)))
+ goto fail;
-static void *dbscan_primary2(dbtxn *tx, dbscan *scan, dbindex *db, MDB_dbi primary, ez_blob_desc *desc, void (*decode_raw)(const ez_blob *blob, void *p), dbid_t keyid, MDB_cursor_op op) {
- if (dbscan_init(tx, scan, db, primary, desc, decode_raw) == 0) {
- dbscan_init_key(scan, keyid);
- if ((scan->res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, op)) == 0)
- return dbscan_decode(scan);
- dbscan_close2(scan);
- }
+ return dbscan_decode(scan);
+fail:
return NULL;
}
-static void *dbscan_primary2_next(dbscan *scan) {
- if ((scan->res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_NEXT)) == 0)
- return dbscan_decode(scan);
+static void *dbscan_table_next(dbscan *scan) {
+ if (scan->mode == 0) {
+ if ((scan->res = mdb_cursor_get(scan->cursor, &scan->key, &scan->dat, MDB_NEXT)))
+ goto fail;
+ } else {
+ if ((scan->res = mdb_cursor_get(scan->cursor, &scan->key, &scan->dat, MDB_NEXT_DUP)))
+ goto fail;
+ scan->key = scan->dat;
+ if ((scan->res = mdb_get(scan->tx, scan->primary, &scan->key, &scan->dat)))
+ goto fail;
+ }
+ return dbscan_decode(scan);
+fail:
return NULL;
}
dbdisk *dbscan_disk(dbtxn *tx, dbscan *scan, dbindex *db, dbid_t diskid) {
- return dbscan_primary2(tx, scan, db, db->disk, DBDISK_DESC, dbdisk_decode_raw, diskid, diskid == 0 ? MDB_FIRST : MDB_SET_RANGE);
+ scan->key.mv_data = &diskid;
+ scan->key.mv_size = sizeof(diskid);
+ return dbscan_primary_first(tx, scan, db, db->disk, DBDISK_DESC, dbdisk_decode_raw, diskid == 0 ? MDB_FIRST : MDB_SET_RANGE);
}
dbdisk *dbscan_disk_next(dbscan *scan) {
- return dbscan_primary2_next(scan);
+ return dbscan_table_next(scan);
}
dbfile *dbscan_file(dbtxn *tx, dbscan *scan, dbindex *db, dbid_t fileid) {
- return dbscan_primary2(tx, scan, db, db->file, DBFILE_DESC, dbfile_decode_raw, fileid, fileid == 0 ? MDB_FIRST : MDB_SET_RANGE);
+ scan->key.mv_data = &fileid;
+ scan->key.mv_size = sizeof(fileid);
+ return dbscan_primary_first(tx, scan, db, db->file, DBFILE_DESC, dbfile_decode_raw, fileid == 0 ? MDB_FIRST : MDB_SET_RANGE);
+}
+
+dbfile *dbscan_file_by_disk(dbtxn *tx, dbscan *scan, dbindex *db, dbid_t diskid) {
+ scan->key.mv_data = &diskid;
+ scan->key.mv_size = sizeof(diskid);
+ return dbscan_secondary_first(tx, scan, db, db->file, db->file_by_disk, DBFILE_DESC, dbfile_decode_raw, MDB_SET);
}
dbfile *dbscan_file_next(dbscan *scan) {
- return dbscan_primary2_next(scan);
+ return dbscan_table_next(scan);
}
dblist *dbscan_list(dbtxn *tx, dbscan *scan, dbindex *db, dbid_t listid) {
- return dbscan_primary2(tx, scan, db, db->list, DBLIST_DESC, dblist_decode_raw, listid, listid == 0 ? MDB_FIRST : MDB_SET_RANGE);
+ return dbscan_primary_first(tx, scan, db, db->list, DBLIST_DESC, dblist_decode_raw, listid == 0 ? MDB_FIRST : MDB_SET_RANGE);
}
dblist *dbscan_list_next(dbscan *scan) {
- return dbscan_primary2_next(scan);
+ return dbscan_table_next(scan);
}
/**
uint32_t seq = info->seq;
dbid_t fileid = info->fileid;
+ scan->tx = tx;
+ scan->DESC = DBFILE_DESC;
+ scan->decode_raw = dbfile_decode_raw;
+ scan->primary = db->file;
+ scan->mode = 2;
scan->list_entry = *info;
- if (dbscan_init(tx, scan, db, db->file_by_list, DBFILE_DESC, dbfile_decode_raw) == 0) {
- // TODO: perhaps if seq is non-zero and fileid is non-zero, lookup next entry of file
- if (seq == 0 && fileid != 0) {
- struct dblistfile thing = { .listid = listid, .seq = seq };
- MDB_cursor *cursor;
+ if ((scan->res = mdb_cursor_open(tx, db->file_by_list, &scan->cursor)))
+ goto fail;
- dbscan_init_key(scan, fileid);
- scan->data.mv_data = &thing;
- scan->data.mv_size = sizeof(thing);
+ // TODO: perhaps if seq is non-zero and fileid is non-zero, lookup next entry of file
+ if (seq == 0 && fileid != 0) {
+ struct dblistfile thing = { .listid = listid, .seq = seq };
+ MDB_cursor *cursor;
- scan->res = mdb_cursor_open(tx, db->list_by_file, &cursor);
- if ((scan->res = mdb_cursor_get(cursor, &scan->key, &scan->data, MDB_GET_BOTH_RANGE)) == 0)
- seq = ((struct dblistfile *)scan->data.mv_data)->seq;
- else
- seq = -1;
+ scan->key = (MDB_val){ sizeof(fileid), &fileid };
+ scan->dat.mv_data = &thing;
+ scan->dat.mv_size = sizeof(thing);
+
+ if ((scan->res = mdb_cursor_open(tx, db->list_by_file, &cursor)))
+ goto fail;
+ if ((scan->res = mdb_cursor_get(cursor, &scan->key, &scan->dat, MDB_GET_BOTH_RANGE)) == 0)
+ seq = ((struct dblistfile *)scan->dat.mv_data)->seq;
+ else {
mdb_cursor_close(cursor);
+ goto fail;
}
+ mdb_cursor_close(cursor);
+ }
- if (seq != -1) {
- struct dbfilelist thing = { .seq = seq };
+ struct dbfilelist thing = { .seq = seq };
- dbscan_init_key(scan, listid);
+ scan->key = (MDB_val){ sizeof(listid), &listid };
+ scan->dat.mv_data = &thing;
+ scan->dat.mv_size = sizeof(thing);
- scan->data.mv_data = &thing;
- scan->data.mv_size = sizeof(thing);
+ if ((scan->res = mdb_cursor_get(scan->cursor, &scan->key, &scan->dat, MDB_GET_BOTH_RANGE)))
+ goto fail;
- if ((scan->res = mdb_cursor_get(scan->cursor, &scan->key, &scan->data, MDB_GET_BOTH_RANGE)) == 0) {
- struct dbfilelist *value = scan->data.mv_data;
+ struct dbfilelist *value = scan->dat.mv_data;
- scan->list_entry.seq = value->seq;
- scan->list_entry.fileid = value->fileid;
+ scan->list_entry.seq = value->seq;
+ scan->list_entry.fileid = value->fileid;
- scan->key.mv_data = &scan->list_entry.fileid;
- scan->key.mv_size = sizeof(scan->list_entry.fileid);
+ scan->key.mv_data = &scan->list_entry.fileid;
+ scan->key.mv_size = sizeof(scan->list_entry.fileid);
- if ((scan->res = mdb_get(tx, db->file, &scan->key, &scan->data)) == 0) {
- dbfile *file = dbscan_decode(scan);
+ if ((scan->res = mdb_get(tx, db->file, &scan->key, &scan->dat)))
+ goto fail;
- if (file) {
- info->seq = scan->list_entry.seq;
- info->fileid = scan->list_entry.fileid;
- return file;
- }
- }
- }
- }
+ dbfile *file = dbscan_decode(scan);
+
+ if (file) {
+ info->seq = scan->list_entry.seq;
+ info->fileid = scan->list_entry.fileid;
+ return file;
}
+fail:
return NULL;
}
static dbfile *scan_list_entry_next(dbscan *scan, dblistcursor *info, MDB_cursor_op next0, MDB_cursor_op next1) {
- dbfile *file;
- MDB_val key, data;
+ MDB_val key, dat;
- if ((scan->res = mdb_cursor_get(scan->cursor, &key, &data, next1)) == 0) {
- struct dbfilelist *value = data.mv_data;
+ if ((scan->res = mdb_cursor_get(scan->cursor, &key, &dat, next1)))
+ goto fail;
- scan->list_entry.seq = value->seq;
- scan->list_entry.fileid = value->fileid;
+ struct dbfilelist *value = dat.mv_data;
- scan->key.mv_data = &scan->list_entry.fileid;
- scan->key.mv_size = sizeof(scan->list_entry.fileid);
+ scan->list_entry.seq = value->seq;
+ scan->list_entry.fileid = value->fileid;
- if ((scan->res = mdb_get(scan->tx, scan->db->file, &scan->key, &scan->data)) == 0
- && (file = dbscan_decode(scan))) {
- info->seq = scan->list_entry.seq;
- info->fileid = scan->list_entry.fileid;
- return file;
- }
- }
+ scan->key.mv_data = &scan->list_entry.fileid;
+ scan->key.mv_size = sizeof(scan->list_entry.fileid);
+ if ((scan->res = mdb_get(scan->tx, scan->primary, &scan->key, &scan->dat)))
+ goto fail;
+
+ dbfile *file = dbscan_decode(scan);
+
+ if (file) {
+ info->seq = scan->list_entry.seq;
+ info->fileid = scan->list_entry.fileid;
+ return file;
+ }
+fail:
return NULL;
}
return scan_list_entry_next(scan, info, MDB_PREV, MDB_PREV_DUP);
}
-
-/* legacy */
-
-
-dbscan *dbfile_scan_disk(dbtxn *tx, dbindex *db, int diskid) {
- return dbscan_secondary(tx, db, db->file_by_disk, diskid);
-}
-
-uint32_t dbfile_scan_next(dbscan *scan) {
- return dbscan_secondary_next(scan);
-}
-
-// TBD
-void dbfile_scan_close(dbscan *scan) {
- dbscan_close(scan);
-}
-
-dbscan *dbdisk_scan(dbtxn *tx, dbindex *db, int diskid) {
- return dbscan_primary(tx, db, db->disk, diskid);
-}
-
-dbdisk *dbdisk_next(dbscan *scan) {
- dbdisk *disk = NULL;
-
- if (dbscan_primary_next(scan)) {
- disk = ez_basic_decode(DBDISK_DESC, (ez_blob *)&scan->data);
- if (disk)
- disk->id = *(int *)scan->key.mv_data;
- }
-
- return disk;
-}
-
// prototyping
int dbfile_clear_suffix(MDB_txn *tx, dbindex *db) {
return mdb_drop(tx, db->file_by_suffix, 0);
return *(const int32_t *)ap - *(const int32_t *)bp;
}
+
/* protoyping */
-void dbindex_validate(dbindex *db) {
+
+static int check_path(const dbfile *file, const MDB_val *key) {
+ char tmp[16];
+ sprintf(tmp, "%08x", file->diskid);
+ return key->mv_size == strlen(file->path) + 8
+ && memcmp(tmp, key->mv_data, 8) == 0
+ && memcmp(file->path, key->mv_data + 8, key->mv_size - 8) == 0;
+}
+static int check_diskid(const dbfile *file, const MDB_val *key) {
+ return key->mv_size == sizeof(dbid_t)
+ && *(dbid_t*)key->mv_data == file->diskid;
+}
+static int check_title(const dbfile *file, const MDB_val *key) {
+ return key->mv_size == strlen(file->title)
+ && memcmp(file->title, key->mv_data, key->mv_size) == 0;
+}
+static int check_artist(const dbfile *file, const MDB_val *key) {
+ return key->mv_size == strlen(file->artist)
+ && memcmp(file->artist, key->mv_data, key->mv_size) == 0;
+}
+static int check_dir(const dbfile *file, const MDB_val *key) {
+ char *slash = strrchr(file->path, '/');
+ char tmp[16];
+ sprintf(tmp, "%08x", file->diskid);
+ return slash != NULL
+ && key->mv_size == (slash - file->path) + 8
+ && memcmp(tmp, key->mv_data, 8) == 0
+ && memcmp(file->path, key->mv_data + 8, (slash - file->path)) == 0;
+}
+
+int dbindex_validate(dbindex *db) {
MDB_txn *tx;
MDB_val key, data;
MDB_cursor *cursor;
int res;
+ int ok = 1;
mdb_txn_begin(db->env, NULL, MDB_RDONLY, &tx);
- size_t alloc = 4096;
- uint32_t *fids = malloc(sizeof(*fids) * alloc);
- size_t fids_size = 0;
-
+ ez_array array = { 0 };
// All files
mdb_cursor_open(tx, db->file, &cursor);
- int next = MDB_FIRST;
- while ((res = mdb_cursor_get(cursor, &key, &data, next)) == 0) {
- if (fids_size >= alloc) {
- alloc *= 2;
- fids = realloc(fids, sizeof(*fids) * alloc);
- }
- fids[fids_size++] = *(uint32_t *)key.mv_data;
- next = MDB_NEXT;
- }
+ for (int next = MDB_FIRST; (res = mdb_cursor_get(cursor, &key, &data, next)) == 0; next = MDB_NEXT)
+ ez_array_add(&array, key.mv_data, key.mv_size);
mdb_cursor_close(cursor);
+
+ uint32_t *fids = array.ea_data;
+ size_t fids_size = array.ea_size / sizeof(*fids);
+
printf("read %zd files\n", fids_size);
qsort(fids, fids_size, sizeof(*fids), cmp_fid);
db->file_by_disk,
db->file_by_title,
db->file_by_artist,
+ db->file_by_dir,
+ };
+ int (*checks[])(const dbfile *file, const MDB_val *key) = {
+ check_path,
+ check_diskid,
+ check_title,
+ check_artist,
+ check_dir
};
for (int i=0;i<4;i++) {
size_t count = 0;
- printf("table %d\n", i);
+ //printf("table %d\n", i);
mdb_cursor_open(tx, tables[i], &cursor);
res = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
while (res == 0) {
if (!bsearch(&fid, fids, fids_size, sizeof(*fids), cmp_fid)) {
printf("table %d references missing file\n", i);
+ ok = 0;
+ }
+ {
+ dbfile *file = dbfile_get(tx, db, fid);
+ if (file) {
+ if (!checks[i](file, &key)) {
+ printf("failed field check %d\n", i);
+ ok = 0;
+ }
+ } else {
+ ok = 0;
+ }
+ dbfile_free(file);
}
-
res = mdb_cursor_get(cursor, &key, &data, MDB_NEXT_DUP);
if (res == MDB_NOTFOUND)
res = mdb_cursor_get(cursor, &key, &data, MDB_NEXT);
}
mdb_cursor_close(cursor);
- if (i == 0 && count != fids_size) {
- printf("file by path miscount %zd != %zd\n", count, fids_size);
+ if (i <= 1 && count != fids_size) {
+ printf("file by [thing] miscount %zd != %zd\n", count, fids_size);
+ ok = 0;
}
}
//fail:
+ ez_array_clear(&array);
dbindex_abort(tx);
+
+ return ok;
}