lmdb 0.6.7 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79e94aae1eb049c37cc44abdde80712dd5c8fa900d1ec2b68c33b773862f4e1a
4
- data.tar.gz: ccf377de1e2e910c81459fad2fe0bce8eb831ca40e3f95fc311ef7ccd3eb1e57
3
+ metadata.gz: c098384d91381d0f7c66a4794f88ea55c1c8a1e54d60480a75a379704407252d
4
+ data.tar.gz: 11c4e5b74f9b552ad9f89d5a189bf812340ab409b43b54361cb84f7d47dfd906
5
5
  SHA512:
6
- metadata.gz: 0e3d55b2b4486caea098bb175b6ae4aeff87d770010ce4359c003e1707e6089da204a1f6f62fd0bf1e300170e0954b6245dc6fd3d9e951211d87f0b94cf958e8
7
- data.tar.gz: 96e68bf724dfc2f47a5bfd72dbc5fcda8ede5e8b7edc69e1cb2e55f5c6230997bd319e04d47bbea8aaca39c5d0e322f70e37b2f9d0cb8f5e991b50ca7df51469
6
+ metadata.gz: da3b52d345951ad527b67ce32998c749b17267b7b0d075f695e841d1b2a0891df4e0064e021e7db9ac21f41c0b81a4fb590ff88a98250675e15ad14baf185680
7
+ data.tar.gz: 12ae851f60db43dec61730f8497a06bf952e56242bff2e8fe64153a852c34582441556320cb1627fa65b7c29dfe417ba312c929d242511c0ab9c3888b12075b4
data/CHANGES CHANGED
@@ -1,3 +1,12 @@
1
+ 0.7.0
2
+
3
+ * Nesting read-only transactions finally works, by making it a noop
4
+ and using the parent transaction (djt)
5
+
6
+ 0.6.6
7
+
8
+ * added `put?` and `delete?` (djt)
9
+
1
10
  0.5.1
2
11
 
3
12
  * Move read-only operations to read-only transactions (djt)
@@ -285,69 +285,87 @@ static void stop_txn_begin(void *arg)
285
285
  */
286
286
 
287
287
  static VALUE with_transaction(VALUE venv, VALUE(*fn)(VALUE), VALUE arg, int flags) {
288
- ENVIRONMENT(venv, environment);
289
-
290
- MDB_txn* txn;
291
- TxnArgs txn_args;
292
-
293
- VALUE thread = rb_thread_current();
294
- VALUE vparent = environment_active_txn(venv);
295
-
296
- Transaction* tparent = NULL;
297
- if (vparent && !NIL_P(vparent))
298
- Data_Get_Struct(vparent, Transaction, tparent);
299
-
288
+ ENVIRONMENT(venv, environment);
289
+
290
+ MDB_txn* txn;
291
+ TxnArgs txn_args;
292
+
293
+ VALUE thread = rb_thread_current();
294
+ VALUE vparent = environment_active_txn(venv);
295
+
296
+ //
297
+ Transaction* tparent = NULL;
298
+ if (vparent && !NIL_P(vparent))
299
+ Data_Get_Struct(vparent, Transaction, tparent);
300
+
301
+ /*
302
+ * If the requested transaction is read-only and there is a parent
303
+ * transaction (whether read-only or not), we need to use the
304
+ * parent transaction.
305
+ *
306
+ * XXX except conceivably you could do a transaction (RO or RW)
307
+ * that spawns a thread that opens another transaction.
308
+ *
309
+ * note we do *NOT* re-begin the parent transaction, nor do we
310
+ * want to commit it
311
+ *
312
+ */
313
+
314
+ if (tparent && flags & MDB_RDONLY) {
315
+ int exception;
316
+ VALUE ret = rb_protect(fn, NIL_P(arg) ? vparent : arg, &exception);
317
+ if (exception) {
318
+ if (vparent == environment_active_txn(venv))
319
+ transaction_abort(vparent);
320
+ rb_jump_tag(exception);
321
+ }
322
+ return ret;
323
+ }
324
+ else {
300
325
  // XXX note this is a cursed goto loop that could almost certainly
301
326
  // be rewritten as a do-while
302
- retry:
327
+ retry:
303
328
  txn = NULL;
304
329
 
305
330
  txn_args.env = environment->env;
306
- txn_args.parent = active_txn(venv);
331
+ txn_args.parent = active_txn(venv); // this returns an MDB_txn
307
332
  txn_args.flags = flags;
308
333
  txn_args.htxn = &txn;
309
334
  txn_args.result = 0;
310
335
  txn_args.stop = 0;
311
336
 
312
- if (flags & MDB_RDONLY) {
313
- if (tparent && tparent->flags & MDB_RDONLY)
314
- // this is a no-op: put the same actual transaction in a
315
- // different wrapper struct
316
- txn = txn_args.parent;
317
- else
318
- // this will return an error if the parent transaction is
319
- // read-write, so we don't need to handle the case explicitly
320
- call_txn_begin(&txn_args);
321
- }
337
+ if (flags & MDB_RDONLY)
338
+ call_txn_begin(&txn_args);
322
339
  else {
323
- if (tparent) {
324
- // first we have to determine if we're on the same thread
325
- // as the parent, which in turn must be the same as the
326
- // environment's registry for which thread has the
327
- // read-write transaction
328
- if (thread != tparent->thread ||
329
- thread != environment->rw_txn_thread)
330
- rb_raise(cError,
331
- "Attempt to nest transaction on a different thread");
340
+ if (tparent) {
341
+ // first we have to determine if we're on the same thread
342
+ // as the parent, which in turn must be the same as the
343
+ // environment's registry for which thread has the
344
+ // read-write transaction
345
+ if (thread != tparent->thread ||
346
+ thread != environment->rw_txn_thread)
347
+ rb_raise(cError,
348
+ "Attempt to nest transaction on a different thread");
349
+ }
350
+
351
+ // try to acquire the new transaction
352
+ CALL_WITHOUT_GVL(call_txn_begin, &txn_args, stop_txn_begin, &txn_args);
353
+
354
+ if (txn_args.stop || !txn) {
355
+ // !txn is when rb_thread_call_without_gvl2
356
+ // returns before calling txn_begin
357
+ if (txn) {
358
+ mdb_txn_abort(txn);
359
+ txn_args.result = 0;
332
360
  }
333
361
 
334
- CALL_WITHOUT_GVL(call_txn_begin, &txn_args, stop_txn_begin, &txn_args);
362
+ //rb_warn("got here lol");
363
+ rb_thread_check_ints();
364
+ goto retry; // in what cases do we get here?
365
+ }
335
366
 
336
- if (txn_args.stop || !txn) {
337
- // !txn is when rb_thread_call_without_gvl2
338
- // returns before calling txn_begin
339
- if (txn) {
340
- mdb_txn_abort(txn);
341
- txn_args.result = 0;
342
- }
343
-
344
- //rb_warn("got here lol");
345
- rb_thread_check_ints();
346
- goto retry; // in what cases do we get here?
347
- }
348
-
349
- // set the thread
350
- environment->rw_txn_thread = thread;
367
+ // set the thread
368
+ environment->rw_txn_thread = thread;
351
369
  }
352
370
 
353
371
  // this will raise unless result is zero
@@ -373,14 +391,15 @@ static VALUE with_transaction(VALUE venv, VALUE(*fn)(VALUE), VALUE arg, int flag
373
391
  VALUE ret = rb_protect(fn, NIL_P(arg) ? vtxn : arg, &exception);
374
392
 
375
393
  if (exception) {
376
- // rb_warn("lol got exception");
377
- if (vtxn == environment_active_txn(venv))
378
- transaction_abort(vtxn);
379
- rb_jump_tag(exception);
394
+ // rb_warn("lol got exception");
395
+ if (vtxn == environment_active_txn(venv))
396
+ transaction_abort(vtxn);
397
+ rb_jump_tag(exception);
380
398
  }
381
399
  if (vtxn == environment_active_txn(venv))
382
- transaction_commit(vtxn);
400
+ transaction_commit(vtxn);
383
401
  return ret;
402
+ }
384
403
  }
385
404
 
386
405
  static void environment_check(Environment* environment) {
@@ -773,23 +792,24 @@ static void environment_set_active_txn(VALUE self, VALUE thread, VALUE txn) {
773
792
  }
774
793
  }
775
794
 
795
+ static MDB_txn* extract_txn(VALUE vtxn) {
796
+ if (NIL_P(vtxn)) return NULL;
797
+ TRANSACTION(vtxn, transaction);
798
+ if (!transaction->txn) rb_raise(cError, "Transaction is already terminated");
799
+ if (transaction->thread != rb_thread_current())
800
+ rb_raise(cError, "Transaction is from another thread");
801
+ return transaction->txn;
802
+ }
776
803
 
777
804
  static MDB_txn* active_txn(VALUE self) {
778
805
  VALUE vtxn = environment_active_txn(self);
779
- if (NIL_P(vtxn))
780
- return 0;
781
- TRANSACTION(vtxn, transaction);
782
- if (!transaction->txn)
783
- rb_raise(cError, "Transaction is already terminated");
784
- if (transaction->thread != rb_thread_current())
785
- rb_raise(cError, "Wrong thread");
786
- return transaction->txn;
806
+ return extract_txn(vtxn);
787
807
  }
788
808
 
789
809
  static MDB_txn* need_txn(VALUE self) {
790
810
  MDB_txn* txn = active_txn(self);
791
- if (!txn)
792
- rb_raise(cError, "No active transaction");
811
+
812
+ if (!txn) rb_raise(cError, "No active transaction");
793
813
  return txn;
794
814
  }
795
815
 
@@ -104,12 +104,12 @@ typedef struct {
104
104
  } EnvironmentOptions;
105
105
 
106
106
  typedef struct {
107
- MDB_env *env;
108
- MDB_txn *parent;
109
- unsigned int flags;
110
- MDB_txn **htxn;
111
- int result;
112
- int stop;
107
+ MDB_env *env;
108
+ MDB_txn *parent;
109
+ unsigned int flags;
110
+ MDB_txn **htxn; // not sure why this is a pointer to a pointer
111
+ int result;
112
+ int stop;
113
113
  } TxnArgs;
114
114
 
115
115
  static VALUE cEnvironment, cDatabase, cTransaction, cCursor, cError;
data/lib/lmdb/database.rb CHANGED
@@ -145,8 +145,7 @@ module LMDB
145
145
  # @return [void]
146
146
  #
147
147
  def put?(key, value = nil, **options)
148
- flags = {}
149
- flags[dupsort? ? :nodupdata : :nooverwrite] = true
148
+ flags = { (dupsort? ? :nodupdata : :nooverwrite) => true }
150
149
  begin
151
150
  put key, value, **options.merge(flags)
152
151
  rescue LMDB::Error::KEYEXIST
data/lib/lmdb/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LMDB
2
- VERSION = '0.6.7'.freeze
2
+ VERSION = '0.7.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lmdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.7
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Mendler
8
8
  - Dorian Taylor
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-11-21 00:00:00.000000000 Z
11
+ date: 2025-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake