Handle journal_v2 file creation failure due to OOM (#19965)
Stelios Fragkakis committed
Apr 3, 2025 at 11:08 UTC
936832d5777e4b8c24c24d2987493929b88918aa
4 files changed
+18
-12
src/database/engine/cache.c
+7
-5
@@ -2552,7 +2552,7 @@ void pgc_open_cache_to_journal_v2(PGC *cache, Word_t section, unsigned datafile_
2552
pgc_queue_unlock(cache, &cache->hot);
2553
2554
// callback
2555
- cb(section, datafile_fileno, type, JudyL_metrics, JudyL_extents_pos, count_of_unique_extents, count_of_unique_metrics, count_of_unique_pages, data);
2555
+ bool success = cb(section, datafile_fileno, type, JudyL_metrics, JudyL_extents_pos, count_of_unique_extents, count_of_unique_metrics, count_of_unique_pages, data);
2556
2557
{
2558
Pvoid_t *PValue1;
@@ -2567,12 +2567,14 @@ void pgc_open_cache_to_journal_v2(PGC *cache, Word_t section, unsigned datafile_
2567
while ((PValue2 = JudyLFirstThenNext(mi->JudyL_pages_by_start_time, &start_time, &start_time_first))) {
2568
struct jv2_page_info *pi = *PValue2;
2569
2570
- // balance-parents: transition from hot to clean directly
2570
yield_the_processor(); // do not lock too aggressively
2572
- page_set_clean(cache, pi->page, true, false, PGC_QUEUE_LOCK_PRIO_LOW);
2573
- page_transition_unlock(cache, pi->page);
2574
- page_release(cache, pi->page, true);
2571
+ if (likely(success))
2572
+ page_set_clean(cache, pi->page, true, false, PGC_QUEUE_LOCK_PRIO_LOW);
2573
+ else
2574
+ page_flag_clear(pi->page, PGC_PAGE_IS_BEING_MIGRATED_TO_V2);
2575
2576
+ page_transition_unlock(cache, pi->page);
2577
+ page_release(cache, pi->page, success);
2578
// before balance-parents:
2579
// page_transition_unlock(cache, pi->page);
2580
// pgc_page_hot_to_dirty_and_release(cache, pi->page, true);
src/database/engine/cache.h
+1
-1
@@ -227,7 +227,7 @@ int64_t pgc_get_wanted_cache_size(PGC *cache);
227
void pgc_page_hot_set_end_time_s(PGC *cache, PGC_PAGE *page, time_t end_time_s, size_t additional_bytes);
228
bool pgc_page_to_clean_evict_or_release(PGC *cache, PGC_PAGE *page);
229
230
-typedef void (*migrate_to_v2_callback)(Word_t section, unsigned datafile_fileno, uint8_t type, Pvoid_t JudyL_metrics, Pvoid_t JudyL_extents_pos, size_t count_of_unique_extents, size_t count_of_unique_metrics, size_t count_of_unique_pages, void *data);
230
+typedef bool (*migrate_to_v2_callback)(Word_t section, unsigned datafile_fileno, uint8_t type, Pvoid_t JudyL_metrics, Pvoid_t JudyL_extents_pos, size_t count_of_unique_extents, size_t count_of_unique_metrics, size_t count_of_unique_pages, void *data);
231
void pgc_open_cache_to_journal_v2(PGC *cache, Word_t section, unsigned datafile_fileno, uint8_t type, migrate_to_v2_callback cb, void *data);
232
void pgc_open_evict_clean_pages_of_datafile(PGC *cache, struct rrdengine_datafile *datafile);
233
size_t pgc_count_clean_pages_having_data_ptr(PGC *cache, Word_t section, void *ptr);
src/database/engine/journalfile.c
+9
-5
@@ -1293,7 +1293,7 @@ static void *journalfile_v2_write_descriptors(struct journal_v2_header *j2_heade
1293
// startup : if the migration is done during agent startup
1294
// this will allow us to optimize certain things
1295
1296
-void journalfile_migrate_to_v2_callback(Word_t section, unsigned datafile_fileno __maybe_unused, uint8_t type __maybe_unused,
1296
+bool journalfile_migrate_to_v2_callback(Word_t section, unsigned datafile_fileno __maybe_unused, uint8_t type __maybe_unused,
1297
Pvoid_t JudyL_metrics, Pvoid_t JudyL_extents_pos,
1298
size_t number_of_extents, size_t number_of_metrics, size_t number_of_pages, void *user_data)
1299
{
@@ -1346,8 +1346,10 @@ void journalfile_migrate_to_v2_callback(Word_t section, unsigned datafile_fileno
1346
1347
int fd_v2;
1348
uint8_t *data_start = nd_mmap_advanced(path, total_file_size, MAP_SHARED, 0, false, true, &fd_v2);
1349
- if(!data_start)
1350
- out_of_memory(__FUNCTION__, total_file_size, path);
1349
+ if(!data_start) {
1350
+ nd_log_daemon(NDLP_WARNING, "DBENGINE: Failed to allocate %"PRIu64" bytes of memory for journal file '%s'. Will retry later", total_file_size, path);
1351
+ return false;
1352
+ }
1353
1354
memset(data_start, 0, extent_offset);
1355
@@ -1492,7 +1494,7 @@ void journalfile_migrate_to_v2_callback(Word_t section, unsigned datafile_fileno
1494
internal_error(true, "DBENGINE: ACTIVATING NEW INDEX JNL %llu", (now_monotonic_usec() - start_loading) / USEC_PER_MS);
1495
ctx_current_disk_space_increase(ctx, total_file_size);
1496
freez(uuid_list);
1495
- return;
1497
+ return true;
1498
}
1499
else {
1500
netdata_log_info("DBENGINE: failed to build index '%s', file will be skipped", path);
@@ -1506,7 +1508,7 @@ void journalfile_migrate_to_v2_callback(Word_t section, unsigned datafile_fileno
1508
freez(uuid_list);
1509
1510
if (likely(resize_file_to == total_file_size))
1509
- return;
1511
+ return true;
1512
1513
int ret = truncate(path, (long) resize_file_to);
1514
if (ret < 0) {
@@ -1516,6 +1518,8 @@ void journalfile_migrate_to_v2_callback(Word_t section, unsigned datafile_fileno
1518
}
1519
else
1520
ctx_current_disk_space_increase(ctx, resize_file_to);
1521
+
1522
+ return true;
1523
}
1524
1525
int journalfile_load(struct rrdengine_instance *ctx, struct rrdengine_journalfile *journalfile,
src/database/engine/journalfile.h
+1
-1
@@ -264,7 +264,7 @@ int journalfile_load(struct rrdengine_instance *ctx, struct rrdengine_journalfil
264
struct rrdengine_datafile *datafile);
265
void journalfile_v2_populate_retention_to_mrg(struct rrdengine_instance *ctx, struct rrdengine_journalfile *journalfile);
266
267
-void journalfile_migrate_to_v2_callback(Word_t section, unsigned datafile_fileno __maybe_unused, uint8_t type __maybe_unused,
267
+bool journalfile_migrate_to_v2_callback(Word_t section, unsigned datafile_fileno __maybe_unused, uint8_t type __maybe_unused,
268
Pvoid_t JudyL_metrics, Pvoid_t JudyL_extents_pos,
269
size_t number_of_extents, size_t number_of_metrics, size_t number_of_pages, void *user_data);
270