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
292303void
@@ -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