diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-05-21 19:48:09 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-05-23 13:55:15 +0200 |
commit | 4cb0d1561cf41551d4ddc418f8666388b90318b9 (patch) | |
tree | 2efb1dbc7a8627893b3b0ddd9f95d08dda6b7e8f /tests | |
parent | fa9e0e2cbbcb0733e86a47f489296f58fbcf34af (diff) | |
download | sink-4cb0d1561cf41551d4ddc418f8666388b90318b9.tar.gz sink-4cb0d1561cf41551d4ddc418f8666388b90318b9.zip |
Fixed use of mdb_dbi_open
There can only ever be one transaction using mdb_dbi_open running,
and that transaction must commit or abort before any other transaction
attempts to use mdb_dbi_open.
Use delayed dbi merging with write transactions and a temporary
transaction for read transactions.
We now protect dbi initialization with a mutex and immediately update
the sDbis hash. This assumes that the created dbis are indeed
We can still violate the only one transaction may use mdb_dbi_open rule
if we start a read-only transaction after the write transaction, before
the write transaction commits.
It does not seem to be something we actually do though.
Opening dbis on environment init is further separated out, so we don't
end up in the regular openDatabase codepath at all.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/dbwriter.cpp | 6 | ||||
-rw-r--r-- | tests/storagetest.cpp | 129 |
2 files changed, 110 insertions, 25 deletions
diff --git a/tests/dbwriter.cpp b/tests/dbwriter.cpp index 902a607..3045eac 100644 --- a/tests/dbwriter.cpp +++ b/tests/dbwriter.cpp | |||
@@ -18,7 +18,11 @@ int main(int argc, char *argv[]) | |||
18 | } | 18 | } |
19 | 19 | ||
20 | qWarning() << "Creating db: " << testDataPath << dbName << count; | 20 | qWarning() << "Creating db: " << testDataPath << dbName << count; |
21 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 21 | QMap<QByteArray, int> dbs = {{"a", 0}, {"b", 0}, {"c", 0}, {"p", 0}, {"q", 0}, {"db", 0}}; |
22 | for (int d = 0; d < 40; d++) { | ||
23 | dbs.insert("db" + QByteArray::number(d), 0); | ||
24 | } | ||
25 | Sink::Storage::DataStore store(testDataPath, {dbName, dbs}, Sink::Storage::DataStore::ReadWrite); | ||
22 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 26 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
23 | for (int i = 0; i < count; i++) { | 27 | for (int i = 0; i < count; i++) { |
24 | if (!transaction) { | 28 | if (!transaction) { |
diff --git a/tests/storagetest.cpp b/tests/storagetest.cpp index 802947f..618f9d0 100644 --- a/tests/storagetest.cpp +++ b/tests/storagetest.cpp | |||
@@ -16,12 +16,12 @@ class StorageTest : public QObject | |||
16 | Q_OBJECT | 16 | Q_OBJECT |
17 | private: | 17 | private: |
18 | QString testDataPath; | 18 | QString testDataPath; |
19 | QString dbName; | 19 | QByteArray dbName; |
20 | const char *keyPrefix = "key"; | 20 | const char *keyPrefix = "key"; |
21 | 21 | ||
22 | void populate(int count) | 22 | void populate(int count) |
23 | { | 23 | { |
24 | Sink::Storage::DataStore storage(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 24 | Sink::Storage::DataStore storage(testDataPath, {dbName, {{"default", 0}}}, Sink::Storage::DataStore::ReadWrite); |
25 | auto transaction = storage.createTransaction(Sink::Storage::DataStore::ReadWrite); | 25 | auto transaction = storage.createTransaction(Sink::Storage::DataStore::ReadWrite); |
26 | for (int i = 0; i < count; i++) { | 26 | for (int i = 0; i < count; i++) { |
27 | // This should perhaps become an implementation detail of the db? | 27 | // This should perhaps become an implementation detail of the db? |
@@ -63,20 +63,20 @@ private slots: | |||
63 | { | 63 | { |
64 | testDataPath = "./testdb"; | 64 | testDataPath = "./testdb"; |
65 | dbName = "test"; | 65 | dbName = "test"; |
66 | Sink::Storage::DataStore storage(testDataPath, dbName); | 66 | Sink::Storage::DataStore storage(testDataPath, {dbName, {{"default", 0}}}); |
67 | storage.removeFromDisk(); | 67 | storage.removeFromDisk(); |
68 | } | 68 | } |
69 | 69 | ||
70 | void cleanup() | 70 | void cleanup() |
71 | { | 71 | { |
72 | Sink::Storage::DataStore storage(testDataPath, dbName); | 72 | Sink::Storage::DataStore storage(testDataPath, {dbName, {{"default", 0}}}); |
73 | storage.removeFromDisk(); | 73 | storage.removeFromDisk(); |
74 | } | 74 | } |
75 | 75 | ||
76 | void testCleanup() | 76 | void testCleanup() |
77 | { | 77 | { |
78 | populate(1); | 78 | populate(1); |
79 | Sink::Storage::DataStore storage(testDataPath, dbName); | 79 | Sink::Storage::DataStore storage(testDataPath, {dbName, {{"default", 0}}}); |
80 | storage.removeFromDisk(); | 80 | storage.removeFromDisk(); |
81 | QFileInfo info(testDataPath + "/" + dbName); | 81 | QFileInfo info(testDataPath + "/" + dbName); |
82 | QVERIFY(!info.exists()); | 82 | QVERIFY(!info.exists()); |
@@ -163,7 +163,7 @@ private slots: | |||
163 | { | 163 | { |
164 | bool gotResult = false; | 164 | bool gotResult = false; |
165 | bool gotError = false; | 165 | bool gotError = false; |
166 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 166 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"default", 0}}}, Sink::Storage::DataStore::ReadWrite); |
167 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadOnly); | 167 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadOnly); |
168 | auto db = transaction.openDatabase("default", [&](const Sink::Storage::DataStore::Error &error) { | 168 | auto db = transaction.openDatabase("default", [&](const Sink::Storage::DataStore::Error &error) { |
169 | qDebug() << error.message; | 169 | qDebug() << error.message; |
@@ -227,7 +227,7 @@ private slots: | |||
227 | { | 227 | { |
228 | bool gotResult = false; | 228 | bool gotResult = false; |
229 | bool gotError = false; | 229 | bool gotError = false; |
230 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 230 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"default", 0}}}, Sink::Storage::DataStore::ReadWrite); |
231 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 231 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
232 | auto db = transaction.openDatabase("default", nullptr, false); | 232 | auto db = transaction.openDatabase("default", nullptr, false); |
233 | db.write("key", "value"); | 233 | db.write("key", "value"); |
@@ -252,7 +252,7 @@ private slots: | |||
252 | { | 252 | { |
253 | bool gotResult = false; | 253 | bool gotResult = false; |
254 | bool gotError = false; | 254 | bool gotError = false; |
255 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 255 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"default", 0x04}}}, Sink::Storage::DataStore::ReadWrite); |
256 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 256 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
257 | auto db = transaction.openDatabase("default", nullptr, true); | 257 | auto db = transaction.openDatabase("default", nullptr, true); |
258 | db.write("key", "value1"); | 258 | db.write("key", "value1"); |
@@ -295,7 +295,7 @@ private slots: | |||
295 | void testWriteToNamedDb() | 295 | void testWriteToNamedDb() |
296 | { | 296 | { |
297 | bool gotError = false; | 297 | bool gotError = false; |
298 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 298 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
299 | store.createTransaction(Sink::Storage::DataStore::ReadWrite) | 299 | store.createTransaction(Sink::Storage::DataStore::ReadWrite) |
300 | .openDatabase("test") | 300 | .openDatabase("test") |
301 | .write("key1", "value1", [&](const Sink::Storage::DataStore::Error &error) { | 301 | .write("key1", "value1", [&](const Sink::Storage::DataStore::Error &error) { |
@@ -308,7 +308,8 @@ private slots: | |||
308 | void testWriteDuplicatesToNamedDb() | 308 | void testWriteDuplicatesToNamedDb() |
309 | { | 309 | { |
310 | bool gotError = false; | 310 | bool gotError = false; |
311 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 311 | |
312 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); | ||
312 | store.createTransaction(Sink::Storage::DataStore::ReadWrite) | 313 | store.createTransaction(Sink::Storage::DataStore::ReadWrite) |
313 | .openDatabase("test", nullptr, true) | 314 | .openDatabase("test", nullptr, true) |
314 | .write("key1", "value1", [&](const Sink::Storage::DataStore::Error &error) { | 315 | .write("key1", "value1", [&](const Sink::Storage::DataStore::Error &error) { |
@@ -321,7 +322,7 @@ private slots: | |||
321 | // By default we want only exact matches | 322 | // By default we want only exact matches |
322 | void testSubstringKeys() | 323 | void testSubstringKeys() |
323 | { | 324 | { |
324 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 325 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0x04}}}, Sink::Storage::DataStore::ReadWrite); |
325 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 326 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
326 | auto db = transaction.openDatabase("test", nullptr, true); | 327 | auto db = transaction.openDatabase("test", nullptr, true); |
327 | db.write("sub", "value1"); | 328 | db.write("sub", "value1"); |
@@ -333,7 +334,7 @@ private slots: | |||
333 | 334 | ||
334 | void testFindSubstringKeys() | 335 | void testFindSubstringKeys() |
335 | { | 336 | { |
336 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 337 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
337 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 338 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
338 | auto db = transaction.openDatabase("test", nullptr, false); | 339 | auto db = transaction.openDatabase("test", nullptr, false); |
339 | db.write("sub", "value1"); | 340 | db.write("sub", "value1"); |
@@ -346,7 +347,7 @@ private slots: | |||
346 | 347 | ||
347 | void testFindSubstringKeysWithDuplicatesEnabled() | 348 | void testFindSubstringKeysWithDuplicatesEnabled() |
348 | { | 349 | { |
349 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 350 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
350 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 351 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
351 | auto db = transaction.openDatabase("test", nullptr, true); | 352 | auto db = transaction.openDatabase("test", nullptr, true); |
352 | db.write("sub", "value1"); | 353 | db.write("sub", "value1"); |
@@ -359,7 +360,7 @@ private slots: | |||
359 | 360 | ||
360 | void testKeySorting() | 361 | void testKeySorting() |
361 | { | 362 | { |
362 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 363 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
363 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 364 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
364 | auto db = transaction.openDatabase("test", nullptr, false); | 365 | auto db = transaction.openDatabase("test", nullptr, false); |
365 | db.write("sub_2", "value2"); | 366 | db.write("sub_2", "value2"); |
@@ -380,7 +381,7 @@ private slots: | |||
380 | // Ensure we don't retrieve a key that is greater than the current key. We only want equal keys. | 381 | // Ensure we don't retrieve a key that is greater than the current key. We only want equal keys. |
381 | void testKeyRange() | 382 | void testKeyRange() |
382 | { | 383 | { |
383 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 384 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
384 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 385 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
385 | auto db = transaction.openDatabase("test", nullptr, true); | 386 | auto db = transaction.openDatabase("test", nullptr, true); |
386 | db.write("sub1", "value1"); | 387 | db.write("sub1", "value1"); |
@@ -391,7 +392,7 @@ private slots: | |||
391 | 392 | ||
392 | void testFindLatest() | 393 | void testFindLatest() |
393 | { | 394 | { |
394 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 395 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
395 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 396 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
396 | auto db = transaction.openDatabase("test", nullptr, false); | 397 | auto db = transaction.openDatabase("test", nullptr, false); |
397 | db.write("sub1", "value1"); | 398 | db.write("sub1", "value1"); |
@@ -406,7 +407,7 @@ private slots: | |||
406 | 407 | ||
407 | void testFindLatestInSingle() | 408 | void testFindLatestInSingle() |
408 | { | 409 | { |
409 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 410 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
410 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 411 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
411 | auto db = transaction.openDatabase("test", nullptr, false); | 412 | auto db = transaction.openDatabase("test", nullptr, false); |
412 | db.write("sub2", "value2"); | 413 | db.write("sub2", "value2"); |
@@ -418,7 +419,7 @@ private slots: | |||
418 | 419 | ||
419 | void testFindLast() | 420 | void testFindLast() |
420 | { | 421 | { |
421 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 422 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
422 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 423 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
423 | auto db = transaction.openDatabase("test", nullptr, false); | 424 | auto db = transaction.openDatabase("test", nullptr, false); |
424 | db.write("sub2", "value2"); | 425 | db.write("sub2", "value2"); |
@@ -429,9 +430,18 @@ private slots: | |||
429 | QCOMPARE(result, QByteArray("value3")); | 430 | QCOMPARE(result, QByteArray("value3")); |
430 | } | 431 | } |
431 | 432 | ||
433 | static QMap<QByteArray, int> baseDbs() | ||
434 | { | ||
435 | return {{"revisionType", 0}, | ||
436 | {"revisions", 0}, | ||
437 | {"uids", 0}, | ||
438 | {"default", 0}, | ||
439 | {"__flagtable", 0}}; | ||
440 | } | ||
441 | |||
432 | void testRecordRevision() | 442 | void testRecordRevision() |
433 | { | 443 | { |
434 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 444 | Sink::Storage::DataStore store(testDataPath, {dbName, baseDbs()}, Sink::Storage::DataStore::ReadWrite); |
435 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 445 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
436 | Sink::Storage::DataStore::recordRevision(transaction, 1, "uid", "type"); | 446 | Sink::Storage::DataStore::recordRevision(transaction, 1, "uid", "type"); |
437 | QCOMPARE(Sink::Storage::DataStore::getTypeFromRevision(transaction, 1), QByteArray("type")); | 447 | QCOMPARE(Sink::Storage::DataStore::getTypeFromRevision(transaction, 1), QByteArray("type")); |
@@ -440,7 +450,7 @@ private slots: | |||
440 | 450 | ||
441 | void testRecordRevisionSorting() | 451 | void testRecordRevisionSorting() |
442 | { | 452 | { |
443 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 453 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"test", 0}}}, Sink::Storage::DataStore::ReadWrite); |
444 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 454 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
445 | QByteArray result; | 455 | QByteArray result; |
446 | auto db = transaction.openDatabase("test", nullptr, false); | 456 | auto db = transaction.openDatabase("test", nullptr, false); |
@@ -463,7 +473,7 @@ private slots: | |||
463 | return result; | 473 | return result; |
464 | }; | 474 | }; |
465 | { | 475 | { |
466 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 476 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"testTransactionVisibility", 0}}}, Sink::Storage::DataStore::ReadWrite); |
467 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 477 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
468 | 478 | ||
469 | auto db = transaction.openDatabase("testTransactionVisibility", nullptr, false); | 479 | auto db = transaction.openDatabase("testTransactionVisibility", nullptr, false); |
@@ -489,7 +499,7 @@ private slots: | |||
489 | 499 | ||
490 | void testCopyTransaction() | 500 | void testCopyTransaction() |
491 | { | 501 | { |
492 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 502 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"a", 0}, {"b", 0}, {"c", 0}}}, Sink::Storage::DataStore::ReadWrite); |
493 | { | 503 | { |
494 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 504 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
495 | transaction.openDatabase("a", nullptr, false); | 505 | transaction.openDatabase("a", nullptr, false); |
@@ -516,7 +526,6 @@ private slots: | |||
516 | */ | 526 | */ |
517 | void testReadDuringExternalProcessWrite() | 527 | void testReadDuringExternalProcessWrite() |
518 | { | 528 | { |
519 | QSKIP("Not running multiprocess test"); | ||
520 | 529 | ||
521 | QList<QFuture<void>> futures; | 530 | QList<QFuture<void>> futures; |
522 | for (int i = 0; i < 5; i++) { | 531 | for (int i = 0; i < 5; i++) { |
@@ -545,7 +554,17 @@ private slots: | |||
545 | 554 | ||
546 | void testRecordUid() | 555 | void testRecordUid() |
547 | { | 556 | { |
548 | Sink::Storage::DataStore store(testDataPath, dbName, Sink::Storage::DataStore::ReadWrite); | 557 | |
558 | QMap<QByteArray, int> dbs = {{"revisionType", 0}, | ||
559 | {"revisions", 0}, | ||
560 | {"uids", 0}, | ||
561 | {"default", 0}, | ||
562 | {"__flagtable", 0}, | ||
563 | {"typeuids", 0}, | ||
564 | {"type2uids", 0} | ||
565 | }; | ||
566 | |||
567 | Sink::Storage::DataStore store(testDataPath, {dbName, dbs}, Sink::Storage::DataStore::ReadWrite); | ||
549 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | 568 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); |
550 | Sink::Storage::DataStore::recordUid(transaction, "uid1", "type"); | 569 | Sink::Storage::DataStore::recordUid(transaction, "uid1", "type"); |
551 | Sink::Storage::DataStore::recordUid(transaction, "uid2", "type"); | 570 | Sink::Storage::DataStore::recordUid(transaction, "uid2", "type"); |
@@ -571,6 +590,68 @@ private slots: | |||
571 | QCOMPARE(uids, expected); | 590 | QCOMPARE(uids, expected); |
572 | } | 591 | } |
573 | } | 592 | } |
593 | |||
594 | void testDbiVisibility() | ||
595 | { | ||
596 | auto readValue = [](const Sink::Storage::DataStore::NamedDatabase &db, const QByteArray) { | ||
597 | QByteArray result; | ||
598 | db.scan("key1", [&](const QByteArray &, const QByteArray &value) { | ||
599 | result = value; | ||
600 | return true; | ||
601 | }); | ||
602 | return result; | ||
603 | }; | ||
604 | { | ||
605 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"testTransactionVisibility", 0}}}, Sink::Storage::DataStore::ReadWrite); | ||
606 | auto transaction = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | ||
607 | |||
608 | auto db = transaction.openDatabase("testTransactionVisibility", nullptr, false); | ||
609 | db.write("key1", "foo"); | ||
610 | QCOMPARE(readValue(db, "key1"), QByteArray("foo")); | ||
611 | transaction.commit(); | ||
612 | } | ||
613 | Sink::Storage::DataStore::clearEnv(); | ||
614 | |||
615 | //Try to read-only dynamic opening of the db. | ||
616 | //This is the case if we don't have all databases available upon initializatoin and we don't (e.g. because the db hasn't been created yet) | ||
617 | { | ||
618 | // Trick the db into not loading all dbs by passing in a bogus layout. | ||
619 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadOnly); | ||
620 | |||
621 | //This transaction should open the dbi | ||
622 | auto transaction2 = store.createTransaction(Sink::Storage::DataStore::ReadOnly); | ||
623 | auto db2 = transaction2.openDatabase("testTransactionVisibility", nullptr, false); | ||
624 | QCOMPARE(readValue(db2, "key1"), QByteArray("foo")); | ||
625 | |||
626 | //This transaction should have the dbi available | ||
627 | auto transaction3 = store.createTransaction(Sink::Storage::DataStore::ReadOnly); | ||
628 | auto db3 = transaction3.openDatabase("testTransactionVisibility", nullptr, false); | ||
629 | QCOMPARE(readValue(db3, "key1"), QByteArray("foo")); | ||
630 | } | ||
631 | |||
632 | Sink::Storage::DataStore::clearEnv(); | ||
633 | //Try to read-write dynamic opening of the db. | ||
634 | //This is the case if we don't have all databases available upon initializatoin and we don't (e.g. because the db hasn't been created yet) | ||
635 | { | ||
636 | // Trick the db into not loading all dbs by passing in a bogus layout. | ||
637 | Sink::Storage::DataStore store(testDataPath, {dbName, {{"bogus", 0}}}, Sink::Storage::DataStore::ReadWrite); | ||
638 | |||
639 | //This transaction should open the dbi | ||
640 | auto transaction2 = store.createTransaction(Sink::Storage::DataStore::ReadWrite); | ||
641 | auto db2 = transaction2.openDatabase("testTransactionVisibility", nullptr, false); | ||
642 | QCOMPARE(readValue(db2, "key1"), QByteArray("foo")); | ||
643 | |||
644 | //This transaction should have the dbi available (creating two write transactions obviously doesn't work) | ||
645 | //NOTE: we don't support this scenario. A write transaction must commit or abort before a read transaction opens the same database. | ||
646 | // auto transaction3 = store.createTransaction(Sink::Storage::DataStore::ReadOnly); | ||
647 | // auto db3 = transaction3.openDatabase("testTransactionVisibility", nullptr, false); | ||
648 | // QCOMPARE(readValue(db3, "key1"), QByteArray("foo")); | ||
649 | |||
650 | //Ensure we can still open further dbis in the write transaction | ||
651 | auto db4 = transaction2.openDatabase("anotherDb", nullptr, false); | ||
652 | } | ||
653 | |||
654 | } | ||
574 | }; | 655 | }; |
575 | 656 | ||
576 | QTEST_MAIN(StorageTest) | 657 | QTEST_MAIN(StorageTest) |