commit 48d62971a6c396f1e0dc0e03c58d64932403beb7
parent e85222188d19f1d94ad88fb2120a9a3dfb9375bd
Author: William Casarin <jb55@jb55.com>
Date: Wed, 30 Aug 2023 13:57:51 -0700
add transactions
this will allow reads to survive for longer
Diffstat:
M | nostrdb.c | | | 56 | +++++++++++++++++++++++++++----------------------------- |
M | nostrdb.h | | | 15 | ++++++++++++--- |
M | test.c | | | 14 | ++++++++++---- |
3 files changed, 49 insertions(+), 36 deletions(-)
diff --git a/nostrdb.c b/nostrdb.c
@@ -207,6 +207,18 @@ struct ndb_writer_msg {
};
};
+int ndb_begin_query(struct ndb *ndb, struct ndb_txn *txn)
+{
+ txn->ndb = ndb;
+ MDB_txn **mdb_txn = (MDB_txn **)&txn->mdb_txn;
+ return mdb_txn_begin(ndb->lmdb.env, NULL, 0, mdb_txn) == 0;
+}
+
+void ndb_end_query(struct ndb_txn *txn)
+{
+ mdb_txn_abort(txn->mdb_txn);
+}
+
int ndb_note_verify(void *ctx, unsigned char pubkey[32], unsigned char id[32],
unsigned char sig[64])
{
@@ -249,8 +261,8 @@ int ndb_get_tsid(MDB_txn *txn, struct ndb_lmdb *lmdb, enum ndb_dbs db,
{
MDB_val k, v;
MDB_cursor *cur;
- struct ndb_tsid tsid;
int success = 0;
+ struct ndb_tsid tsid;
ndb_tsid_high(&tsid, id);
k.mv_data = &tsid;
@@ -280,23 +292,17 @@ cleanup:
return success;
}
-static void *ndb_lookup_by_key(struct ndb *ndb, uint64_t key,
+static void *ndb_lookup_by_key(struct ndb_txn *txn, uint64_t key,
enum ndb_dbs store, size_t *len)
{
MDB_val k, v;
- MDB_txn *txn;
k.mv_data = &key;
k.mv_size = sizeof(key);
- if (mdb_txn_begin(ndb->lmdb.env, 0, 0, &txn)) {
- ndb_debug("ndb_get_note_by_id: mdb_txn_begin failed\n");
- return NULL;
- }
-
- if (mdb_get(txn, ndb->lmdb.dbs[store], &k, &v)) {
+ if (mdb_get(txn->mdb_txn, txn->ndb->lmdb.dbs[store], &k, &v)) {
ndb_debug("ndb_get_profile_by_pubkey: mdb_get note failed\n");
- mdb_txn_abort(txn);
+ mdb_txn_abort(txn->mdb_txn);
return NULL;
}
@@ -306,53 +312,45 @@ static void *ndb_lookup_by_key(struct ndb *ndb, uint64_t key,
return v.mv_data;
}
-static void *ndb_lookup_tsid(struct ndb *ndb, enum ndb_dbs ind,
+static void *ndb_lookup_tsid(struct ndb_txn *txn, enum ndb_dbs ind,
enum ndb_dbs store, const unsigned char *pk,
size_t *len)
{
MDB_val k, v;
- MDB_txn *txn;
void *res = NULL;
if (len)
*len = 0;
- if (mdb_txn_begin(ndb->lmdb.env, 0, 0, &txn)) {
- ndb_debug("ndb_get_note_by_id: mdb_txn_begin failed\n");
- return NULL;
- }
-
- if (!ndb_get_tsid(txn, &ndb->lmdb, ind, pk, &k)) {
+ if (!ndb_get_tsid(txn->mdb_txn, &txn->ndb->lmdb, ind, pk, &k)) {
//ndb_debug("ndb_get_profile_by_pubkey: ndb_get_tsid failed\n");
- goto cleanup;
+ return 0;
}
- if (mdb_get(txn, ndb->lmdb.dbs[store], &k, &v)) {
+ if (mdb_get(txn->mdb_txn, txn->ndb->lmdb.dbs[store], &k, &v)) {
ndb_debug("ndb_get_profile_by_pubkey: mdb_get note failed\n");
- goto cleanup;
+ return 0;
}
res = v.mv_data;
assert(((uint64_t)res % 4) == 0);
if (len)
*len = v.mv_size;
-cleanup:
- mdb_txn_abort(txn);
return res;
}
-void *ndb_get_profile_by_pubkey(struct ndb *ndb, const unsigned char *pk, size_t *len)
+void *ndb_get_profile_by_pubkey(struct ndb_txn *txn, const unsigned char *pk, size_t *len)
{
- return ndb_lookup_tsid(ndb, NDB_DB_PROFILE_PK, NDB_DB_PROFILE, pk, len);
+ return ndb_lookup_tsid(txn, NDB_DB_PROFILE_PK, NDB_DB_PROFILE, pk, len);
}
-struct ndb_note *ndb_get_note_by_id(struct ndb *ndb, const unsigned char *id, size_t *len)
+struct ndb_note *ndb_get_note_by_id(struct ndb_txn *txn, const unsigned char *id, size_t *len)
{
- return ndb_lookup_tsid(ndb, NDB_DB_NOTE_ID, NDB_DB_NOTE, id, len);
+ return ndb_lookup_tsid(txn, NDB_DB_NOTE_ID, NDB_DB_NOTE, id, len);
}
-struct ndb_note *ndb_get_note_by_key(struct ndb *ndb, uint64_t key, size_t *len)
+struct ndb_note *ndb_get_note_by_key(struct ndb_txn *txn, uint64_t key, size_t *len)
{
- return ndb_lookup_by_key(ndb, key, NDB_DB_NOTE, len);
+ return ndb_lookup_by_key(txn, key, NDB_DB_NOTE, len);
}
static int ndb_has_note(MDB_txn *txn, struct ndb_lmdb *lmdb, const unsigned char *id)
diff --git a/nostrdb.h b/nostrdb.h
@@ -18,10 +18,17 @@
struct ndb_json_parser;
struct ndb;
+// sorry, swift needs help with forward declared pointers like this
struct ndb_t {
struct ndb *ndb;
};
+// required to keep a read
+struct ndb_txn {
+ struct ndb *ndb;
+ void *mdb_txn;
+};
+
// To-client event types
enum tce_type {
NDB_TCE_EVENT = 0x1,
@@ -154,9 +161,11 @@ int ndb_note_verify(void *secp_ctx, unsigned char pubkey[32], unsigned char id[3
int ndb_init(struct ndb **ndb, const char *dbdir, size_t mapsize, int ingester_threads);
int ndb_process_event(struct ndb *, const char *json, int len);
int ndb_process_events(struct ndb *, const char *ldjson, size_t len);
-void *ndb_get_profile_by_pubkey(struct ndb *, const unsigned char *pubkey, size_t *len);
-struct ndb_note *ndb_get_note_by_id(struct ndb *, const unsigned char *id, size_t *len);
-struct ndb_note *ndb_get_note_by_key(struct ndb *, uint64_t key, size_t *len);
+int ndb_begin_query(struct ndb *, struct ndb_txn *);
+void ndb_end_query(struct ndb_txn *);
+void *ndb_get_profile_by_pubkey(struct ndb_txn *txn, const unsigned char *pubkey, size_t *len);
+struct ndb_note *ndb_get_note_by_id(struct ndb_txn *txn, const unsigned char *id, size_t *len);
+struct ndb_note *ndb_get_note_by_key(struct ndb_txn *txn, uint64_t key, size_t *len);
void ndb_destroy(struct ndb *);
// BUILDER
diff --git a/test.c b/test.c
@@ -41,9 +41,12 @@ static void test_load_profiles()
0xd2, 0xb4, 0xd1, 0x3a, 0x55, 0x43, 0x09, 0x07 };
const char *expected_content = "{\"website\":\"selenejin.com\",\"lud06\":\"\",\"nip05\":\"selenejin@BitcoinNostr.com\",\"picture\":\"https://nostr.build/i/3549697beda0fe1f4ae621f359c639373d92b7c8d5c62582b656c5843138c9ed.jpg\",\"display_name\":\"Selene Jin\",\"about\":\"INTJ | Founding Designer @Blockstream\",\"name\":\"SeleneJin\"}";
- struct ndb_note *note = ndb_get_note_by_id(ndb, id, NULL);
+ struct ndb_txn txn;
+ assert(ndb_begin_query(ndb, &txn));
+ struct ndb_note *note = ndb_get_note_by_id(&txn, id, NULL);
assert(note != NULL);
assert(!strcmp(ndb_note_content(note), expected_content));
+ ndb_end_query(&txn);
ndb_destroy(ndb);
@@ -268,7 +271,9 @@ static void test_fetch_last_noteid()
unsigned char id[32] = { 0xdc, 0x96, 0x4f, 0x4c, 0x89, 0x83, 0x64, 0x13, 0x8e, 0x81, 0x96, 0xf0, 0xc7, 0x33, 0x38, 0xc8, 0xcc, 0x3e, 0xbf, 0xa3, 0xaf, 0xdd, 0xbc, 0x7d, 0xd1, 0x58, 0xb4, 0x84, 0x7c, 0x1e, 0xbf, 0xa0 };
- struct ndb_note *note = ndb_get_note_by_id(ndb, id, &len);
+ struct ndb_txn txn;
+ assert(ndb_begin_query(ndb, &txn));
+ struct ndb_note *note = ndb_get_note_by_id(&txn, id, &len);
assert(note != NULL);
assert(note->created_at == 1650054135);
@@ -278,7 +283,7 @@ static void test_fetch_last_noteid()
0xd1, 0x2c, 0x17, 0xbd, 0xe3, 0x09, 0x4a, 0xd3, 0x2f, 0x4a, 0xb8, 0x62, 0xa6, 0xcc, 0x6f, 0x5c, 0x28, 0x9c, 0xfe, 0x7d, 0x58, 0x02, 0x27, 0x0b, 0xdf, 0x34, 0x90, 0x4d, 0xf5, 0x85, 0xf3, 0x49
};
- void *root = ndb_get_profile_by_pubkey(ndb, pk, &len);
+ void *root = ndb_get_profile_by_pubkey(&txn, pk, &len);
assert(root);
int res = NdbProfileRecord_verify_as_root(root, len);
@@ -297,7 +302,8 @@ static void test_fetch_last_noteid()
printf("note_key %" PRIu64 "\n", key);
- struct ndb_note *n = ndb_get_note_by_key(ndb, key, NULL);
+ struct ndb_note *n = ndb_get_note_by_key(&txn, key, NULL);
+ ndb_end_query(&txn);
assert(memcmp(profile_note_id, n->id, 32) == 0);
//fwrite(profile, len, 1, stdout);