File: test_persistence.cpp

package info (click to toggle)
duckdb 1.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 299,196 kB
  • sloc: cpp: 865,414; ansic: 57,292; python: 18,871; sql: 12,663; lisp: 11,751; yacc: 7,412; lex: 1,682; sh: 747; makefile: 558
file content (70 lines) | stat: -rw-r--r-- 1,896 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "catch.hpp"
#include "duckdb/common/file_system.hpp"
#include "duckdb.hpp"
#include "test_helpers.hpp"

#include <signal.h>
#include <sys/mman.h>
#include <unistd.h>

using namespace duckdb;
using namespace std;

TEST_CASE("Test transactional integrity when facing process aborts", "[persistence][.]") {
	duckdb::unique_ptr<FileSystem> fs = FileSystem::CreateLocal();

	// shared memory to keep track of insertions
	size_t *count = (size_t *)mmap(NULL, sizeof(size_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0);

	string db_folder_parent = TestCreatePath("llstorage");
	if (fs->DirectoryExists(db_folder_parent)) {
		fs->RemoveDirectory(db_folder_parent);
	}
	fs->CreateDirectory(db_folder_parent);

	string db_folder = fs->JoinPath(db_folder_parent, "dbfolder");
	{
		DuckDB db(db_folder);
		Connection con(db);
		con.Query("CREATE TABLE a (i INTEGER)");
	}

	// fork away a child to be mercilessy shot in a bit
	pid_t pid = fork();

	if (pid == 0) { // child process
		DuckDB db(db_folder);
		Connection con(db);
		while (true) {
			con.Query("INSERT INTO a VALUES(42)");
			(*count)++;
		}
	} else if (pid > 0) { // parent process
		// wait until child has inserted at least 1000 rows
		while (*count < 1000) {
			usleep(100);
		}
		if (kill(pid, SIGKILL) != 0) {
			FAIL();
		}
		duckdb::unique_ptr<DuckDB> db;
		// it may take some time for the OS to reclaim the lock
		// loop and wait until the database is successfully started again
		for (size_t i = 0; i < 1000; i++) {
			usleep(10000);
			try {
				db = make_uniq<DuckDB>(db_folder);
			} catch (...) {
			}
			if (db) {
				break;
			}
		}
		Connection con(*db);
		auto res = con.Query("SELECT COUNT(*) FROM a");
		// there may be an off-by-one if we kill exactly between query and count increment
		REQUIRE(std::abs((int64_t)(res->GetValue(0, 0).GetValue<int64_t>() - *count)) < 2);
	} else {
		FAIL();
	}
}