Skip to content

Commit 7ca757c

Browse files
committed
recovery files added
1 parent 748f604 commit 7ca757c

21 files changed

Lines changed: 1786 additions & 28 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,4 @@ CMAKE_BINARY_DIR
5454
.cargo
5555

5656
# Cargo build directory
57-
/target
57+
/target

Cargo.lock

Lines changed: 33 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/rust/config/src/seg.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use serde::{Deserialize, Serialize};
88

99
const MB: usize = 1024 * 1024;
1010

11+
// restore and graceful shutdown options
12+
const RESTORE: bool = false;
13+
const GRACEFUL_SHUTDOWN: bool = false;
14+
1115
// defaults for hashtable
1216
const HASH_POWER: u8 = 16;
1317
const OVERFLOW_FACTOR: f64 = 1.0;
@@ -24,9 +28,18 @@ const COMPACT_TARGET: usize = 2;
2428
const MERGE_TARGET: usize = 4;
2529
const MERGE_MAX: usize = 8;
2630

27-
// datapool
31+
// datapool (`Segments.data`)
2832
const DATAPOOL_PATH: Option<&str> = None;
2933

34+
// `Segments` fields
35+
const SEGMENT_FIELDS_PATH: Option<&str> = None;
36+
37+
// ttl buckets
38+
const TTL_BUCKETS_PATH: Option<&str> = None;
39+
40+
// hashtable
41+
const HASHTABLE_PATH: Option<&str> = None;
42+
3043
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
3144
pub enum Eviction {
3245
None,
@@ -39,6 +52,14 @@ pub enum Eviction {
3952
}
4053

4154
// helper functions for default values
55+
fn restore() -> bool {
56+
RESTORE
57+
}
58+
59+
fn graceful_shutdown() -> bool {
60+
GRACEFUL_SHUTDOWN
61+
}
62+
4263
fn hash_power() -> u8 {
4364
HASH_POWER
4465
}
@@ -75,9 +96,25 @@ fn datapool_path() -> Option<String> {
7596
DATAPOOL_PATH.map(|v| v.to_string())
7697
}
7798

99+
fn segments_fields_path() -> Option<String> {
100+
SEGMENT_FIELDS_PATH.map(|v| v.to_string())
101+
}
102+
103+
fn ttl_buckets_path() -> Option<String> {
104+
TTL_BUCKETS_PATH.map(|v| v.to_string())
105+
}
106+
107+
fn hashtable_path() -> Option<String> {
108+
HASHTABLE_PATH.map(|v| v.to_string())
109+
}
110+
78111
// definitions
79112
#[derive(Serialize, Deserialize, Debug)]
80113
pub struct Seg {
114+
#[serde(default = "restore")]
115+
restore: bool,
116+
#[serde(default = "graceful_shutdown")]
117+
graceful_shutdown: bool,
81118
#[serde(default = "hash_power")]
82119
hash_power: u8,
83120
#[serde(default = "overflow_factor")]
@@ -96,11 +133,19 @@ pub struct Seg {
96133
compact_target: usize,
97134
#[serde(default = "datapool_path")]
98135
datapool_path: Option<String>,
136+
#[serde(default = "segments_fields_path")]
137+
segments_fields_path: Option<String>,
138+
#[serde(default = "ttl_buckets_path")]
139+
ttl_buckets_path: Option<String>,
140+
#[serde(default = "hashtable_path")]
141+
hashtable_path: Option<String>,
99142
}
100143

101144
impl Default for Seg {
102145
fn default() -> Self {
103146
Self {
147+
restore: restore(),
148+
graceful_shutdown: graceful_shutdown(),
104149
hash_power: hash_power(),
105150
overflow_factor: overflow_factor(),
106151
heap_size: heap_size(),
@@ -110,12 +155,21 @@ impl Default for Seg {
110155
merge_max: merge_max(),
111156
compact_target: compact_target(),
112157
datapool_path: datapool_path(),
158+
segments_fields_path: segments_fields_path(),
159+
ttl_buckets_path: ttl_buckets_path(),
160+
hashtable_path: hashtable_path(),
113161
}
114162
}
115163
}
116164

117165
// implementation
118166
impl Seg {
167+
pub fn restore(&self) -> bool {
168+
self.restore
169+
}
170+
pub fn graceful_shutdown(&self) -> bool {
171+
self.graceful_shutdown
172+
}
119173
pub fn hash_power(&self) -> u8 {
120174
self.hash_power
121175
}
@@ -151,6 +205,24 @@ impl Seg {
151205
pub fn datapool_path(&self) -> Option<PathBuf> {
152206
self.datapool_path.as_ref().map(|v| Path::new(v).to_owned())
153207
}
208+
209+
pub fn segments_fields_path(&self) -> Option<PathBuf> {
210+
self.segments_fields_path
211+
.as_ref()
212+
.map(|v| Path::new(v).to_owned())
213+
}
214+
215+
pub fn ttl_buckets_path(&self) -> Option<PathBuf> {
216+
self.ttl_buckets_path
217+
.as_ref()
218+
.map(|v| Path::new(v).to_owned())
219+
}
220+
221+
pub fn hashtable_path(&self) -> Option<PathBuf> {
222+
self.hashtable_path
223+
.as_ref()
224+
.map(|v| Path::new(v).to_owned())
225+
}
154226
}
155227

156228
// trait definitions

src/rust/entrystore/src/seg/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,36 @@ impl Seg {
4343

4444
// build the datastructure from the config
4545
let data = ::seg::Seg::builder()
46+
.restore(config.restore())
4647
.hash_power(config.hash_power())
4748
.overflow_factor(config.overflow_factor())
4849
.heap_size(config.heap_size())
4950
.segment_size(config.segment_size())
5051
.eviction(eviction)
5152
.datapool_path(config.datapool_path())
53+
.segments_fields_path(config.segments_fields_path())
54+
.ttl_buckets_path(config.ttl_buckets_path())
55+
.hashtable_path(config.hashtable_path())
5256
.build();
5357

5458
Self { data }
5559
}
60+
61+
/// Demolish (gracefully shutdown) the cache if
62+
/// configured to do so
63+
pub fn demolish<T: SegConfig>(self, config: &T) {
64+
let config = config.seg();
65+
66+
if config.graceful_shutdown() {
67+
::seg::Seg::demolisher()
68+
.heap_size(config.heap_size())
69+
.overflow_factor(config.overflow_factor())
70+
.segments_fields_path(config.segments_fields_path())
71+
.ttl_buckets_path(config.ttl_buckets_path())
72+
.hashtable_path(config.hashtable_path())
73+
.demolish(self.data);
74+
};
75+
}
5676
}
5777

5878
impl EntryStore for Seg {

src/rust/server/segcache/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ impl Segcache {
7171
/// fully terminated. This is more likely to be used for running integration
7272
/// tests or other automated testing.
7373
pub fn shutdown(self) {
74+
// TODO: demolish cache
7475
self.process.shutdown()
7576
}
7677
}

src/rust/storage/seg/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ rand_chacha = { version = "0.3.0" }
3535
rand_xoshiro = { version = "0.6.0" }
3636
storage-types = { path = "../types" }
3737
thiserror = "1.0.24"
38+
tempfile = "3"
3839

3940
[dev-dependencies]
4041
criterion = "0.3.4"

src/rust/storage/seg/src/builder.rs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,41 @@
66
77
use crate::*;
88
use std::path::Path;
9+
use std::path::PathBuf;
910

1011
/// A builder that is used to construct a new [`Seg`] instance.
1112
pub struct Builder {
13+
restore: bool,
1214
hash_power: u8,
1315
overflow_factor: f64,
1416
segments_builder: SegmentsBuilder,
17+
ttl_buckets_path: Option<PathBuf>,
18+
hashtable_path: Option<PathBuf>,
1519
}
1620

1721
// Defines the default parameters
1822
impl Default for Builder {
1923
fn default() -> Self {
2024
Self {
25+
restore: false,
2126
hash_power: 16,
2227
overflow_factor: 0.0,
2328
segments_builder: SegmentsBuilder::default(),
29+
ttl_buckets_path: None,
30+
hashtable_path: None,
2431
}
2532
}
2633
}
2734

2835
impl Builder {
36+
/// Specify to `Builder` and `SegmentsBuilder` whether the cache will be restored.
37+
/// Otherwise, the cache will be created and treated as new.
38+
pub fn restore(mut self, will_restore: bool) -> Self {
39+
self.restore = will_restore;
40+
self.segments_builder = self.segments_builder.restore(will_restore);
41+
self
42+
}
43+
2944
/// Specify the hash power, which limits the size of the hashtable to 2^N
3045
/// entries. 1/8th of these are used for metadata storage, meaning that the
3146
/// total number of items which can be held in the cache is limited to
@@ -135,17 +150,33 @@ impl Builder {
135150
self
136151
}
137152

138-
/// Specify a backing file to be used for segment storage.
139-
///
140-
/// # Panics
141-
///
142-
/// This will panic if the file already exists
153+
/// Specify a backing file to be used for `Segments.data` storage.
143154
pub fn datapool_path<T: AsRef<Path>>(mut self, path: Option<T>) -> Self {
144155
self.segments_builder = self.segments_builder.datapool_path(path);
145156
self
146157
}
147158

159+
/// Specify a backing file to be used for `Segments` fields' storage.
160+
pub fn segments_fields_path<T: AsRef<Path>>(mut self, path: Option<T>) -> Self {
161+
self.segments_builder = self.segments_builder.segments_fields_path(path);
162+
self
163+
}
164+
165+
/// Specify a backing file to be used for `TtlBuckets` storage.
166+
pub fn ttl_buckets_path<T: AsRef<Path>>(mut self, path: Option<T>) -> Self {
167+
self.ttl_buckets_path = path.map(|p| p.as_ref().to_owned());
168+
self
169+
}
170+
171+
/// Specify a backing file to be used for `HashTable` storage.
172+
pub fn hashtable_path<T: AsRef<Path>>(mut self, path: Option<T>) -> Self {
173+
self.hashtable_path = path.map(|p| p.as_ref().to_owned());
174+
self
175+
}
176+
148177
/// Consumes the builder and returns a fully-allocated `Seg` instance.
178+
/// If `restore` and valid paths to the structures are given, `Seg` will
179+
/// be restored. Otherwise, create a new `Seg` instance.
149180
///
150181
/// ```
151182
/// use seg::{Policy, Seg};
@@ -159,14 +190,35 @@ impl Builder {
159190
/// .eviction(Policy::Random).build();
160191
/// ```
161192
pub fn build(self) -> Seg {
162-
let hashtable = HashTable::new(self.hash_power, self.overflow_factor);
193+
// Build `Segments`.
194+
// If `restore` and a valid path is given,
195+
// it will be copied back
163196
let segments = self.segments_builder.build();
164-
let ttl_buckets = TtlBuckets::default();
197+
if segments.fields_copied_back && self.restore {
198+
// Attempt to restore `HashTable` and `TtlBuckets`
199+
let hashtable =
200+
HashTable::restore(self.hashtable_path, self.hash_power, self.overflow_factor);
201+
let ttl_buckets = TtlBuckets::restore(self.ttl_buckets_path);
202+
203+
// If successful, return a restored segcache
204+
if hashtable.table_copied_back && ttl_buckets.buckets_copied_back {
205+
return Seg {
206+
hashtable,
207+
segments,
208+
ttl_buckets,
209+
_restored: true,
210+
};
211+
}
212+
}
165213

214+
// If not `restore` or restoration failed, create a new cache
215+
let hashtable = HashTable::new(self.hash_power, self.overflow_factor);
216+
let ttl_buckets = TtlBuckets::new();
166217
Seg {
167218
hashtable,
168219
segments,
169220
ttl_buckets,
221+
_restored: false,
170222
}
171223
}
172224
}

0 commit comments

Comments
 (0)