-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdbnames.h
173 lines (135 loc) · 5.11 KB
/
dbnames.h
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#ifndef SXPDB_DB_NAMES_H
#define SXPDB_DB_NAMES_H
#include <vector>
#include <filesystem>
#include <unistd.h>
#include "table.h"
#include "robin_hood.h"
class DBNames {
private:
pid_t pid;
bool write_mode = true;
uint64_t last_written = 0;
bool new_dbnames = false;
mutable std::vector<uint32_t> current_ids;
std::vector<robin_hood::unordered_set<uint32_t>> dbs;
UniqTextTable db_names;
std::unique_ptr<VSizeTable<std::vector<uint32_t>>> dbs_table;
fs::path base_path = "";
public:
DBNames() : pid(getpid()) {}
DBNames(const fs::path& base_path_, bool write = true) : pid(getpid()), write_mode(write) {
open(base_path_, write);
}
void open(const fs::path& base_path_, bool write = true) {
write_mode = write;
base_path = fs::absolute(base_path_);
// open the table only in write mode or
// if it already exists
if(write_mode || fs::exists(base_path / "dbs.bin")) {
dbs_table = std::make_unique<VSizeTable<std::vector<uint32_t>>>(base_path / "dbs.bin", write_mode);
db_names.open(base_path / "dbnames.bin", write_mode);
}
// Populate db names in write_mode
// In other mode, we just directly read from the db_table if it exists
if(write_mode) {
dbs.clear();
dbs.resize(dbs_table->nb_values());
for(uint64_t i = 0; i < dbs_table->nb_values() ; i++) {
const std::vector<uint32_t>& names = dbs_table->read(i);
assert(names.size() > 0);
// 0 is the place holder for no db
if(names.size() != 1 || names[0] != 0) {
dbs[i].reserve(names.size());
dbs[i].insert(dbs[i].end(), names.begin()< names.end());
}
}
dbs_table.reset();
}
if(db_names.nb_values() == 0) {
db_names.append("");
}
last_written = dbs.size();// or the number of value in the table, before?
}
void add_dbname(uint64_t index, const std::string& dbname) {
assert(write_mode);
assert(pid == getpid());
if(index > dbs.size()) {
Rf_error("Cannot add a db name for a value that was not recorded in the main table."
" Last index is %lu, but the index of that new db name is %lu.\n",
dbs.size(), index);
}
uint32_t db_id = db_names.append_index(dbname);
if(index < dbs.size()) {
auto res = dbs[index].insert(db_id);
if(res.second) {
new_dbnames = true;
}
}
else if(index == dbs.size()) {
robin_hood::unordered_set<uint32_t> ids{db_id};
dbs.push_back(ids);
new_dbnames = true;
}
}
void fill_dbnames(uint64_t last_index, const std::string& dbname) {
assert(write_mode);
assert(pid == getpid());
for(uint64_t i = 0; i < last_index ; i++) {
add_dbname(i, dbname);
}
}
const std::vector<uint32_t>& get_dbs(uint64_t index) const {
if(write_mode) {
if(index < dbs.size()) {
current_ids.clear();
auto ids_set = dbs[index];
current_ids.insert(current_ids.end(), ids_set.begin(), ids_set.end());
return current_ids;
}
else {
current_ids.clear();
return current_ids;
}
}
else {
return dbs_table->read(index);
}
}
const std::string& dbname(uint32_t i) const { return db_names.read(i); }
const fs::path& get_base_path() const { return base_path; }
uint32_t nb_dbnames() const { return db_names.nb_values(); }
const SEXP dbnames_cache() const { return db_names.to_sexp(); }
virtual ~DBNames() {
// TODO
if(write_mode && pid == getpid() && new_dbnames) {
fs::rename(base_path / "dbs.bin", base_path / "dbs-old.bin");
fs::rename(base_path / "dbs.conf", base_path / "dbs-old.conf");
fs::rename(base_path / "dbs_offsets.bin", base_path / "dbs_offsets-old.bin");
fs::rename(base_path / "dbs_offsets.conf", base_path / "dbs_offsets-old.conf");
VSizeTable<std::vector<uint32_t>> dbs_table(base_path / "dbs.bin");
for(const auto& ids : dbs) {
current_ids.clear();
current_ids.insert(current_ids.end(), ids.begin(), ids.end());
dbs_table.append(current_ids);
}
dbs_table.flush();
fs::remove(base_path / "dbs-old.bin");
fs::remove(base_path / "dbs-old.conf");
fs::remove(base_path / "dbs_offsets-old.bin");
fs::remove(base_path / "dbs_offsets-old.conf");
}
}
uint64_t nb_values() const {
if(write_mode && last_written > 0 ) {
return dbs.size();
}
else if(write_mode && last_written == 0) {
return 0;
}
else {
return dbs_table->nb_values();
}
}
};
#endif