Skip to content

Commit 12c5cc5

Browse files
committed
Changes from code review
1 parent e79b323 commit 12c5cc5

File tree

4 files changed

+82
-40
lines changed

4 files changed

+82
-40
lines changed

doc/developer-guide/cripts/cripts-misc.en.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ Debug logging uses the same format string syntax as ``fmt::format()`` in ``libfm
418418
Cache Groups
419419
============
420420

421-
As a way to manage assosication between cache entries, Cripts provides an infrastructure
421+
As a way to manage association between cache entries, Cripts provides an infrastructure
422422
for cache groups. A cache group is a set of cache entries that are logically
423423
associated with each other via custom identifiers.
424424

include/cripts/CacheGroup.hpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ class Group
4949
uint64_t hash; // Hash value of the group ID, needed when writing to disk
5050
};
5151

52+
// Header structure for on-disk map files (after VERSION field)
53+
struct _MapHeader {
54+
time_t created_ts;
55+
time_t last_write_ts;
56+
time_t last_sync_ts;
57+
size_t count;
58+
};
59+
5260
using _MapType = std::unordered_map<uint64_t, _Entry>;
5361

5462
struct _MapSlot {
@@ -65,9 +73,11 @@ class Group
6573
(static_cast<uint64_t>('P') << 24) | (static_cast<uint64_t>('S') << 16) |
6674
(static_cast<uint64_t>('0') << 8) | 0x00; // Change this on version bump
6775

76+
static constexpr std::chrono::seconds DEFAULT_MAX_AGE{63072000}; // 2 Years, max cache lifetime in ATS as well
77+
6878
Group(const std::string &name, const std::string &base_dir, size_t max_entries = 1024, size_t num_maps = 3)
6979
{
70-
Initialize(name, base_dir, num_maps, max_entries, std::chrono::seconds{63072000});
80+
Initialize(name, base_dir, num_maps, max_entries, DEFAULT_MAX_AGE);
7181
}
7282

7383
// Not used at the moment.
@@ -79,7 +89,7 @@ class Group
7989
self_type &operator=(const self_type &) = delete;
8090

8191
void Initialize(const std::string &name, const std::string &base_dir, size_t num_maps = 3, size_t max_entries = 1024,
82-
std::chrono::seconds max_age = std::chrono::seconds{63072000});
92+
std::chrono::seconds max_age = DEFAULT_MAX_AGE);
8393

8494
void
8595
SetMaxEntries(size_t max_entries)
@@ -127,7 +137,7 @@ class Group
127137
std::string _name = "CacheGroup";
128138
size_t _num_maps = 3;
129139
size_t _max_entries = 1024;
130-
std::chrono::seconds _max_age = std::chrono::seconds(63072000);
140+
std::chrono::seconds _max_age = DEFAULT_MAX_AGE;
131141
std::atomic<size_t> _map_index = 0;
132142
cripts::Time::Point _last_sync = cripts::Time::Point{};
133143

@@ -166,8 +176,19 @@ class Group
166176
if (std::filesystem::exists(_base_dir)) {
167177
_base_dir += "/cache_groups";
168178
if (!std::filesystem::exists(_base_dir)) {
169-
std::filesystem::create_directories(_base_dir);
170-
std::filesystem::permissions(_base_dir, std::filesystem::perms::group_write, std::filesystem::perm_options::add);
179+
std::error_code ec;
180+
181+
std::filesystem::create_directories(_base_dir, ec);
182+
if (ec) {
183+
TSError("cripts::Cache::Group::Manager: Failed to create directory `%s': %s", _base_dir.c_str(), ec.message().c_str());
184+
} else {
185+
std::filesystem::permissions(_base_dir, std::filesystem::perms::group_write, std::filesystem::perm_options::add, ec);
186+
187+
if (ec) {
188+
TSWarning("cripts::Cache::Group::Manager: Failed to set permissions on `%s': %s", _base_dir.c_str(),
189+
ec.message().c_str());
190+
}
191+
}
171192
}
172193
}
173194
_scheduleCont(); // Kick it off

include/cripts/Matcher.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include <algorithm>
2424
#include <vector>
2525
#include <tuple>
26-
#include <algorithm>
2726

2827
#include "cripts/Headers.hpp"
2928
#include "cripts/Lulu.hpp"

src/cripts/CacheGroup.cc

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
*/
1818

1919
#include <algorithm>
20-
#include <iostream>
2120
#include <filesystem>
2221

2322
#include "ts/ts.h"
@@ -47,14 +46,15 @@ _cripts_cache_group_sync(TSCont cont, TSEvent /* event */, void * /* edata */)
4746
size_t processed = 0;
4847
auto now = cripts::Time::Clock::now();
4948

50-
for (auto it = groups.begin(); it != groups.end() && processed < max_to_process; ++it) {
49+
for (auto it = groups.begin(); it != groups.end() && processed < max_to_process;) {
5150
if (auto group = it->second.lock()) {
5251
if (group->LastSync() + std::chrono::seconds{_SYNC_GROUP_EVERY} < now) {
5352
group->WriteToDisk();
5453
++processed;
5554
}
55+
++it;
5656
} else {
57-
// The group has been deleted, remove it from the map ??
57+
// The group has been deleted, remove it from the map
5858
it = groups.erase(it);
5959
}
6060
}
@@ -81,8 +81,17 @@ Cache::Group::Initialize(const std::string &name, const std::string &base_dir, s
8181
_log_path = _base_dir + "/" + "txn.log";
8282

8383
if (!std::filesystem::exists(_base_dir)) {
84-
std::filesystem::create_directories(_base_dir);
85-
std::filesystem::permissions(_base_dir, std::filesystem::perms::group_write, std::filesystem::perm_options::add);
84+
std::error_code ec;
85+
86+
std::filesystem::create_directories(_base_dir, ec);
87+
if (ec) {
88+
TSWarning("cripts::Cache::Group: Failed to create directory `%s': %s", _base_dir.c_str(), ec.message().c_str());
89+
} else {
90+
std::filesystem::permissions(_base_dir, std::filesystem::perms::group_write, std::filesystem::perm_options::add, ec);
91+
if (ec) {
92+
TSWarning("cripts::Cache::Group: Failed to set permissions on `%s': %s", _base_dir.c_str(), ec.message().c_str());
93+
}
94+
}
8695
}
8796

8897
for (size_t ix = 0; ix < _num_maps; ++ix) {
@@ -207,12 +216,9 @@ Cache::Group::LoadFromDisk()
207216
std::ifstream log(_log_path, std::ios::binary);
208217

209218
for (size_t slot_ix = 0; slot_ix < _slots.size(); ++slot_ix) {
210-
auto &slot = _slots[slot_ix];
211-
uint64_t version_id = 0;
212-
size_t count = 0;
213-
time_t created_ts = 0;
214-
time_t last_write_ts = 0;
215-
time_t last_sync_ts = 0;
219+
auto &slot = _slots[slot_ix];
220+
uint64_t version_id = 0;
221+
_MapHeader header{};
216222
std::ifstream file(slot.path, std::ios::binary);
217223

218224
if (!file) {
@@ -226,19 +232,24 @@ Cache::Group::LoadFromDisk()
226232
continue;
227233
}
228234

229-
file.read(reinterpret_cast<char *>(&created_ts), sizeof(created_ts));
230-
file.read(reinterpret_cast<char *>(&last_write_ts), sizeof(last_write_ts));
231-
file.read(reinterpret_cast<char *>(&last_sync_ts), sizeof(last_sync_ts));
232-
file.read(reinterpret_cast<char *>(&count), sizeof(count));
235+
file.read(reinterpret_cast<char *>(&header), sizeof(header));
236+
if (!file) {
237+
TSWarning("cripts::Cache::Group: Failed to read header from map file: %s. Skipping this map.", slot.path.c_str());
238+
continue;
239+
}
233240

234-
slot.created = cripts::Time::Clock::from_time_t(created_ts);
235-
slot.last_write = cripts::Time::Clock::from_time_t(last_write_ts);
236-
slot.last_sync = cripts::Time::Clock::from_time_t(last_sync_ts);
241+
slot.created = cripts::Time::Clock::from_time_t(header.created_ts);
242+
slot.last_write = cripts::Time::Clock::from_time_t(header.last_write_ts);
243+
slot.last_sync = cripts::Time::Clock::from_time_t(header.last_sync_ts);
237244

238-
for (size_t i = 0; i < count; ++i) {
245+
for (size_t i = 0; i < header.count; ++i) {
239246
Cache::Group::_Entry entry;
240247

241248
file.read(reinterpret_cast<char *>(&entry), sizeof(entry));
249+
if (!file) {
250+
TSWarning("cripts::Cache::Group: Failed to read entry %zu from map file: %s. Stopping entry load.", i, slot.path.c_str());
251+
break;
252+
}
242253
if (!std::ranges::any_of(_slots, [&](const auto &slot) { return slot.map->find(entry.hash) != slot.map->end(); })) {
243254
slot.map->insert_or_assign(entry.hash, entry);
244255
}
@@ -286,7 +297,7 @@ Cache::Group::WriteToDisk()
286297

287298
//
288299
// Here comes the private member methods, these must never be called without
289-
// already hodling an exclusive lock on the mutex.
300+
// already holding an exclusive lock on the mutex.
290301
//
291302

292303
void
@@ -309,48 +320,59 @@ Cache::Group::syncMap(size_t index)
309320
{
310321
constexpr size_t BUFFER_SIZE = 64 * 1024;
311322
std::array<std::byte, BUFFER_SIZE> buffer;
312-
size_t buf_pos = 0;
313-
const auto &slot = _slots[index];
314-
const std::string tmp_path = slot.path + ".tmp";
323+
size_t buf_pos = 0;
324+
bool write_failed = false;
325+
const auto &slot = _slots[index];
326+
const std::string tmp_path = slot.path + ".tmp";
315327
std::ofstream o_file(tmp_path, std::ios::binary | std::ios::trunc);
316328

317329
if (!o_file) {
318-
std::cerr << "Failed to open temp file for sync: " << tmp_path << "\n";
330+
TSWarning("cripts::Cache::Group: Failed to open temp file for sync: %s.", tmp_path.c_str());
319331
return;
320332
}
321333

322334
// Helper lambda to append data to the write buffer
323335
auto _AppendToBuffer = [&](const void *data, size_t size) {
336+
if (write_failed) {
337+
return;
338+
}
324339
if (buf_pos + size > buffer.size()) {
325340
o_file.write(reinterpret_cast<const char *>(buffer.data()), buf_pos);
341+
if (!o_file) {
342+
write_failed = true;
343+
return;
344+
}
326345
buf_pos = 0;
327346
}
328347
std::memcpy(buffer.data() + buf_pos, static_cast<const std::byte *>(data), size);
329348
buf_pos += size;
330349
};
331350

332-
time_t created_ts = cripts::Time::Clock::to_time_t(slot.created);
333-
time_t last_write_ts = cripts::Time::Clock::to_time_t(slot.last_write);
334-
time_t last_sync_ts = cripts::Time::Clock::to_time_t(slot.last_sync);
335-
size_t count = slot.map->size();
351+
_MapHeader header{.created_ts = cripts::Time::Clock::to_time_t(slot.created),
352+
.last_write_ts = cripts::Time::Clock::to_time_t(slot.last_write),
353+
.last_sync_ts = cripts::Time::Clock::to_time_t(slot.last_sync),
354+
.count = slot.map->size()};
336355

337356
_AppendToBuffer(&VERSION, sizeof(VERSION));
338-
_AppendToBuffer(&created_ts, sizeof(created_ts));
339-
_AppendToBuffer(&last_write_ts, sizeof(last_write_ts));
340-
_AppendToBuffer(&last_sync_ts, sizeof(last_sync_ts));
341-
_AppendToBuffer(&count, sizeof(count));
357+
_AppendToBuffer(&header, sizeof(header));
342358

343359
// Write entries
344360
for (const auto &[_, entry] : *slot.map) {
345361
_AppendToBuffer(&entry, sizeof(entry));
346362
}
347363

348-
if (buf_pos > 0) {
364+
if (buf_pos > 0 && !write_failed) {
349365
o_file.write(reinterpret_cast<const char *>(buffer.data()), buf_pos);
350366
}
351367
o_file.flush();
352368
o_file.close();
353369

370+
if (write_failed || !o_file) {
371+
TSWarning("cripts::Cache::Group: Failed to write to temp file `%s'.", tmp_path.c_str());
372+
std::filesystem::remove(tmp_path);
373+
return;
374+
}
375+
354376
if (std::rename(tmp_path.c_str(), slot.path.c_str()) != 0) {
355377
TSWarning("cripts::Cache::Group: Failed to rename temp file `%s' to `%s'.", tmp_path.c_str(), slot.path.c_str());
356378
std::filesystem::remove(tmp_path);

0 commit comments

Comments
 (0)