isomorfeus-ferret 0.15.0 → 0.16.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.
@@ -17,31 +17,59 @@ const char *lock_s = "lock";
17
17
 
18
18
  // txn
19
19
 
20
- static void mdbxs_begin_txn(FrtStore *store, MDBX_txn **txn) {
20
+ static bool mdbxs_begin_txn(FrtStore *store, MDBX_txn **txn) {
21
+ MDBX_txn *env_txn = mdbx_env_get_userctx(store->dir.mdbx->env);
22
+ if (env_txn) {
23
+ *txn = env_txn;
24
+ return false;
25
+ }
21
26
  int res = mdbx_txn_begin(store->dir.mdbx->env, NULL, 0, txn);
22
27
  if (res != MDBX_SUCCESS) {
23
28
  FRT_RAISE(FRT_IO_ERROR, "failed to begin txn, error: %i\n", res);
24
29
  }
30
+ res = mdbx_env_set_userctx(store->dir.mdbx->env, *txn);
31
+ if (res != MDBX_SUCCESS) {
32
+ mdbx_txn_abort(*txn);
33
+ FRT_RAISE(FRT_IO_ERROR, "failed to begin txn, userctx, error: %i\n", res);
34
+ }
35
+ return true;
25
36
  }
26
37
 
27
- static void mdbxs_begin_ro_txn(FrtStore *store, MDBX_txn **txn) {
38
+ static bool mdbxs_begin_ro_txn(FrtStore *store, MDBX_txn **txn) {
39
+ MDBX_txn *env_txn = mdbx_env_get_userctx(store->dir.mdbx->env);
40
+ if (env_txn) {
41
+ *txn = env_txn;
42
+ return false;
43
+ }
28
44
  int res = mdbx_txn_begin(store->dir.mdbx->env, NULL, 0 | MDBX_RDONLY, txn);
29
45
  if (res != MDBX_SUCCESS) {
30
46
  FRT_RAISE(FRT_IO_ERROR, "failed to begin read only txn, error: %i\n", res);
31
47
  }
48
+ res = mdbx_env_set_userctx(store->dir.mdbx->env, *txn);
49
+ if (res != MDBX_SUCCESS) {
50
+ mdbx_txn_abort(*txn);
51
+ FRT_RAISE(FRT_IO_ERROR, "failed to begin read only txn, userctx, error: %i\n", res);
52
+ }
53
+ return true;
32
54
  }
33
55
 
34
- static void mdbxs_commit_txn(MDBX_txn *txn) {
35
- int res = mdbx_txn_commit(txn);
36
- if (res != MDBX_SUCCESS) {
37
- FRT_RAISE(FRT_IO_ERROR, "failed to commit txn, error: %i\n", res);
56
+ static void mdbxs_commit_txn(FrtStore *store, MDBX_txn *txn, bool del_env_txn) {
57
+ if (del_env_txn) {
58
+ mdbx_env_set_userctx(store->dir.mdbx->env, NULL);
59
+ int res = mdbx_txn_commit(txn);
60
+ if (res != MDBX_SUCCESS) {
61
+ FRT_RAISE(FRT_IO_ERROR, "failed to commit txn, error: %i\n", res);
62
+ }
38
63
  }
39
64
  }
40
65
 
41
- static void mdbxs_abort_txn(MDBX_txn *txn) {
42
- int res = mdbx_txn_abort(txn);
43
- if (res != MDBX_SUCCESS) {
44
- FRT_RAISE(FRT_IO_ERROR, "failed to abort txn, error: %i\n", res);
66
+ static void mdbxs_abort_txn(FrtStore *store, MDBX_txn *txn, bool del_env_txn) {
67
+ if (del_env_txn) {
68
+ mdbx_env_set_userctx(store->dir.mdbx->env, NULL);
69
+ int res = mdbx_txn_abort(txn);
70
+ if (res != MDBX_SUCCESS) {
71
+ FRT_RAISE(FRT_IO_ERROR, "failed to abort txn, error: %i\n", res);
72
+ }
45
73
  }
46
74
  }
47
75
 
@@ -91,7 +119,7 @@ static void mdbxs_touch(FrtStore *store, const char *filename) {
91
119
  val.iov_base = NULL;
92
120
  val.iov_len = 0;
93
121
 
94
- mdbxs_begin_txn(store, &txn);
122
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
95
123
  mdbxs_open_dbi(txn, dbi_name, &dbi);
96
124
  res = mdbx_get(txn, dbi, &key, &val);
97
125
 
@@ -99,12 +127,12 @@ static void mdbxs_touch(FrtStore *store, const char *filename) {
99
127
  val.iov_base = NULL;
100
128
  val.iov_len = 0;
101
129
  mdbxs_put(txn, dbi, &key, &val);
102
- mdbxs_commit_txn(txn);
103
- } else if (res == MDBX_SUCCESS) {
104
- mdbxs_abort_txn(txn);
130
+ mdbxs_commit_txn(store, txn, del_env_txn);
105
131
  } else {
106
- mdbxs_abort_txn(txn);
107
- FRT_RAISE(FRT_IO_ERROR, "failed to touch '%s', error: %i\n", filename, res);
132
+ mdbxs_abort_txn(store, txn, del_env_txn);
133
+ if (res != MDBX_SUCCESS) {
134
+ FRT_RAISE(FRT_IO_ERROR, "failed to touch '%s', error: %i\n", filename, res);
135
+ }
108
136
  }
109
137
  }
110
138
 
@@ -118,10 +146,10 @@ static int mdbxs_exists(FrtStore *store, const char *filename) {
118
146
  val.iov_base = NULL;
119
147
  val.iov_len = 0;
120
148
 
121
- mdbxs_begin_ro_txn(store, &txn);
149
+ bool del_env_txn = mdbxs_begin_ro_txn(store, &txn);
122
150
  mdbxs_open_dbi(txn, dbi_name, &dbi);
123
151
  int res = mdbx_get(txn, dbi, &key, &val);
124
- mdbxs_abort_txn(txn);
152
+ mdbxs_abort_txn(store, txn, del_env_txn);
125
153
 
126
154
  if (res == MDBX_SUCCESS) { return true; }
127
155
  return false;
@@ -135,10 +163,10 @@ static int mdbxs_remove(FrtStore *store, const char *filename) {
135
163
  key.iov_base = (char *)filename;
136
164
  key.iov_len = strlen(filename);
137
165
 
138
- mdbxs_begin_txn(store, &txn);
166
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
139
167
  mdbxs_open_dbi(txn, dbi_name, &dbi);
140
168
  mdbxs_del(txn, dbi, &key, NULL);
141
- mdbxs_commit_txn(txn);
169
+ mdbxs_commit_txn(store, txn, del_env_txn);
142
170
 
143
171
  return 0;
144
172
  }
@@ -154,7 +182,7 @@ static void mdbxs_rename(FrtStore *store, const char *from, const char *to) {
154
182
  val.iov_base = NULL;
155
183
  val.iov_len = 0;
156
184
 
157
- mdbxs_begin_txn(store, &txn);
185
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
158
186
  mdbxs_open_dbi(txn, dbi_name, &dbi);
159
187
  res = mdbx_get(txn, dbi, &from_key, &val);
160
188
 
@@ -164,9 +192,9 @@ static void mdbxs_rename(FrtStore *store, const char *from, const char *to) {
164
192
 
165
193
  mdbxs_put(txn, dbi, &to_key, &val);
166
194
  mdbxs_del(txn, dbi, &from_key, NULL);
167
- mdbxs_commit_txn(txn);
195
+ mdbxs_commit_txn(store, txn, del_env_txn);
168
196
  } else {
169
- mdbxs_abort_txn(txn);
197
+ mdbxs_abort_txn(store, txn, del_env_txn);
170
198
  FRT_RAISE(FRT_FILE_NOT_FOUND_ERROR, "tried to open '%s' but its not accessible, error: %i", from, res);
171
199
  }
172
200
  }
@@ -178,11 +206,11 @@ static int mdbxs_count(FrtStore *store) {
178
206
  int res = 0;
179
207
  int cnt = 0;
180
208
 
181
- mdbxs_begin_txn(store, &txn);
209
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
182
210
  mdbxs_open_dbi(txn, dbi_name, &dbi);
183
211
  res = mdbx_dbi_stat(txn, dbi, &stat, sizeof(MDBX_stat));
184
212
  cnt = stat.ms_entries;
185
- mdbxs_abort_txn(txn);
213
+ mdbxs_abort_txn(store, txn, del_env_txn);
186
214
 
187
215
  if (res != MDBX_SUCCESS) {
188
216
  FRT_RAISE(FRT_FILE_NOT_FOUND_ERROR, "failed to stat dbi, error: %i", res);
@@ -201,16 +229,27 @@ static void mdbxs_each(FrtStore *store, void (*func)(const char *fname, void *ar
201
229
  val.iov_base = NULL;
202
230
  val.iov_len = 0;
203
231
 
204
- mdbxs_begin_txn(store, &txn);
232
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
205
233
  mdbxs_open_dbi(txn, dbi_name, &dbi);
206
234
  mdbxs_open_cursor(txn, dbi, &cursor);
207
235
 
208
236
  int op = MDBX_FIRST;
237
+ int buffer_size = FRT_MAX_WORD_SIZE;
238
+ char *name = FRT_ALLOC_N(char, buffer_size);
209
239
  while(mdbx_cursor_get(cursor, &key, &val, op) == MDBX_SUCCESS) {
210
240
  op = MDBX_NEXT;
211
- func(key.iov_base, arg);
241
+ if (key.iov_len >= buffer_size) {
242
+ buffer_size = key.iov_len + 1;
243
+ FRT_REALLOC_N(name, char, buffer_size);
244
+ }
245
+ memcpy(name, key.iov_base, key.iov_len);
246
+ name[key.iov_len] = '\0';
247
+ func(name, arg);
212
248
  }
213
- mdbxs_commit_txn(txn);
249
+ free(name);
250
+
251
+ mdbx_cursor_close(cursor);
252
+ mdbxs_commit_txn(store, txn, del_env_txn);
214
253
  }
215
254
 
216
255
  static void mdbxs_clear_locks(FrtStore *store) {
@@ -224,16 +263,32 @@ static void mdbxs_clear_locks(FrtStore *store) {
224
263
  val.iov_base = NULL;
225
264
  val.iov_len = 0;
226
265
 
227
- mdbxs_begin_txn(store, &txn);
266
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
228
267
  mdbxs_open_dbi(txn, dbi_name, &dbi);
229
268
  mdbxs_open_cursor(txn, dbi, &cursor);
230
269
 
231
270
  int op = MDBX_FIRST;
271
+ int buffer_size = FRT_MAX_WORD_SIZE;
272
+ char *name = FRT_ALLOC_N(char, buffer_size);
232
273
  while(mdbx_cursor_get(cursor, &key, &val, op) == MDBX_SUCCESS) {
233
274
  op = MDBX_NEXT;
234
- mdbx_cursor_del(cursor, MDBX_ALLDUPS);
275
+ if (key.iov_len >= buffer_size) {
276
+ buffer_size = key.iov_len + 1;
277
+ FRT_REALLOC_N(name, char, buffer_size);
278
+ }
279
+ memcpy(name, key.iov_base, key.iov_len);
280
+ name[key.iov_len] = '\0';
281
+ if (key.iov_len > 11) { // "ferret-" + ".lck"
282
+ if ((strncmp(FRT_LOCK_PREFIX, name, strlen(FRT_LOCK_PREFIX)) == 0) &&
283
+ (strncmp(".lck", name + (key.iov_len - 4), 4) == 0)) {
284
+ mdbx_cursor_del(cursor, MDBX_ALLDUPS);
285
+ }
286
+ }
235
287
  }
236
- mdbxs_commit_txn(txn);
288
+ free(name);
289
+
290
+ mdbx_cursor_close(cursor);
291
+ mdbxs_commit_txn(store, txn, del_env_txn);
237
292
  }
238
293
 
239
294
  static bool mdbxs_is_locked(FrtStore *store, MDBX_val *key, MDBX_txn *txn, MDBX_dbi dbi) {
@@ -259,7 +314,7 @@ static void mdbxs_clear(FrtStore *store) {
259
314
  val.iov_base = NULL;
260
315
  val.iov_len = 0;
261
316
 
262
- mdbxs_begin_txn(store, &txn);
317
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
263
318
  mdbxs_open_dbi(txn, dbi_name, &dbi);
264
319
  mdbxs_open_cursor(txn, dbi, &cursor);
265
320
 
@@ -270,7 +325,8 @@ static void mdbxs_clear(FrtStore *store) {
270
325
  mdbx_cursor_del(cursor, MDBX_ALLDUPS);
271
326
  }
272
327
  }
273
- mdbxs_commit_txn(txn);
328
+ mdbx_cursor_close(cursor);
329
+ mdbxs_commit_txn(store, txn, del_env_txn);
274
330
  }
275
331
 
276
332
  /**
@@ -288,7 +344,7 @@ static void mdbxs_clear_all(FrtStore *store) {
288
344
  val.iov_base = NULL;
289
345
  val.iov_len = 0;
290
346
 
291
- mdbxs_begin_txn(store, &txn);
347
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
292
348
  mdbxs_open_dbi(txn, dbi_name, &dbi);
293
349
  mdbxs_open_cursor(txn, dbi, &cursor);
294
350
 
@@ -297,7 +353,9 @@ static void mdbxs_clear_all(FrtStore *store) {
297
353
  op = MDBX_NEXT;
298
354
  mdbx_cursor_del(cursor, MDBX_ALLDUPS);
299
355
  }
300
- mdbxs_commit_txn(txn);
356
+
357
+ mdbx_cursor_close(cursor);
358
+ mdbxs_commit_txn(store, txn, del_env_txn);
301
359
 
302
360
  mdbxs_clear_locks(store);
303
361
  }
@@ -336,15 +394,15 @@ static frt_off_t mdbxs_length(FrtStore *store, const char *filename) {
336
394
  val.iov_base = NULL;
337
395
  val.iov_len = 0;
338
396
 
339
- mdbxs_begin_ro_txn(store, &txn);
397
+ bool del_env_txn = mdbxs_begin_ro_txn(store, &txn);
340
398
  mdbxs_open_dbi(txn, dbi_name, &dbi);
341
399
  int res = mdbx_get(txn, dbi, &key, &val);
342
400
  if (res != MDBX_SUCCESS) {
343
- mdbxs_abort_txn(txn);
344
- FRT_RAISE(FRT_FILE_NOT_FOUND_ERROR, "tried to open \"%s\" but it doesn't exist, error: %i", filename, res);
401
+ mdbxs_abort_txn(store, txn, del_env_txn);
402
+ FRT_RAISE(FRT_FILE_NOT_FOUND_ERROR, "tried to open '%s' but it doesn't exist, error: %i", filename, res);
345
403
  }
346
404
  len = val.iov_len;
347
- mdbxs_abort_txn(txn);
405
+ mdbxs_abort_txn(store, txn, del_env_txn);
348
406
  return len;
349
407
  }
350
408
 
@@ -352,7 +410,7 @@ static void mdbxso_close_i(FrtOutStream *os) {
352
410
  MDBX_txn *txn = NULL;
353
411
  MDBX_dbi dbi;
354
412
 
355
- mdbxs_begin_txn(os->store, &txn);
413
+ bool del_env_txn = mdbxs_begin_txn(os->store, &txn);
356
414
  mdbxs_open_dbi(txn, dbi_name, &dbi);
357
415
 
358
416
  FrtRAMFile *rf = os->file.rf;
@@ -388,7 +446,7 @@ static void mdbxso_close_i(FrtOutStream *os) {
388
446
  }
389
447
 
390
448
  mdbxs_put(txn, dbi, &key, &val);
391
- mdbxs_commit_txn(txn);
449
+ mdbxs_commit_txn(os->store, txn, del_env_txn);
392
450
  free(val.iov_base);
393
451
  rf_close(os->file.rf);
394
452
  }
@@ -408,10 +466,10 @@ static FrtOutStream *mdbxs_new_output(FrtStore *store, const char *filename) {
408
466
  val.iov_base = NULL;
409
467
  val.iov_len = 0;
410
468
 
411
- mdbxs_begin_txn(store, &txn);
469
+ bool del_env_txn = mdbxs_begin_txn(store, &txn);
412
470
  mdbxs_open_dbi(txn, dbi_name, &dbi);
413
471
  mdbxs_put(txn, dbi, &key, &val);
414
- mdbxs_commit_txn(txn);
472
+ mdbxs_commit_txn(store, txn, del_env_txn);
415
473
 
416
474
  FrtRAMFile *rf = rf_new(filename);
417
475
  FRT_REF(rf);
@@ -442,11 +500,11 @@ static FrtInStream *mdbxs_open_input(FrtStore *store, const char *filename) {
442
500
  FrtRAMFile *rf = NULL;
443
501
  FrtInStream *is;
444
502
 
445
- mdbxs_begin_ro_txn(store, &txn);
503
+ bool del_env_txn = mdbxs_begin_ro_txn(store, &txn);
446
504
  mdbxs_open_dbi(txn, dbi_name, &dbi);
447
505
  if (mdbx_get(txn, dbi, &key, &val) != MDBX_SUCCESS) {
448
- mdbxs_abort_txn(txn);
449
- FRT_RAISE(FRT_FILE_NOT_FOUND_ERROR, "tried to open \"%s\" but it doesn't exist", filename);
506
+ mdbxs_abort_txn(store, txn, del_env_txn);
507
+ FRT_RAISE(FRT_FILE_NOT_FOUND_ERROR, "tried to open '%s' but it doesn't exist", filename);
450
508
  }
451
509
 
452
510
  rf = rf_new(filename);
@@ -478,7 +536,7 @@ static FrtInStream *mdbxs_open_input(FrtStore *store, const char *filename) {
478
536
  }
479
537
  rf->len = len;
480
538
  }
481
- mdbxs_abort_txn(txn);
539
+ mdbxs_abort_txn(store, txn, del_env_txn);
482
540
 
483
541
  is = frt_is_new();
484
542
  is->f->file.rf = rf;
@@ -494,7 +552,7 @@ static FrtInStream *mdbxs_open_input(FrtStore *store, const char *filename) {
494
552
  static int mdbxs_lock_obtain(FrtLock *lock) {
495
553
  MDBX_txn *txn = NULL;
496
554
  MDBX_dbi dbi;
497
- mdbxs_begin_txn(lock->store, &txn);
555
+ bool del_env_txn = mdbxs_begin_txn(lock->store, &txn);
498
556
  mdbxs_open_dbi(txn, dbi_name, &dbi);
499
557
 
500
558
  MDBX_val key, val;
@@ -503,25 +561,25 @@ static int mdbxs_lock_obtain(FrtLock *lock) {
503
561
  int trys = LOCK_OBTAIN_TIMEOUT;
504
562
  bool is_locked = mdbxs_is_locked(lock->store, &key, txn, dbi);
505
563
  while (is_locked && (trys > 0)) {
506
- mdbxs_abort_txn(txn);
564
+ mdbxs_abort_txn(lock->store, txn, del_env_txn);
507
565
 
508
566
  trys--;
509
567
  /* sleep for 10 milliseconds */
510
568
  frt_micro_sleep(10000);
511
569
 
512
- mdbxs_begin_txn(lock->store, &txn);
570
+ del_env_txn = mdbxs_begin_txn(lock->store, &txn);
513
571
  mdbxs_open_dbi(txn, dbi_name, &dbi);
514
572
 
515
573
  is_locked = mdbxs_is_locked(lock->store, &key, txn, dbi);
516
574
  }
517
575
  if (is_locked) {
518
- mdbxs_abort_txn(txn);
576
+ mdbxs_abort_txn(lock->store, txn, del_env_txn);
519
577
  return false;
520
578
  } else {
521
579
  val.iov_base = (char *)lock_s; // could be a number to count locks
522
580
  val.iov_len = 4;
523
581
  mdbxs_put(txn, dbi, &key, &val);
524
- mdbxs_commit_txn(txn);
582
+ mdbxs_commit_txn(lock->store, txn, del_env_txn);
525
583
  return true;
526
584
  }
527
585
  }
@@ -535,10 +593,10 @@ static int mdbxs_lock_is_locked(FrtLock *lock) {
535
593
  key.iov_base = lock->name;
536
594
  key.iov_len = strlen(lock->name);
537
595
 
538
- mdbxs_begin_ro_txn(lock->store, &txn);
596
+ bool del_env_txn = mdbxs_begin_ro_txn(lock->store, &txn);
539
597
  mdbxs_open_dbi(txn, dbi_name, &dbi);
540
598
  res = mdbxs_is_locked(lock->store, &key, txn, dbi);
541
- mdbxs_abort_txn(txn);
599
+ mdbxs_abort_txn(lock->store, txn, del_env_txn);
542
600
 
543
601
  return res;
544
602
  }
@@ -551,10 +609,10 @@ static void mdbxs_lock_release(FrtLock *lock) {
551
609
  key.iov_base = lock->name;
552
610
  key.iov_len = strlen(lock->name);
553
611
 
554
- mdbxs_begin_txn(lock->store, &txn);
612
+ bool del_env_txn = mdbxs_begin_txn(lock->store, &txn);
555
613
  mdbxs_open_dbi(txn, dbi_name, &dbi);
556
614
  mdbxs_del(txn, dbi, &key, NULL);
557
- mdbxs_commit_txn(txn);
615
+ mdbxs_commit_txn(lock->store, txn, del_env_txn);
558
616
  }
559
617
 
560
618
  static FrtLock *mdbxs_open_lock_i(FrtStore *store, const char *lockname) {
@@ -330,15 +330,6 @@ struct FrtStore {
330
330
  VALUE rstore;
331
331
  };
332
332
 
333
- /**
334
- * Create a newly allocated file-system FrtStore at the pathname designated. The
335
- * pathname must be the name of an existing directory.
336
- *
337
- * @param pathname the pathname of the directory to be used by the index
338
- * @return a newly allocated file-system FrtStore.
339
- */
340
- extern FrtStore *frt_open_fs_store(const char *pathname);
341
-
342
333
  /**
343
334
  * Create a newly allocated MDBX FrtStore at the pathname designated. The
344
335
  * pathname must be the name of an existing directory.
@@ -13,7 +13,7 @@ ID id_hash;
13
13
  ID id_capacity;
14
14
  ID id_less_than;
15
15
  ID id_lt;
16
- ID id_is_directory;
16
+ ID id_exist;
17
17
  ID id_close;
18
18
  ID id_cclass;
19
19
  ID id_data;
@@ -256,7 +256,7 @@ void Init_isomorfeus_ferret_ext(void) {
256
256
  id_lt = rb_intern("<");
257
257
 
258
258
  id_mkdir_p = rb_intern("mkdir_p");
259
- id_is_directory = rb_intern("directory?");
259
+ id_exist = rb_intern("exist?");
260
260
  id_close = rb_intern("close");
261
261
 
262
262
  id_cclass = rb_intern("cclass");
@@ -13,7 +13,7 @@ extern ID id_eql;
13
13
  extern ID id_capacity;
14
14
  extern ID id_less_than;
15
15
  extern ID id_lt;
16
- extern ID id_is_directory;
16
+ extern ID id_exist;
17
17
  extern ID id_close;
18
18
  extern ID id_cclass;
19
19
  extern ID id_data;