Skip to content

Commit 69b325e

Browse files
committed
Add Read only Mode, does not allow inserts
1 parent 6d005d3 commit 69b325e

File tree

5 files changed

+80
-14
lines changed

5 files changed

+80
-14
lines changed

examples/example.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ int main()
2727
0.5f,
2828
ec);
2929
store db;
30-
db.open(dat_path, key_path, log_path, ec);
30+
db.open(dat_path, key_path, log_path, store::open_mode::read_write, ec);
3131
char data = 0;
3232
// Insert
3333
for(key_type i = 0; i < N; ++i)

include/nudb/_experimental/test/test_store.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ basic_test_store<File>::basic_test_store(
286286
, openf_(
287287
[this, args...](error_code& ec)
288288
{
289-
db.open(dp, kp, lp, ec, args...);
289+
db.open(dp, kp, lp, basic_store<Hasher, File>::open_mode::read_write, ec, args...);
290290
})
291291
, dirp(td_.path())
292292
, dp(td_.file("nudb.dat"))

include/nudb/basic_store.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ class basic_store
5252
using hash_type = Hasher;
5353
using file_type = File;
5454

55+
enum class open_mode {
56+
/// Open the database for both read and write access
57+
read_write,
58+
59+
/// Open the database for reach access only
60+
read
61+
};
62+
5563
private:
5664
using clock_type =
5765
std::chrono::steady_clock;
@@ -90,9 +98,14 @@ class basic_store
9098
path_type const& dp_, path_type const& kp_,
9199
path_type const& lp_,
92100
detail::key_file_header const& kh_);
101+
102+
state(File&& df_, File&& kf_,
103+
path_type const& dp_, path_type const& kp_,
104+
detail::key_file_header const& kh_);
93105
};
94106

95107
bool open_ = false;
108+
bool is_writable_;
96109

97110
// Use optional because some
98111
// members cannot be default-constructed.
@@ -173,6 +186,19 @@ class basic_store
173186
return open_;
174187
}
175188

189+
/** Returns `true` if the database is writable
190+
191+
@par Thread safety
192+
193+
Safe to call concurrently with any function
194+
except @ref open.
195+
*/
196+
bool
197+
is_writable() const
198+
{
199+
return is_writable_;
200+
}
201+
176202
/** Return the path to the data file.
177203
178204
@par Requirements
@@ -329,6 +355,8 @@ class basic_store
329355
330356
@param log_path The path to the log file.
331357
358+
@param open_mode Mode of database access
359+
332360
@param ec Set to the error, if any occurred.
333361
334362
@param args Optional arguments passed to @b File constructors.
@@ -340,6 +368,7 @@ class basic_store
340368
path_type const& dat_path,
341369
path_type const& key_path,
342370
path_type const& log_path,
371+
open_mode mode,
343372
error_code& ec,
344373
Args&&... args);
345374

include/nudb/impl/basic_store.ipp

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,25 @@ state(File&& df_, File&& kf_, File&& lf_,
4646
"File requirements not met");
4747
}
4848

49+
template<class Hasher, class File>
50+
basic_store<Hasher, File>::state::
51+
state(File&& df_, File&& kf_,
52+
path_type const& dp_, path_type const& kp_,
53+
detail::key_file_header const& kh_)
54+
: df(std::move(df_))
55+
, kf(std::move(kf_))
56+
, dp(dp_)
57+
, kp(kp_)
58+
, hasher(kh_.salt)
59+
, p0(kh_.key_size, "p0")
60+
, p1(kh_.key_size, "p1")
61+
, c1(kh_.key_size, kh_.block_size, "c1")
62+
, kh(kh_)
63+
{
64+
BOOST_STATIC_ASSERT_MSG(is_File<File>::value,
65+
"File requirements not met");
66+
}
67+
4968
//------------------------------------------------------------------------------
5069

5170
template<class Hasher, class File>
@@ -122,9 +141,12 @@ open(
122141
path_type const& dat_path,
123142
path_type const& key_path,
124143
path_type const& log_path,
144+
open_mode mode,
125145
error_code& ec,
126146
Args&&... args)
127147
{
148+
bool writable = mode == open_mode::read_write;
149+
128150
static_assert(is_Hasher<Hasher>::value,
129151
"Hasher requirements not met");
130152
using namespace detail;
@@ -138,17 +160,23 @@ open(
138160
File df(args...);
139161
File kf(args...);
140162
File lf(args...);
141-
df.open(file_mode::append, dat_path, ec);
142-
if(ec)
143-
return;
144-
kf.open(file_mode::write, key_path, ec);
163+
df.open(writable ? file_mode::append : file_mode::read,
164+
dat_path, ec);
145165
if(ec)
146166
return;
147-
lf.create(file_mode::append, log_path, ec);
167+
kf.open(writable ? file_mode::write : file_mode::read,
168+
key_path, ec);
148169
if(ec)
149170
return;
150-
// VFALCO TODO Erase empty log file if this
151-
// function subsequently fails.
171+
172+
if(writable){
173+
lf.create(file_mode::append, log_path, ec);
174+
if(ec)
175+
return;
176+
// VFALCO TODO Erase empty log file if this
177+
// function subsequently fails.
178+
}
179+
152180
dat_file_header dh;
153181
read(df, dh, ec);
154182
if(ec)
@@ -167,8 +195,12 @@ open(
167195
if(ec)
168196
return;
169197
boost::optional<state> s;
170-
s.emplace(std::move(df), std::move(kf), std::move(lf),
171-
dat_path, key_path, log_path, kh);
198+
if(writable)
199+
s.emplace(std::move(df), std::move(kf), std::move(lf),
200+
dat_path, key_path, log_path, kh);
201+
else
202+
s.emplace(std::move(df), std::move(kf),
203+
dat_path, key_path, kh);
172204
thresh_ = std::max<std::size_t>(65536UL,
173205
kh.load_factor * kh.capacity);
174206
frac_ = thresh_ / 2;
@@ -180,10 +212,13 @@ open(
180212
ec = error::short_key_file;
181213
return;
182214
}
183-
dataWriteSize_ = 32 * nudb::block_size(dat_path);
184-
logWriteSize_ = 32 * nudb::block_size(log_path);
215+
if(writable){
216+
dataWriteSize_ = 32 * nudb::block_size(dat_path);
217+
logWriteSize_ = 32 * nudb::block_size(log_path);
218+
}
185219
s_.emplace(std::move(*s));
186220
open_ = true;
221+
is_writable_ = writable;
187222
ctx_->insert(*this);
188223
}
189224

test/recover.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ class basic_recover_test : public boost::beast::unit_test::suite
6060
if(ec)
6161
return;
6262
basic_store<xxhasher, fail_file<native_file>> db;
63-
db.open(ts.dp, ts.kp, ts.lp, ec, c);
63+
db.open(ts.dp, ts.kp, ts.lp,
64+
basic_store<xxhasher, fail_file<native_file>>::open_mode::read_write,
65+
ec, c);
6466
if(ec)
6567
return;
6668
if(! BEAST_EXPECT(db.appnum() == ts.appnum))

0 commit comments

Comments
 (0)