From d57d1f69f4bca321d6365403f454a79a0bc20c26 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 12 Apr 2023 15:09:26 -0400 Subject: [PATCH 01/87] disk: add epoch handling to `u3_disk_init` --- pkg/vere/disk.c | 36 +++++++++++++++++++++++++++++++++--- pkg/vere/vere.h | 3 ++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 87c683fa9f..538238780e 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -867,7 +867,9 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) c3_free(dir_c); } - // create/load $pier/.urb/log, initialize db + // create/load $pier/.urb/log + // create/load $pier/.urb/log/0iN (epoch dir) + // initialize db // { c3_c* log_c = c3_malloc(10 + strlen(pax_c)); @@ -882,6 +884,30 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } + // iterate through the log directory to find the latest epoch, + // or set it to "0i0" if none exist + // + u3_dent* den_u = log_u->com_u->all_u; + c3_c* lat_c; // latest epoch or "0i0" if none exist + if ( !den_u ) { + lat_c = "0i0"; + } else { + while ( den_u ) { + if ( 0 == strncmp(den_u->nam_c, "0i", 2) ) { + // update the lat_c if it's a later epoch + if ( !lat_c || (strcmp(den_u->nam_c, lat_c) > 0) ) { + lat_c = den_u->nam_c; + } + } + den_u = den_u->nex_u; + } + } + + // create/load $pier/.urb/log/0iN epoch directory + c3_c epo_c[8193]; + snprintf(epo_c, sizeof(epo_c), "%s/%s", log_c, lat_c); + c3_mkdir(epo_c, 0700); + // Arbitrarily choosing 1TB as a "large enough" mapsize // // per the LMDB docs: @@ -895,12 +921,16 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) #else 0x10000000000; #endif + + fprintf(stderr, "disk: initializing database at %s\r\n", epo_c); - if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); - c3_free(log_c); c3_free(log_u); return 0; + } else { + // register the epoch directory in the disk struct + log_u->epo_u = u3_foil_folder(epo_c); } } diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index ca8a6da06d..ba06820a62 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -536,8 +536,9 @@ u3_dire* dir_u; // main pier directory u3_dire* urb_u; // urbit system data u3_dire* com_u; // log directory + u3_dire* epo_u; // current epoch directory c3_o liv_o; // live - void* mdb_u; // lmdb environment. + void* mdb_u; // lmdb environment c3_d sen_d; // commit requested c3_d dun_d; // committed u3_disk_cb cb_u; // callbacks From 4be7ec30102a409c7ac3a723e69653b97ce85009 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 13 Apr 2023 14:10:41 -0400 Subject: [PATCH 02/87] u3: add dir list to `u3_dire` --- pkg/vere/foil.c | 6 +++++- pkg/vere/vere.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/vere/foil.c b/pkg/vere/foil.c index 26ff8b3d04..a241c32b66 100644 --- a/pkg/vere/foil.c +++ b/pkg/vere/foil.c @@ -106,13 +106,17 @@ u3_foil_folder(const c3_c* pax_c) dir_u = u3_dire_init(pax_c); } - /* create entries for all files + /* create entries for all files and directories */ while ( UV_EOF != uv_fs_scandir_next(&ruq_u, &den_u) ) { if ( UV_DIRENT_FILE == den_u.type ) { u3_dent* det_u = u3_dent_init(den_u.name); det_u->nex_u = dir_u->all_u; dir_u->all_u = det_u; + } else if ( UV_DIRENT_DIR == den_u.type ) { + u3_dent* det_u = u3_dent_init(den_u.name); + det_u->nex_u = dir_u->dir_u; + dir_u->dir_u = det_u; } } diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index ba06820a62..a1522c6e40 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -130,6 +130,7 @@ c3_c* pax_c; // path of directory uv_file fil_u; // file, opened read-only to fsync u3_dent* all_u; // file list + u3_dent* dir_u; // directory list } u3_dire; /* u3_save: checkpoint control. @@ -538,7 +539,7 @@ u3_dire* com_u; // log directory u3_dire* epo_u; // current epoch directory c3_o liv_o; // live - void* mdb_u; // lmdb environment + void* mdb_u; // lmdb env of current epoch c3_d sen_d; // commit requested c3_d dun_d; // committed u3_disk_cb cb_u; // callbacks From 89e919865a7422d7e558c09600edeeb79d34961f Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 13 Apr 2023 15:02:20 -0400 Subject: [PATCH 03/87] disk: add `u3_disk_last_epoc` and `u3_disk_migrate` --- BUILD.bazel | 4 +- pkg/vere/disk.c | 113 +++++++++++++++++++++++++++++++++++------------- pkg/vere/main.c | 4 +- pkg/vere/vere.h | 11 +++++ 4 files changed, 97 insertions(+), 35 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index 4ea5807432..304ecb66d4 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -44,8 +44,8 @@ config_setting( # Version flag for clang. string_flag( name = "clang_version", - # macOS uses `clang-14.0.0` by default. - build_setting_default = "14.0.0", + # macOS uses `clang-14.0.3` by default. + build_setting_default = "14.0.3", visibility = ["//visibility:public"], ) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 538238780e..867716ac74 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -2,6 +2,7 @@ #include "noun.h" #include "vere.h" +#include "version.h" #include "db/lmdb.h" struct _cd_read { @@ -22,6 +23,12 @@ struct _cd_save { struct _u3_disk* log_u; }; +/* DISK FORMAT + */ + +#define U3D_VER1 1 +#define U3D_VERLAT U3L_VER1 + #undef VERBOSE_DISK #undef DISK_TRACE_JAM #undef DISK_TRACE_CUE @@ -868,8 +875,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } // create/load $pier/.urb/log - // create/load $pier/.urb/log/0iN (epoch dir) - // initialize db + // XX closures? // { c3_c* log_c = c3_malloc(10 + strlen(pax_c)); @@ -884,34 +890,26 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } - // iterate through the log directory to find the latest epoch, - // or set it to "0i0" if none exist + // validation before migration // - u3_dent* den_u = log_u->com_u->all_u; - c3_c* lat_c; // latest epoch or "0i0" if none exist - if ( !den_u ) { - lat_c = "0i0"; - } else { - while ( den_u ) { - if ( 0 == strncmp(den_u->nam_c, "0i", 2) ) { - // update the lat_c if it's a later epoch - if ( !lat_c || (strcmp(den_u->nam_c, lat_c) > 0) ) { - lat_c = den_u->nam_c; - } - } - den_u = den_u->nex_u; - } - } - // create/load $pier/.urb/log/0iN epoch directory - c3_c epo_c[8193]; - snprintf(epo_c, sizeof(epo_c), "%s/%s", log_c, lat_c); - c3_mkdir(epo_c, 0700); + // migrate to the correct disk format + // + u3_disk_migrate(log_u); + + // find the latest epoch directory + // + c3_d lat_d; + u3_disk_last_epoc(log_u, &lat_d); + fprintf(stderr, "disk: latest epoch is 0i%" PRIu64 "\r\n", lat_d); - // Arbitrarily choosing 1TB as a "large enough" mapsize + // load latest epoch directory and set it in log_u // - // per the LMDB docs: - // "[..] on 64-bit there is no penalty for making this huge (say 1TB)." + c3_c epo_c[8193]; + snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); + log_u->epo_u = u3_foil_folder(epo_c); + + // initialize db of latest epoch // { const size_t siz_i = @@ -922,15 +920,10 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) 0x10000000000; #endif - fprintf(stderr, "disk: initializing database at %s\r\n", epo_c); - if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); return 0; - } else { - // register the epoch directory in the disk struct - log_u->epo_u = u3_foil_folder(epo_c); } } @@ -960,3 +953,61 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return log_u; } + +/* u3_disk_last_epoc: get latest epoch number. + */ +c3_d u3_disk_last_epoc(u3_disk* log_u, c3_d* lat_d) { + c3_d ret_d = 1; // return code 1 if no epoch directories exist + *lat_d = 0; // initialize lat_d to 0 + u3_dent* den_u = log_u->com_u->dir_u; + while ( den_u ) { + c3_d epo_d = 0; + if ( 1 != sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { + fprintf(stderr, "disk: epoch directory is not a @ui: %s\r\n", den_u->nam_c); + } else { + ret_d = 0; // return code 0 if at least one epoch directory exists + } + *lat_d = c3_max(epo_d, *lat_d); // update the latest epoch number + den_u = den_u->nex_u; + } + + return ret_d; +} + +/* u3_disk_migrate: migrates disk format. + */ +void u3_disk_migrate(u3_disk* log_u) +{ + c3_d lat_d; // latest epoch number + + // initialize disk v1 on fresh boots + // + if ( 1 == u3_disk_last_epoc(log_u, &lat_d) ) { // XX add another condition to ensure fresh boot + fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); + + // create first epoch directory "0i0" + c3_c epo_c[8193]; + snprintf(epo_c, sizeof(epo_c), "%s/0i0", log_u->com_u->pax_c); + c3_mkdir(epo_c, 0700); + + // create epoch version file + c3_c epv_c[8193]; + snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); + FILE* epv_f = fopen(epv_c, "a"); + fprintf(epv_f, "%d\n", U3D_VER1); + fclose(epv_f); + + // create binary version file + c3_c biv_c[8193]; + snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); + FILE* biv_f = fopen(biv_c, "a"); + fprintf(biv_f, URBIT_VERSION); + fclose(biv_f); + } + + // migrate existing unversioned pier to v1 + // + // XX write this + + return; +} \ No newline at end of file diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 510ed95498..d2450b1cd9 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2072,7 +2072,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) // gracefully shutdown the pier if it's running u3_disk* old_u = _cw_disk_init(u3_Host.dir_c); - // note: this include patch applications (if any) + // note: this includes patch applications (if any) u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); // check if there's a *current* snapshot @@ -2083,7 +2083,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) exit(1); } - if ( c3n == u3e_backup(c3y)) { // backup current snapshot + if ( c3n == u3e_backup(c3y) ) { // backup current snapshot fprintf(stderr, "chop: error: failed to backup snapshot\r\n"); exit(1); } diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index a1522c6e40..a32d9a4604 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -8,6 +8,7 @@ #include "noun.h" #include "serf.h" #include "uv.h" +#include "version.h" /** Quasi-tunable parameters. **/ @@ -981,6 +982,16 @@ */ void u3_disk_plan(u3_disk* log_u, u3_fact* tac_u); + + /* u3_disk_last_epoc(): get latest epoch number. + */ + c3_d + u3_disk_last_epoc(u3_disk* log_u, c3_d* lat_d); + + /* u3_disk_migrate(): migrates disk format. + */ + void + u3_disk_migrate(u3_disk* log_u); /* u3_lord_init(): start serf. */ From 796de555b8f389961dba300d6dba5be027bc1fe3 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 14 Apr 2023 14:19:48 -0400 Subject: [PATCH 04/87] u3: make `u3e_backup` copy snapshot to arbitrary path --- pkg/noun/events.c | 38 ++++++++++++++++++++------------------ pkg/noun/events.h | 4 ++-- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 2d831ffef4..9d772faf9b 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -993,48 +993,48 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) return c3y; } -/* u3e_backup(); +/* u3e_backup(): copy snapshot to pax_c, overwrite optionally. */ c3_o -u3e_backup(c3_o ovw_o) +u3e_backup(c3_c* pax_c, c3_o ovw_o) { u3e_image nop_u = { .nam_c = "north", .pgs_w = 0 }; u3e_image sop_u = { .nam_c = "south", .pgs_w = 0 }; c3_i mod_i = O_RDWR | O_CREAT; - c3_c ful_c[8193]; - snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); + if ( !pax_c ) { + fprintf(stderr, "loom: image backup: bad path\r\n"); + return c3n; + } - if ( (c3n == ovw_o) && c3_mkdir(ful_c, 0700) ) { + if ( (c3n == ovw_o) && c3_mkdir(pax_c, 0700) ) { if ( EEXIST != errno ) { fprintf(stderr, "loom: image backup: %s\r\n", strerror(errno)); } return c3n; } - snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c); + c3_c nop_c[8193]; + snprintf(nop_c, 8192, "%s/%s.bin", pax_c, nop_u.nam_c); - if ( -1 == (nop_u.fid_i = c3_open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); + if ( -1 == (nop_u.fid_i = c3_open(nop_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", nop_c, strerror(errno)); return c3n; } - snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, sop_u.nam_c); + c3_c sop_c[8193]; + snprintf(sop_c, 8192, "%s/%s.bin", pax_c, sop_u.nam_c); - if ( -1 == (sop_u.fid_i = c3_open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); + if ( -1 == (sop_u.fid_i = c3_open(sop_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", sop_c, strerror(errno)); return c3n; } if ( (c3n == _ce_image_copy(&u3P.nor_u, &nop_u)) || (c3n == _ce_image_copy(&u3P.sou_u, &sop_u)) ) { - - c3_unlink(ful_c); - snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c); - c3_unlink(ful_c); - snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); - c3_rmdir(ful_c); + c3_unlink(nop_c); + c3_unlink(sop_c); fprintf(stderr, "loom: image backup failed\r\n"); return c3n; } @@ -1111,7 +1111,9 @@ u3e_save(void) _ce_patch_free(pat_u); _ce_patch_delete(); - u3e_backup(c3n); + c3_c bhk_c[8193]; + snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3P.dir_c); + u3e_backup(bhk_c, c3n); } /* u3e_live(): start the checkpointing system. diff --git a/pkg/noun/events.h b/pkg/noun/events.h index b4c78fe364..a4d7c5cf43 100644 --- a/pkg/noun/events.h +++ b/pkg/noun/events.h @@ -64,10 +64,10 @@ /** Functions. **/ - /* u3e_backup(): copy the snapshot from chk to bhk. + /* u3e_backup(): copy the snapshot to pax_c, overwrite optionally. */ c3_o - u3e_backup(c3_o ovw_o); + u3e_backup(c3_c* pax_c, c3_o ovw_o); /* u3e_fault(): handle a memory event with libsigsegv protocol. */ From 6d00b08ee3f6ffb94c1ca94ef2ad5870d7768c63 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 14 Apr 2023 14:22:33 -0400 Subject: [PATCH 05/87] disk: add `epoc` functions --- pkg/vere/disk.c | 140 +++++++++++++++++++++++++++++++++++------------- pkg/vere/vere.h | 10 ++-- 2 files changed, 110 insertions(+), 40 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 867716ac74..fee6ce28dd 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -893,24 +893,22 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) // validation before migration // - // migrate to the correct disk format + // migrate to the correct disk format if necessary // u3_disk_migrate(log_u); - // find the latest epoch directory + // initialize latest epoch // c3_d lat_d; - u3_disk_last_epoc(log_u, &lat_d); + u3_disk_epoc_last(log_u, &lat_d); fprintf(stderr, "disk: latest epoch is 0i%" PRIu64 "\r\n", lat_d); - // load latest epoch directory and set it in log_u + // initialize epoch's db // c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); - log_u->epo_u = u3_foil_folder(epo_c); - - // initialize db of latest epoch - // + fprintf(stderr, "epo_c: %s\r\n", epo_c); + c3_free(log_c); { const size_t siz_i = // 500 GiB is as large as musl on aarch64 wants to allow @@ -919,15 +917,13 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) #else 0x10000000000; #endif - + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); return 0; } } - - c3_free(log_c); } // get the latest event number from the db @@ -954,18 +950,101 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return log_u; } -/* u3_disk_last_epoc: get latest epoch number. - */ -c3_d u3_disk_last_epoc(u3_disk* log_u, c3_d* lat_d) { - c3_d ret_d = 1; // return code 1 if no epoch directories exist - *lat_d = 0; // initialize lat_d to 0 +/* u3_disk_epoc_init: create new epoch. +*/ +c3_o u3_disk_epoc_init(u3_disk* log_u) { + // set new epoch number + c3_d lat_d, new_d; + c3_o eps_o = u3_disk_epoc_last(log_u, &lat_d); + if ( c3n == eps_o ) { + new_d = 0; // no epochs yet, so create first one 0i0 + } else { + // ensure latest epoch isn't empty + c3_d fir_d, las_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { + fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); + return c3n; + } + if ( fir_d == las_d ) { + fprintf(stderr, "disk: latest epoch is empty; skipping epoch init\r\n"); + return c3n; + } + new_d = 1 + lat_d; // create next epoch + } + + // create new epoch directory + c3_c epo_c[8193]; + snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, new_d); + fprintf(stderr, "disk: creating new epoch directory 0i%" PRIu64 "\r\n", new_d); + if ( 0 != c3_mkdir(epo_c, 0700) ) { + fprintf(stderr, "disk: failed to create epoch directory\r\n"); + return c3n; + } + + // create epoch version file + c3_c epv_c[8193]; + snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); + FILE* epv_f = fopen(epv_c, "a"); + fprintf(epv_f, "%d\n", U3D_VER1); + fclose(epv_f); + + // create binary version file + c3_c biv_c[8193]; + snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); + FILE* biv_f = fopen(biv_c, "a"); + fprintf(biv_f, URBIT_VERSION); + fclose(biv_f); + + // copy snapshot (skip if first epoch 0i0) + if ( new_d > 0 ) { + if ( c3n == u3e_backup(epo_c, c3n) ) { + fprintf(stderr, "disk: failed to copy snapshot to new epoch\r\n"); + goto fail; + } + } + + // initialize db of latest epoch + { + const size_t siz_i = + // 500 GiB is as large as musl on aarch64 wants to allow + #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) + 0x7d00000000; + #else + 0x10000000000; + #endif + + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { + fprintf(stderr, "disk: failed to initialize database\r\n"); + c3_free(log_u); + goto fail; + } + } + + // load new epoch directory and set it in log_u + log_u->epo_u = u3_foil_folder(epo_c); + + // success + return c3y; + +fail: + c3_unlink(epv_c); + c3_unlink(biv_c); + c3_rmdir(epo_c); + return c3n; +} + +/* u3_disk_epoc_last: get latest epoch number. +*/ +c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { + c3_o ret_d = c3n; // return no if no epoch directories exist + *lat_d = 0; // initialize lat_d to 0 u3_dent* den_u = log_u->com_u->dir_u; while ( den_u ) { c3_d epo_d = 0; if ( 1 != sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { fprintf(stderr, "disk: epoch directory is not a @ui: %s\r\n", den_u->nam_c); } else { - ret_d = 0; // return code 0 if at least one epoch directory exists + ret_d = c3y; // return yes if at least one epoch directory exists } *lat_d = c3_max(epo_d, *lat_d); // update the latest epoch number den_u = den_u->nex_u; @@ -982,30 +1061,17 @@ void u3_disk_migrate(u3_disk* log_u) // initialize disk v1 on fresh boots // - if ( 1 == u3_disk_last_epoc(log_u, &lat_d) ) { // XX add another condition to ensure fresh boot + if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { // XX ensure fresh boot fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); - // create first epoch directory "0i0" - c3_c epo_c[8193]; - snprintf(epo_c, sizeof(epo_c), "%s/0i0", log_u->com_u->pax_c); - c3_mkdir(epo_c, 0700); - - // create epoch version file - c3_c epv_c[8193]; - snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); - FILE* epv_f = fopen(epv_c, "a"); - fprintf(epv_f, "%d\n", U3D_VER1); - fclose(epv_f); - - // create binary version file - c3_c biv_c[8193]; - snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); - FILE* biv_f = fopen(biv_c, "a"); - fprintf(biv_f, URBIT_VERSION); - fclose(biv_f); + // initialize first epoch "0i0" + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); + exit(1); + } } - // migrate existing unversioned pier to v1 + // migrate existing, unversioned disk to v1 // // XX write this diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index a32d9a4604..694769cf57 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -8,7 +8,6 @@ #include "noun.h" #include "serf.h" #include "uv.h" -#include "version.h" /** Quasi-tunable parameters. **/ @@ -983,10 +982,15 @@ void u3_disk_plan(u3_disk* log_u, u3_fact* tac_u); + /* u3_disk_init_epoc(): create new epoch. + */ + c3_o + u3_disk_epoc_init(u3_disk* log_u); + /* u3_disk_last_epoc(): get latest epoch number. */ - c3_d - u3_disk_last_epoc(u3_disk* log_u, c3_d* lat_d); + c3_o + u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d); /* u3_disk_migrate(): migrates disk format. */ From 488adc3f7cede004a09b18796386ae03409b6d3c Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 17 Apr 2023 05:13:11 -0400 Subject: [PATCH 06/87] cli: add `roll` subcommand for epoch rollovers --- pkg/noun/events.h | 2 +- pkg/vere/disk.c | 72 +++++++++++++++++++++++++++------------- pkg/vere/foil.c | 4 +-- pkg/vere/main.c | 84 +++++++++++++++++++++++++++++++++++++++++++++-- pkg/vere/vere.h | 2 +- pkg/vere/ward.c | 12 +++++++ 6 files changed, 147 insertions(+), 29 deletions(-) diff --git a/pkg/noun/events.h b/pkg/noun/events.h index a4d7c5cf43..058fa2fe23 100644 --- a/pkg/noun/events.h +++ b/pkg/noun/events.h @@ -64,7 +64,7 @@ /** Functions. **/ - /* u3e_backup(): copy the snapshot to pax_c, overwrite optionally. + /* u3e_backup(): copy the snapshot to pax_c, overwrite optional. */ c3_o u3e_backup(c3_c* pax_c, c3_o ovw_o); diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index fee6ce28dd..8eefc7c973 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -890,26 +890,25 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } - // validation before migration + // XX validation before migration // // migrate to the correct disk format if necessary // u3_disk_migrate(log_u); - // initialize latest epoch + // get latest epoch number // c3_d lat_d; u3_disk_epoc_last(log_u, &lat_d); - fprintf(stderr, "disk: latest epoch is 0i%" PRIu64 "\r\n", lat_d); // initialize epoch's db // c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); - fprintf(stderr, "epo_c: %s\r\n", epo_c); c3_free(log_c); { + // XX extract into function? const size_t siz_i = // 500 GiB is as large as musl on aarch64 wants to allow #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) @@ -924,24 +923,33 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } } - } + fprintf(stderr, "disk: loaded epoch 0i%" PRIu64 "\r\n", lat_d); - // get the latest event number from the db - // - { - log_u->dun_d = 0; - c3_d fir_d; - - if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { - fprintf(stderr, "disk: failed to load latest event from database\r\n"); - c3_free(log_u); + // get first/last event numbers from lmdb + c3_d fir_d, las_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { + fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); return 0; } - log_u->sen_d = log_u->dun_d; + // initialize dun_d/sen_d values + if ( 0 == las_d ) { // fresh epoch (no events in lmdb yet) + if ( 0 == lat_d ) { // first epoch + log_u->dun_d = 0; + log_u->sen_d = 0; + } else { // not first epoch + log_u->dun_d = lat_d - 1; // set dun_d to last event in prev epoch + log_u->sen_d = log_u->dun_d; + } + } else { // not fresh epoch + log_u->dun_d = las_d; // set dun_d to last event in lmdb + log_u->sen_d = las_d; + } + + // mark the log as live + log_u->liv_o = c3y; } - log_u->liv_o = c3y; #if defined(DISK_TRACE_JAM) || defined(DISK_TRACE_CUE) u3t_trace_open(pax_c); @@ -966,16 +974,15 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { return c3n; } if ( fir_d == las_d ) { - fprintf(stderr, "disk: latest epoch is empty; skipping epoch init\r\n"); + fprintf(stderr, "disk: latest epoch is empty; skipping rollover\r\n"); return c3n; } - new_d = 1 + lat_d; // create next epoch + new_d = 1 + las_d; // create next epoch } // create new epoch directory c3_c epo_c[8193]; snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, new_d); - fprintf(stderr, "disk: creating new epoch directory 0i%" PRIu64 "\r\n", new_d); if ( 0 != c3_mkdir(epo_c, 0700) ) { fprintf(stderr, "disk: failed to create epoch directory\r\n"); return c3n; @@ -995,15 +1002,26 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { fprintf(biv_f, URBIT_VERSION); fclose(biv_f); - // copy snapshot (skip if first epoch 0i0) + // copy snapshot (skip if first epoch) if ( new_d > 0 ) { - if ( c3n == u3e_backup(epo_c, c3n) ) { + if ( c3n == u3e_backup(epo_c, c3y) ) { fprintf(stderr, "disk: failed to copy snapshot to new epoch\r\n"); goto fail; } } - // initialize db of latest epoch + // get metadata from old epoch's db + c3_d who_d[2]; + c3_o fak_o; + c3_w lif_w; + if ( c3y == eps_o ) { + if ( c3y != u3_disk_read_meta(log_u->mdb_u, who_d, &fak_o, &lif_w) ) { + fprintf(stderr, "disk: failed to read metadata\r\n"); + goto fail; + } + } + + // initialize db of new epoch { const size_t siz_i = // 500 GiB is as large as musl on aarch64 wants to allow @@ -1020,6 +1038,14 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { } } + // write the metadata to the database + if ( c3y == eps_o ) { + if ( c3n == u3_disk_save_meta(log_u->mdb_u, who_d, fak_o, lif_w) ) { + fprintf(stderr, "disk: failed to save metadata\r\n"); + exit(1); + } + } + // load new epoch directory and set it in log_u log_u->epo_u = u3_foil_folder(epo_c); @@ -1038,7 +1064,7 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { c3_o ret_d = c3n; // return no if no epoch directories exist *lat_d = 0; // initialize lat_d to 0 - u3_dent* den_u = log_u->com_u->dir_u; + u3_dent* den_u = log_u->com_u->dil_u; while ( den_u ) { c3_d epo_d = 0; if ( 1 != sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { diff --git a/pkg/vere/foil.c b/pkg/vere/foil.c index a241c32b66..9fae86973f 100644 --- a/pkg/vere/foil.c +++ b/pkg/vere/foil.c @@ -115,8 +115,8 @@ u3_foil_folder(const c3_c* pax_c) dir_u->all_u = det_u; } else if ( UV_DIRENT_DIR == den_u.type ) { u3_dent* det_u = u3_dent_init(den_u.name); - det_u->nex_u = dir_u->dir_u; - dir_u->dir_u = det_u; + det_u->nex_u = dir_u->dil_u; + dir_u->dil_u = det_u; } } diff --git a/pkg/vere/main.c b/pkg/vere/main.c index d2450b1cd9..6aba090477 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -682,6 +682,7 @@ _cw_usage(c3_c* bin_c) " %s next %.*s request upgrade:\n", " %s queu %.*s cue state:\n", " %s chop %.*s truncate event log:\n", + " %s roll %.*s rollover to new epoch:\n", " %s vere ARGS download binary:\n", "\n run as a 'serf':\n", " %s serf " @@ -1151,7 +1152,7 @@ _cw_disk_init(c3_c* dir_c) u3_disk* log_u = u3_disk_init(dir_c, cb_u); if ( !log_u ) { - fprintf(stderr, "unable to open event log\n"); + fprintf(stderr, "unable to open event log\n");; exit(1); } @@ -2083,7 +2084,9 @@ _cw_chop(c3_i argc, c3_c* argv[]) exit(1); } - if ( c3n == u3e_backup(c3y) ) { // backup current snapshot + c3_c bhk_c[8193]; + snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3_Host.dir_c); + if ( c3n == u3e_backup(bhk_c, c3y) ) { // backup current snapshot fprintf(stderr, "chop: error: failed to backup snapshot\r\n"); exit(1); } @@ -2189,6 +2192,82 @@ _cw_chop(c3_i argc, c3_c* argv[]) fprintf(stderr, " `mv %s %s` then try again\r\n", bak_c, dat_c); } +/* _cw_roll(): rollover to new epoch + */ +static void +_cw_roll(c3_i argc, c3_c* argv[]) +{ + c3_i ch_i, lid_i; + c3_w arg_w; + + static struct option lop_u[] = { + { "loom", required_argument, NULL, c3__loom }, + { NULL, 0, NULL, 0 } + }; + + u3_Host.dir_c = _main_pier_run(argv[0]); + + while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case c3__loom: { + if (_main_readw_loom("loom", &u3_Host.ops_u.lom_y)) { + exit(1); + } + } break; + + case '?': { + fprintf(stderr, "invalid argument\r\n"); + exit(1); + } break; + } + } + + // argv[optind] is always "roll" + // + + if ( !u3_Host.dir_c ) { + if ( optind + 1 < argc ) { + u3_Host.dir_c = argv[optind + 1]; + } + else { + fprintf(stderr, "invalid command, pier required\r\n"); + exit(1); + } + + optind++; + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } + + // gracefully shutdown the pier if it's running + u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); + + // note: this includes patch applications (if any) + u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + + // check if there's a *current* snapshot + if ( log_u->dun_d != u3A->eve_d ) { + fprintf(stderr, "roll: error: snapshot is out of date, please " + "start/shutdown your pier gracefully first\r\n"); + fprintf(stderr, "roll: eve_d: %" PRIu64 ", dun_d: %" PRIu64 "\r\n", \ + u3A->eve_d, log_u->dun_d); + exit(1); + } + + // create new epoch + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); + exit(1); + } + + // report success + c3_d epo_d = log_u->dun_d + 1; + fprintf(stderr, "roll: success: created epoch 0i%" PRIu64 "\r\n", epo_d); +} + /* _cw_vere(): download vere */ static void @@ -2451,6 +2530,7 @@ _cw_utils(c3_i argc, c3_c* argv[]) case c3__prep: _cw_prep(argc, argv); return 2; // continue on case c3__queu: _cw_queu(argc, argv); return 1; case c3__chop: _cw_chop(argc, argv); return 1; + case c3__roll: _cw_roll(argc, argv); return 1; case c3__vere: _cw_vere(argc, argv); return 1; case c3__vile: _cw_vile(argc, argv); return 1; diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index 694769cf57..fde11bb193 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -130,7 +130,7 @@ c3_c* pax_c; // path of directory uv_file fil_u; // file, opened read-only to fsync u3_dent* all_u; // file list - u3_dent* dir_u; // directory list + u3_dent* dil_u; // directory list } u3_dire; /* u3_save: checkpoint control. diff --git a/pkg/vere/ward.c b/pkg/vere/ward.c index 4c90be7179..9d6c8cbed3 100644 --- a/pkg/vere/ward.c +++ b/pkg/vere/ward.c @@ -39,6 +39,7 @@ u3_dire_init(const c3_c* pax_c) { u3_dire *dir_u = c3_malloc(sizeof *dir_u); dir_u->all_u = 0; + dir_u->dil_u = 0; dir_u->pax_c = c3_malloc(1 + strlen(pax_c)); strcpy(dir_u->pax_c, pax_c); @@ -61,6 +62,17 @@ u3_dire_free(u3_dire *dir_u) } } + { + u3_dent *det_u = dir_u->dil_u; + u3_dent *nex_u; + + while ( det_u ) { + nex_u = det_u->nex_u; + u3_dent_free(det_u); + det_u = nex_u; + } + } + c3_free(dir_u->pax_c); c3_free(dir_u); } From f0289f989d350692246d29a00a1694de68677659 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 17 Apr 2023 12:45:38 -0400 Subject: [PATCH 07/87] cli: make `chop` work with epochs --- pkg/vere/disk.c | 30 ++++++++++++ pkg/vere/main.c | 118 ++++++++++-------------------------------------- pkg/vere/vere.h | 9 +++- 3 files changed, 60 insertions(+), 97 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 8eefc7c973..9aa0f68707 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1059,6 +1059,36 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { return c3n; } +/* u3_disk_epoc_kill: delete an epoch. +*/ +c3_o u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { + // get epoch directory + c3_c epo_c[8193]; + snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, epo_d); + + // delete files in epoch directory + u3_dire* dir_u = u3_foil_folder(epo_c); + u3_dent* den_u = dir_u->all_u; + while ( den_u ) { + c3_c fil_c[8193]; + snprintf(fil_c, sizeof(fil_c), "%s/%s", epo_c, den_u->nam_c); + if ( 0 != c3_unlink(fil_c) ) { + fprintf(stderr, "disk: failed to delete file in epoch directory\r\n"); + return c3n; + } + den_u = den_u->nex_u; + } + + // delete epoch directory + if ( 0 != c3_rmdir(epo_c) ) { + fprintf(stderr, "disk: failed to delete epoch directory\r\n"); + return c3n; + } + + // success + return c3y; +} + /* u3_disk_epoc_last: get latest epoch number. */ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 6aba090477..334a9dddd6 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2071,125 +2071,53 @@ _cw_chop(c3_i argc, c3_c* argv[]) } // gracefully shutdown the pier if it's running - u3_disk* old_u = _cw_disk_init(u3_Host.dir_c); + u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // note: this includes patch applications (if any) u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); // check if there's a *current* snapshot - if ( old_u->dun_d != u3A->eve_d ) { + if ( log_u->dun_d != u3A->eve_d ) { fprintf(stderr, "chop: error: snapshot is out of date, please " "start/shutdown your pier gracefully first\r\n"); - fprintf(stderr, "chop: eve_d: %" PRIu64 ", dun_d: %" PRIu64 "\r\n", u3A->eve_d, old_u->dun_d); - exit(1); - } - - c3_c bhk_c[8193]; - snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3_Host.dir_c); - if ( c3n == u3e_backup(bhk_c, c3y) ) { // backup current snapshot - fprintf(stderr, "chop: error: failed to backup snapshot\r\n"); - exit(1); - } - - // initialize the lmdb environment - // see disk.c:885 - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif - c3_c log_c[8193]; - snprintf(log_c, sizeof(log_c), "%s/.urb/log", u3_Host.dir_c); - - // get the first/last event numbers from the event log - c3_d fir_d, las_d; - if ( c3n == u3_lmdb_gulf(old_u->mdb_u, &fir_d, &las_d) ) { - fprintf(stderr, "chop: failed to load latest event from database\r\n"); + fprintf(stderr, "chop: eve_d: %" PRIu64 ", dun_d: %" PRIu64 "\r\n", u3A->eve_d, log_u->dun_d); exit(1); } - // get the metadata - c3_d who_d[2]; - c3_o fak_o; - c3_w lif_w; - if ( c3y != u3_disk_read_meta(old_u->mdb_u, who_d, &fak_o, &lif_w) ) { - fprintf(stderr, "chop: failed to read metadata\r\n"); + // create new epoch + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "chop: failed to create new epoch\r\n"); exit(1); } - // get the last event - u3_lmdb_walk itr_u; - size_t len_i; - void* buf_v[1]; - if ( c3n == u3_lmdb_walk_init(old_u->mdb_u, &itr_u, las_d, las_d) ) { - fprintf(stderr, "chop: failed to initialize iterator\r\n"); - exit(1); - } - if ( c3n == u3_lmdb_walk_next(&itr_u, &len_i, buf_v) ) { - fprintf(stderr, "chop: failed to read event\r\n"); + // get latest epoch number + c3_d lat_d; + if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { + fprintf(stderr, "chop: failed to find last epoch\r\n"); exit(1); } - u3_lmdb_walk_done(&itr_u); - // initialize a fresh lmdb environment in the "chop" subdir - c3_c cho_c[8193]; - snprintf(cho_c, sizeof(cho_c), "%s/chop", log_c); - if ( 0 != access(cho_c, F_OK) ) { - if ( 0 != c3_mkdir(cho_c, 0700) ) { - fprintf(stderr, "chop: failed to create chop directory\r\n"); - exit(1); + // delete all but the last epoch + u3_dent* den_u = log_u->com_u->dil_u; + c3_d epo_d = 0; + while ( den_u && epo_d <= lat_d ) { + if ( 1 != sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { + fprintf(stderr, "disk: epoch directory is not a @ui: %s\r\n", den_u->nam_c); + } else { + fprintf(stderr, "chop: deleting epoch 0i%" PRIu64 "\r\n", epo_d); + if ( c3y != u3_disk_epoc_kill(log_u, epo_d) ) { + fprintf(stderr, "chop: failed to delete epoch 0i%" PRIu64 "\r\n", epo_d); + } } - } - MDB_env* new_u = u3_lmdb_init(cho_c, siz_i); - if ( !new_u ) { - fprintf(stderr, "chop: failed to initialize new database\r\n"); - exit(1); - } - - // write the metadata to the database - if ( c3n == u3_disk_save_meta(new_u, who_d, fak_o, lif_w) ) { - fprintf(stderr, "chop: failed to save metadata\r\n"); - exit(1); - } - - // write the last event to the database - // warning: this relies on the old database still being open - if ( c3n == u3_lmdb_save(new_u, las_d, 1, buf_v, &len_i) ) { - fprintf(stderr, "chop: failed to write last event\r\n"); - exit(1); - } - - // backup the original database file - c3_c dat_c[8193], bak_c[8193]; - snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", log_c); - // "data_-.mdb.bak" - snprintf(bak_c, sizeof(bak_c), "%s/data_%" PRIu64 "-%" PRIu64 ".mdb.bak", cho_c, fir_d, las_d); - if ( 0 != c3_rename(dat_c, bak_c) ) { - fprintf(stderr, "chop: failed to backup original database file\r\n"); - exit(1); - } - - // rename new database file to be official - c3_c new_c[8193]; - snprintf(new_c, sizeof(new_c), "%s/data.mdb", cho_c); - if ( 0 != c3_rename(new_c, dat_c) ) { - fprintf(stderr, "chop: failed to rename new database file\r\n"); - exit(1); + den_u = den_u->nex_u; } // cleanup - u3_disk_exit(old_u); - u3_lmdb_exit(new_u); + u3_disk_exit(log_u); u3m_stop(); // success fprintf(stderr, "chop: event log truncation complete\r\n"); - fprintf(stderr, " event log backup written to %s\r\n", bak_c); - fprintf(stderr, " WARNING: ENSURE YOU CAN RESTART YOUR SHIP BEFORE DELETING YOUR EVENT LOG BACKUP FILE!\r\n"); - fprintf(stderr, " if you can't, restore your log by running:\r\n"); - fprintf(stderr, " `mv %s %s` then try again\r\n", bak_c, dat_c); } /* _cw_roll(): rollover to new epoch diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index fde11bb193..a2726d2341 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -982,12 +982,17 @@ void u3_disk_plan(u3_disk* log_u, u3_fact* tac_u); - /* u3_disk_init_epoc(): create new epoch. + /* u3_disk_epoc_init(): create new epoch. */ c3_o u3_disk_epoc_init(u3_disk* log_u); - /* u3_disk_last_epoc(): get latest epoch number. + /* u3_disk_epoc_kill(): delete an epoch. + */ + c3_o + u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d); + + /* u3_disk_epoc_last(): get latest epoch number. */ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d); From c54d6c0bba8dfa100705322a40536dd4695e1499 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 18 Apr 2023 15:23:03 -0400 Subject: [PATCH 08/87] disk: migrate existing piers to v1 format (epochs) --- pkg/vere/disk.c | 123 ++++++++++++++++++++++++++++++++++++++++++------ pkg/vere/main.c | 6 +-- 2 files changed, 112 insertions(+), 17 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 9aa0f68707..72dd3fcf91 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -891,19 +891,15 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } // XX validation before migration - // // migrate to the correct disk format if necessary - // u3_disk_migrate(log_u); // get latest epoch number - // c3_d lat_d; u3_disk_epoc_last(log_u, &lat_d); // initialize epoch's db - // c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); c3_free(log_c); @@ -984,7 +980,7 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { c3_c epo_c[8193]; snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, new_d); if ( 0 != c3_mkdir(epo_c, 0700) ) { - fprintf(stderr, "disk: failed to create epoch directory\r\n"); + fprintf(stderr, "disk: failed to create epoch directory %" PRIu64 "\r\n", new_d); return c3n; } @@ -1094,7 +1090,7 @@ c3_o u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { c3_o ret_d = c3n; // return no if no epoch directories exist *lat_d = 0; // initialize lat_d to 0 - u3_dent* den_u = log_u->com_u->dil_u; + u3_dent* den_u = u3_foil_folder(log_u->com_u->pax_c)->dil_u; while ( den_u ) { c3_d epo_d = 0; if ( 1 != sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { @@ -1113,23 +1109,122 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { */ void u3_disk_migrate(u3_disk* log_u) { - c3_d lat_d; // latest epoch number + // check if data.mdb exists in log directory + c3_o dat_o = c3n; + c3_c dat_c[8193]; + snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", log_u->com_u->pax_c); + if ( 0 == access(dat_c, F_OK) ) { + dat_o = c3y; + } - // initialize disk v1 on fresh boots - // - if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { // XX ensure fresh boot + // check if any epochs exist + c3_d lat_d; + c3_o epo_o = u3_disk_epoc_last(log_u, &lat_d); + + if ( c3n == epo_o && c3n == dat_o ) { + // initialize disk v1 on fresh boots + fprintf(stderr, "disk: initializing disk with v%d format\r\n", U3D_VER1); + + // initialize first epoch "0i0" + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); + exit(1); + } + } else if ( c3n == epo_o ) { + // migrate existing, unversioned disk to v1 fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); + // initialize pre-migrated lmdb + MDB_env* old_u; + { + const size_t siz_i = + // 500 GiB is as large as musl on aarch64 wants to allow + #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) + 0x7d00000000; + #else + 0x10000000000; + #endif + + if ( 0 == (old_u = u3_lmdb_init(log_u->com_u->pax_c, siz_i)) ) { + fprintf(stderr, "disk: failed to initialize database\r\n"); + c3_free(log_u); + return; + } + } + + // get first/last event numbers from pre-migrated lmdb + c3_d fir_d, las_d; + if ( c3n == u3_lmdb_gulf(old_u, &fir_d, &las_d) ) { + fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); + return; + } + + // boot + u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + + // make sure there's a current snapshot + if ( las_d != u3A->eve_d ) { + fprintf(stderr, "disk: migrate: error: snapshot is out of date, please " + "start/shutdown your pier gracefully first\r\n"); + exit(1); + } + + // shutdown pre-migrated u3 system and lmdb + u3m_stop(); + // initialize first epoch "0i0" if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); exit(1); } - } - // migrate existing, unversioned disk to v1 - // - // XX write this + // move data.mdb to 0i0/data.mdb + c3_c new_c[8193]; + snprintf(new_c, sizeof(new_c), "%s/0i0/data.mdb", log_u->com_u->pax_c); + if ( 0 != rename(dat_c, new_c) ) { + fprintf(stderr, "disk: migrate: failed to move data.mdb\r\n"); + exit(1); + } + + // move lock.mdb to 0i0/lock.mdb + c3_c old_c[8193]; + snprintf(old_c, sizeof(old_c), "%s/lock.mdb", log_u->com_u->pax_c); + snprintf(new_c, sizeof(new_c), "%s/0i0/lock.mdb", log_u->com_u->pax_c); + if ( 0 != rename(old_c, new_c) ) { + fprintf(stderr, "disk: migrate: failed to move lock.mdb\r\n"); + exit(1); + } + + // rollover to new epoch + log_u->mdb_u = old_u; + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); + exit(1); + } + + // delete backup snapshot + c3_c bhk_c[8193]; + snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3_Host.dir_c); + c3_c nop_c[8193]; + snprintf(nop_c, sizeof(nop_c), "%s/north.bin", bhk_c); + c3_c sop_c[8193]; + snprintf(sop_c, sizeof(sop_c), "%s/south.bin", bhk_c); + if ( c3n == c3_unlink(nop_c) ) { + fprintf(stderr, "disk: migrate: failed to delete north.bin\r\n"); + exit(1); + } else if ( c3n == c3_unlink(sop_c) ) { + fprintf(stderr, "disk: migrate: failed to delete south.bin\r\n"); + exit(1); + } else { + if ( c3n == c3_rmdir(bhk_c) ) { + fprintf(stderr, "disk: migrate: failed to delete bhk\r\n"); + exit(1); + } + } + + // success + fprintf(stderr, "disk: migrated disk to v%d format\r\n", U3D_VER1); + } return; } \ No newline at end of file diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 334a9dddd6..c4fd9de29c 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2097,7 +2097,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) exit(1); } - // delete all but the last epoch + // delete all but the newly created epoch u3_dent* den_u = log_u->com_u->dil_u; c3_d epo_d = 0; while ( den_u && epo_d <= lat_d ) { @@ -2191,9 +2191,9 @@ _cw_roll(c3_i argc, c3_c* argv[]) exit(1); } - // report success + // success c3_d epo_d = log_u->dun_d + 1; - fprintf(stderr, "roll: success: created epoch 0i%" PRIu64 "\r\n", epo_d); + fprintf(stderr, "roll: epoch rollover complete"); } /* _cw_vere(): download vere From f8834e0871de94fbf2a55458b23f8c6cffb87fc0 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 26 Apr 2023 13:51:17 -0400 Subject: [PATCH 09/87] disk: validate current snapshot before migration --- pkg/vere/disk.c | 116 ++++++++++++++++++++++++------------------------ pkg/vere/main.c | 10 +++++ pkg/vere/vere.h | 3 +- 3 files changed, 70 insertions(+), 59 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 72dd3fcf91..bd6f8a4d27 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -878,31 +878,33 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) // XX closures? // { - c3_c* log_c = c3_malloc(10 + strlen(pax_c)); - - strcpy(log_c, pax_c); - strcat(log_c, "/.urb/log"); + c3_c log_c[8193]; + snprintf(log_c, sizeof(log_c), "%s/.urb/log", pax_c); if ( 0 == (log_u->com_u = u3_foil_folder(log_c)) ) { fprintf(stderr, "disk: failed to load /.urb/log in %s\r\n", pax_c); - c3_free(log_c); c3_free(log_u); return 0; } - // XX validation before migration - // migrate to the correct disk format if necessary - u3_disk_migrate(log_u); + if ( c3n == u3_disk_migrate(log_u) ) { + fprintf(stderr, "disk: failed to migrate to v%d\r\n", U3D_VER1); + c3_free(log_u); + return 0; + } // get latest epoch number c3_d lat_d; - u3_disk_epoc_last(log_u, &lat_d); + if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { + fprintf(stderr, "disk: failed to load epoch number\r\n"); + c3_free(log_u); + return 0; + } // initialize epoch's db c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); - c3_free(log_c); { // XX extract into function? const size_t siz_i = @@ -932,16 +934,15 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) if ( 0 == las_d ) { // fresh epoch (no events in lmdb yet) if ( 0 == lat_d ) { // first epoch log_u->dun_d = 0; - log_u->sen_d = 0; } else { // not first epoch log_u->dun_d = lat_d - 1; // set dun_d to last event in prev epoch - log_u->sen_d = log_u->dun_d; } } else { // not fresh epoch log_u->dun_d = las_d; // set dun_d to last event in lmdb - log_u->sen_d = las_d; } + log_u->sen_d = log_u->dun_d; + // mark the log as live log_u->liv_o = c3y; } @@ -992,6 +993,9 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { fclose(epv_f); // create binary version file + // XX make sure if you've updated your binary, a new epoch is created + // so that events within an epoch are guaranteed to have been processed + // by the binary version specified in the file c3_c biv_c[8193]; snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); FILE* biv_f = fopen(biv_c, "a"); @@ -1038,7 +1042,7 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { if ( c3y == eps_o ) { if ( c3n == u3_disk_save_meta(log_u->mdb_u, who_d, fak_o, lif_w) ) { fprintf(stderr, "disk: failed to save metadata\r\n"); - exit(1); + goto fail; } } @@ -1093,9 +1097,7 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { u3_dent* den_u = u3_foil_folder(log_u->com_u->pax_c)->dil_u; while ( den_u ) { c3_d epo_d = 0; - if ( 1 != sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { - fprintf(stderr, "disk: epoch directory is not a @ui: %s\r\n", den_u->nam_c); - } else { + if ( 1 == sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { ret_d = c3y; // return yes if at least one epoch directory exists } *lat_d = c3_max(epo_d, *lat_d); // update the latest epoch number @@ -1107,7 +1109,7 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { /* u3_disk_migrate: migrates disk format. */ -void u3_disk_migrate(u3_disk* log_u) +c3_o u3_disk_migrate(u3_disk* log_u) { // check if data.mdb exists in log directory c3_o dat_o = c3n; @@ -1128,12 +1130,9 @@ void u3_disk_migrate(u3_disk* log_u) // initialize first epoch "0i0" if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); - exit(1); + return c3n; } } else if ( c3n == epo_o ) { - // migrate existing, unversioned disk to v1 - fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); - // initialize pre-migrated lmdb MDB_env* old_u; { @@ -1147,8 +1146,7 @@ void u3_disk_migrate(u3_disk* log_u) if ( 0 == (old_u = u3_lmdb_init(log_u->com_u->pax_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); - c3_free(log_u); - return; + return c3n; } } @@ -1156,69 +1154,64 @@ void u3_disk_migrate(u3_disk* log_u) c3_d fir_d, las_d; if ( c3n == u3_lmdb_gulf(old_u, &fir_d, &las_d) ) { fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); - return; + return c3n; } - // boot - u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); - - // make sure there's a current snapshot - if ( las_d != u3A->eve_d ) { + // ensure there's a current snapshot without the below code + if ( u3_Host.eve_d != las_d ) { fprintf(stderr, "disk: migrate: error: snapshot is out of date, please " "start/shutdown your pier gracefully first\r\n"); - exit(1); + return c3n; } - // shutdown pre-migrated u3 system and lmdb - u3m_stop(); - // initialize first epoch "0i0" if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); - exit(1); + return c3n; } - // move data.mdb to 0i0/data.mdb - c3_c new_c[8193]; - snprintf(new_c, sizeof(new_c), "%s/0i0/data.mdb", log_u->com_u->pax_c); - if ( 0 != rename(dat_c, new_c) ) { + // move data.mdb and lock.mdb to 0i0/ + c3_c dut_c[8193], luk_c[8193]; + snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); + snprintf(luk_c, sizeof(luk_c), "%s/lock.mdb", log_u->com_u->pax_c); + + c3_c epo_c[8193], dat_c[8193], lok_c[8193]; + snprintf(epo_c, sizeof(epo_c), "%s/0i0", log_u->com_u->pax_c); + snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); + snprintf(lok_c, sizeof(lok_c), "%s/lock.mdb", epo_c); + + if ( 0 != c3_rename(dut_c, dat_c) ) { fprintf(stderr, "disk: migrate: failed to move data.mdb\r\n"); - exit(1); + goto _u3_disk_migrate_fail; } - - // move lock.mdb to 0i0/lock.mdb - c3_c old_c[8193]; - snprintf(old_c, sizeof(old_c), "%s/lock.mdb", log_u->com_u->pax_c); - snprintf(new_c, sizeof(new_c), "%s/0i0/lock.mdb", log_u->com_u->pax_c); - if ( 0 != rename(old_c, new_c) ) { + if ( 0 != c3_rename(luk_c, lok_c) ) { fprintf(stderr, "disk: migrate: failed to move lock.mdb\r\n"); - exit(1); + c3_rename(dat_c, dut_c); + goto _u3_disk_migrate_fail; } // rollover to new epoch log_u->mdb_u = old_u; if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); - exit(1); + goto _u3_disk_migrate_fail; } - // delete backup snapshot + // delete backup snapshot; migration still succeeds if this fails c3_c bhk_c[8193]; snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3_Host.dir_c); - c3_c nop_c[8193]; + + c3_c nop_c[8193], sop_c[8193]; snprintf(nop_c, sizeof(nop_c), "%s/north.bin", bhk_c); - c3_c sop_c[8193]; snprintf(sop_c, sizeof(sop_c), "%s/south.bin", bhk_c); + if ( c3n == c3_unlink(nop_c) ) { - fprintf(stderr, "disk: migrate: failed to delete north.bin\r\n"); - exit(1); + fprintf(stderr, "disk: migrate: failed to delete bhk/north.bin\r\n"); } else if ( c3n == c3_unlink(sop_c) ) { - fprintf(stderr, "disk: migrate: failed to delete south.bin\r\n"); - exit(1); + fprintf(stderr, "disk: migrate: failed to delete bhk/south.bin\r\n"); } else { if ( c3n == c3_rmdir(bhk_c) ) { - fprintf(stderr, "disk: migrate: failed to delete bhk\r\n"); - exit(1); + fprintf(stderr, "disk: migrate: failed to delete bhk/\r\n"); } } @@ -1226,5 +1219,12 @@ void u3_disk_migrate(u3_disk* log_u) fprintf(stderr, "disk: migrated disk to v%d format\r\n", U3D_VER1); } - return; +_u3_disk_migrate_fail: +{ + c3_d lat_d; + u3_disk_epoc_last(log_u, &lat_d); + u3_disk_epoc_kill(log_u, lat_d); +} + + return c3y; } \ No newline at end of file diff --git a/pkg/vere/main.c b/pkg/vere/main.c index c4fd9de29c..3dbe724ea7 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -1971,6 +1971,8 @@ _cw_play(c3_i argc, c3_c* argv[]) static void _cw_prep(c3_i argc, c3_c* argv[]) { + // XX roll with old binary + // check that new epoch is empty, migrate snapshot in-place c3_i ch_i, lid_i; c3_w arg_w; @@ -2025,6 +2027,7 @@ _cw_prep(c3_i argc, c3_c* argv[]) static void _cw_chop(c3_i argc, c3_c* argv[]) { + // XX keep the last epoch (2 epochs left after chop) c3_i ch_i, lid_i; c3_w arg_w; @@ -2630,6 +2633,13 @@ main(c3_i argc, } } + // we need the current snapshot's latest event number to + // validate whether we can execute disk migration + if ( c3n == u3_Host.ops_u.nuu ) { + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + // XX u3e_close() + } + // starting u3m configures OpenSSL memory functions, so we must do it // before any OpenSSL allocations // diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index a2726d2341..eeaa8cec4f 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -312,6 +312,7 @@ typedef struct _u3_host { c3_w kno_w; // current executing stage c3_c* dir_c; // pier path (no trailing /) + c3_d eve_d; // initial current snapshot c3_c* dem_c; // daemon executable path c3_c* wrk_c; // worker executable path c3_d now_d; // event tick @@ -999,7 +1000,7 @@ /* u3_disk_migrate(): migrates disk format. */ - void + c3_o u3_disk_migrate(u3_disk* log_u); /* u3_lord_init(): start serf. From b93508e1704090ad2796b2e3c8a4071ab68b5fc8 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 28 Apr 2023 11:29:32 -0400 Subject: [PATCH 10/87] lmdb: factor siz_i calculation --- pkg/vere/db/lmdb.c | 11 ++++++++++- pkg/vere/db/lmdb.h | 2 +- pkg/vere/disk.c | 32 ++++---------------------------- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/pkg/vere/db/lmdb.c b/pkg/vere/db/lmdb.c index 8f8864b77f..d9fed4c0de 100644 --- a/pkg/vere/db/lmdb.c +++ b/pkg/vere/db/lmdb.c @@ -38,11 +38,20 @@ intmax_t mdb_get_filesize(mdb_filehandle_t han_u); /* u3_lmdb_init(): open lmdb at [pax_c], mmap up to [siz_i]. */ MDB_env* -u3_lmdb_init(const c3_c* pax_c, size_t siz_i) +u3_lmdb_init(const c3_c* pax_c) { MDB_env* env_u; c3_w ret_w; + // calculate db size based on architecture + const size_t siz_i = + // 500 GiB is as large as musl on aarch64 wants to allow + #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) + 0x7d00000000; + #else + 0x10000000000; + #endif + if ( (ret_w = mdb_env_create(&env_u)) ) { mdb_logerror(stderr, ret_w, "lmdb: init fail"); return 0; diff --git a/pkg/vere/db/lmdb.h b/pkg/vere/db/lmdb.h index aab4e6c9f7..7aa996001f 100644 --- a/pkg/vere/db/lmdb.h +++ b/pkg/vere/db/lmdb.h @@ -22,7 +22,7 @@ /* u3_lmdb_init(): open lmdb at [pax_c], mmap up to [siz_i]. */ MDB_env* - u3_lmdb_init(const c3_c* pax_c, size_t siz_i); + u3_lmdb_init(const c3_c* pax_c); /* u3_lmdb_exit(): close lmdb. */ diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index bd6f8a4d27..19dce9087c 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -906,16 +906,8 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); { - // XX extract into function? - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif - - if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { + + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); return 0; @@ -1023,15 +1015,7 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { // initialize db of new epoch { - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif - - if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); goto fail; @@ -1136,15 +1120,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) // initialize pre-migrated lmdb MDB_env* old_u; { - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif - - if ( 0 == (old_u = u3_lmdb_init(log_u->com_u->pax_c, siz_i)) ) { + if ( 0 == (old_u = u3_lmdb_init(log_u->com_u->pax_c)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); return c3n; } From bb1f786c2a72abe6e111262e0b8c435d79defa2c Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 28 Apr 2023 13:04:46 -0400 Subject: [PATCH 11/87] disk: create new epoch when vere version is different --- pkg/vere/disk.c | 69 +++++++++++++++++++++++++++++++++++++------------ pkg/vere/main.c | 24 ++++++++++++++--- 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 19dce9087c..2c1d1e0622 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -902,9 +902,48 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } - // initialize epoch's db + // set path to latest epoch c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); + + // get vere version from the latest epoch + c3_c fil_c[8193]; + snprintf(fil_c, 8192, "%s/vere.txt", epo_c); + if ( 0 != access(fil_c, F_OK) ) { + fprintf(stderr, "disk: failed to access %s\r\n", fil_c); + c3_free(log_u); + return 0; + } + + // read string from vere.txt file + c3_c ver_c[8193]; + { + FILE* fil_u = fopen(fil_c, "r"); + if ( !fil_u ) { + fprintf(stderr, "disk: failed to open %s\r\n", fil_c); + c3_free(log_u); + return 0; + } + if ( !fgets(ver_c, 8192, fil_u) ) { + fprintf(stderr, "disk: failed to read %s\r\n", fil_c); + c3_free(log_u); + return 0; + } + fclose(fil_u); + } + + // if binary version from vere.txt is different + // than current version, then create a new epoch + if ( 0 != strcmp(ver_c, URBIT_VERSION) ) { + fprintf(stderr, "disk: binary version mismatch, creating new epoch\r\n"); + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "disk: failed to initialize epoch\r\n"); + c3_free(log_u); + return 0; + } + } + + // initialize epoch's db { if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { @@ -956,16 +995,12 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { if ( c3n == eps_o ) { new_d = 0; // no epochs yet, so create first one 0i0 } else { - // ensure latest epoch isn't empty + // get first/last event numbers c3_d fir_d, las_d; if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); return c3n; } - if ( fir_d == las_d ) { - fprintf(stderr, "disk: latest epoch is empty; skipping rollover\r\n"); - return c3n; - } new_d = 1 + las_d; // create next epoch } @@ -1117,6 +1152,9 @@ c3_o u3_disk_migrate(u3_disk* log_u) return c3n; } } else if ( c3n == epo_o ) { + // migrate existing pier + fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); + // initialize pre-migrated lmdb MDB_env* old_u; { @@ -1158,19 +1196,25 @@ c3_o u3_disk_migrate(u3_disk* log_u) if ( 0 != c3_rename(dut_c, dat_c) ) { fprintf(stderr, "disk: migrate: failed to move data.mdb\r\n"); - goto _u3_disk_migrate_fail; + u3_disk_epoc_last(log_u, &lat_d); + u3_disk_epoc_kill(log_u, lat_d); + return c3n; } if ( 0 != c3_rename(luk_c, lok_c) ) { fprintf(stderr, "disk: migrate: failed to move lock.mdb\r\n"); c3_rename(dat_c, dut_c); - goto _u3_disk_migrate_fail; + u3_disk_epoc_last(log_u, &lat_d); + u3_disk_epoc_kill(log_u, lat_d); + return c3n; } // rollover to new epoch log_u->mdb_u = old_u; if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); - goto _u3_disk_migrate_fail; + u3_disk_epoc_last(log_u, &lat_d); + u3_disk_epoc_kill(log_u, lat_d); + return c3n; } // delete backup snapshot; migration still succeeds if this fails @@ -1195,12 +1239,5 @@ c3_o u3_disk_migrate(u3_disk* log_u) fprintf(stderr, "disk: migrated disk to v%d format\r\n", U3D_VER1); } -_u3_disk_migrate_fail: -{ - c3_d lat_d; - u3_disk_epoc_last(log_u, &lat_d); - u3_disk_epoc_kill(log_u, lat_d); -} - return c3y; } \ No newline at end of file diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 3dbe724ea7..ba073d1b21 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2088,7 +2088,16 @@ _cw_chop(c3_i argc, c3_c* argv[]) } // create new epoch - if ( c3n == u3_disk_epoc_init(log_u) ) { + c3_d fir_d, las_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { + fprintf(stderr, "chop: failed to get first/last events\r\n"); + exit(1); + } + if ( fir_d == las_d == 0 ) { + fprintf(stderr, "chop: latest epoch already empty\r\n"); + exit(1); + } + else if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "chop: failed to create new epoch\r\n"); exit(1); } @@ -2189,8 +2198,17 @@ _cw_roll(c3_i argc, c3_c* argv[]) } // create new epoch - if ( c3n == u3_disk_epoc_init(log_u) ) { - fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); + c3_d fir_d, las_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { + fprintf(stderr, "roll: failed to get first/last events\r\n"); + exit(1); + } + if ( fir_d == las_d == 0 ) { + fprintf(stderr, "roll: latest epoch already empty\r\n"); + exit(1); + } + else if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "roll: failed to create new epoch\r\n"); exit(1); } From 5b432b6b3ec8188d002ff8a32f0c52522dc0c1e9 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 1 May 2023 08:54:08 -0400 Subject: [PATCH 12/87] cli: make `chop` leave only the latest two epochs --- pkg/vere/disk.c | 42 ++---------------------------------------- pkg/vere/main.c | 25 ++++++++++++++++--------- 2 files changed, 18 insertions(+), 49 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 2c1d1e0622..d4ca5a21b8 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -906,43 +906,6 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); - // get vere version from the latest epoch - c3_c fil_c[8193]; - snprintf(fil_c, 8192, "%s/vere.txt", epo_c); - if ( 0 != access(fil_c, F_OK) ) { - fprintf(stderr, "disk: failed to access %s\r\n", fil_c); - c3_free(log_u); - return 0; - } - - // read string from vere.txt file - c3_c ver_c[8193]; - { - FILE* fil_u = fopen(fil_c, "r"); - if ( !fil_u ) { - fprintf(stderr, "disk: failed to open %s\r\n", fil_c); - c3_free(log_u); - return 0; - } - if ( !fgets(ver_c, 8192, fil_u) ) { - fprintf(stderr, "disk: failed to read %s\r\n", fil_c); - c3_free(log_u); - return 0; - } - fclose(fil_u); - } - - // if binary version from vere.txt is different - // than current version, then create a new epoch - if ( 0 != strcmp(ver_c, URBIT_VERSION) ) { - fprintf(stderr, "disk: binary version mismatch, creating new epoch\r\n"); - if ( c3n == u3_disk_epoc_init(log_u) ) { - fprintf(stderr, "disk: failed to initialize epoch\r\n"); - c3_free(log_u); - return 0; - } - } - // initialize epoch's db { @@ -966,12 +929,11 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) if ( 0 == lat_d ) { // first epoch log_u->dun_d = 0; } else { // not first epoch - log_u->dun_d = lat_d - 1; // set dun_d to last event in prev epoch + log_u->dun_d = lat_d; // set dun_d to last event in prev epoch } } else { // not fresh epoch log_u->dun_d = las_d; // set dun_d to last event in lmdb } - log_u->sen_d = log_u->dun_d; // mark the log as live @@ -1001,7 +963,7 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); return c3n; } - new_d = 1 + las_d; // create next epoch + new_d = las_d; // create next epoch } // create new epoch directory diff --git a/pkg/vere/main.c b/pkg/vere/main.c index ba073d1b21..b122aa45ab 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2027,7 +2027,6 @@ _cw_prep(c3_i argc, c3_c* argv[]) static void _cw_chop(c3_i argc, c3_c* argv[]) { - // XX keep the last epoch (2 epochs left after chop) c3_i ch_i, lid_i; c3_w arg_w; @@ -2087,13 +2086,20 @@ _cw_chop(c3_i argc, c3_c* argv[]) exit(1); } + // get latest epoch number prior to creating a new one + c3_d pre_d; + if ( c3n == u3_disk_epoc_last(log_u, &pre_d) ) { + fprintf(stderr, "chop: failed to find last epoch\r\n"); + exit(1); + } + // create new epoch c3_d fir_d, las_d; if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { fprintf(stderr, "chop: failed to get first/last events\r\n"); exit(1); } - if ( fir_d == las_d == 0 ) { + if ( fir_d == las_d ) { fprintf(stderr, "chop: latest epoch already empty\r\n"); exit(1); } @@ -2102,20 +2108,20 @@ _cw_chop(c3_i argc, c3_c* argv[]) exit(1); } - // get latest epoch number - c3_d lat_d; - if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { + // get latest epoch number prior to creating a new one + c3_d pos_d; + if ( c3n == u3_disk_epoc_last(log_u, &pos_d) ) { fprintf(stderr, "chop: failed to find last epoch\r\n"); exit(1); } - // delete all but the newly created epoch + // delete all but the last two epochs u3_dent* den_u = log_u->com_u->dil_u; c3_d epo_d = 0; - while ( den_u && epo_d <= lat_d ) { + while ( den_u ) { if ( 1 != sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { fprintf(stderr, "disk: epoch directory is not a @ui: %s\r\n", den_u->nam_c); - } else { + } else if ( epo_d != pre_d && epo_d != pos_d ) { fprintf(stderr, "chop: deleting epoch 0i%" PRIu64 "\r\n", epo_d); if ( c3y != u3_disk_epoc_kill(log_u, epo_d) ) { fprintf(stderr, "chop: failed to delete epoch 0i%" PRIu64 "\r\n", epo_d); @@ -2203,7 +2209,8 @@ _cw_roll(c3_i argc, c3_c* argv[]) fprintf(stderr, "roll: failed to get first/last events\r\n"); exit(1); } - if ( fir_d == las_d == 0 ) { + + if ( fir_d == las_d ) { fprintf(stderr, "roll: latest epoch already empty\r\n"); exit(1); } From 2e9da020793173c32d3589330f7b148f11530f1c Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 1 May 2023 10:16:10 -0400 Subject: [PATCH 13/87] disk: create a new epoch when version change detected --- pkg/vere/disk.c | 56 ++++++++++++++++++++++++++++++++++++++++--------- pkg/vere/main.c | 5 ++--- pkg/vere/vere.h | 5 +++++ 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index d4ca5a21b8..866e6b9391 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -875,7 +875,6 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } // create/load $pier/.urb/log - // XX closures? // { c3_c log_c[8193]; @@ -902,18 +901,23 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } + // get binary version from latest epoch + c3_c ver_w[8193]; + if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_w) ) { + fprintf(stderr, "disk: failed to load epoch version\r\n"); + c3_free(log_u); + return 0; + } + // set path to latest epoch c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); - // initialize epoch's db - { - - if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { - fprintf(stderr, "disk: failed to initialize database\r\n"); - c3_free(log_u); - return 0; - } + // initialize latest epoch's db + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { + fprintf(stderr, "disk: failed to initialize database\r\n"); + c3_free(log_u); + return 0; } fprintf(stderr, "disk: loaded epoch 0i%" PRIu64 "\r\n", lat_d); @@ -936,6 +940,16 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } log_u->sen_d = log_u->dun_d; + // if binary version of latest epoch is not the same as the + // running binary, then we need to create a new epoch + if ( 0 != strcmp(ver_w, URBIT_VERSION) ) { + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "disk: failed to initialize epoch\r\n"); + c3_free(log_u); + return 0; + } + } + // mark the log as live log_u->liv_o = c3y; } @@ -1088,6 +1102,29 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { return ret_d; } +/* u3_disk_epoc_vere: get binary version from epoch. +*/ +c3_o +u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) { + c3_c ver_c[8193]; + snprintf(ver_c, sizeof(ver_c), "%s/0i%" PRIu64 "/vere.txt", + log_u->com_u->pax_c, epo_d); + + FILE* fil_u = fopen(ver_c, "r"); + if ( NULL == fil_u ) { + fprintf(stderr, "disk: failed to open vere.txt in epoch 0i%" PRIu64 + "\r\n", epo_d); + return c3n; + } + + if ( 1 != fscanf(fil_u, "%s", ver_w) ) { + fprintf(stderr, "disk: failed to read vere.txt in epoch 0i%" PRIu64 + "\r\n", epo_d); + return c3n; + } + return c3y; +} + /* u3_disk_migrate: migrates disk format. */ c3_o u3_disk_migrate(u3_disk* log_u) @@ -1115,7 +1152,6 @@ c3_o u3_disk_migrate(u3_disk* log_u) } } else if ( c3n == epo_o ) { // migrate existing pier - fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); // initialize pre-migrated lmdb MDB_env* old_u; diff --git a/pkg/vere/main.c b/pkg/vere/main.c index b122aa45ab..838cac5388 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2119,9 +2119,8 @@ _cw_chop(c3_i argc, c3_c* argv[]) u3_dent* den_u = log_u->com_u->dil_u; c3_d epo_d = 0; while ( den_u ) { - if ( 1 != sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { - fprintf(stderr, "disk: epoch directory is not a @ui: %s\r\n", den_u->nam_c); - } else if ( epo_d != pre_d && epo_d != pos_d ) { + c3_d res_d = sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d); + if ( (1 == res_d) && (epo_d != pre_d) && (epo_d != pos_d) ) { fprintf(stderr, "chop: deleting epoch 0i%" PRIu64 "\r\n", epo_d); if ( c3y != u3_disk_epoc_kill(log_u, epo_d) ) { fprintf(stderr, "chop: failed to delete epoch 0i%" PRIu64 "\r\n", epo_d); diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index eeaa8cec4f..f54fa2a6d6 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -998,6 +998,11 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d); + /* u3_disk_epoc_vere(): get binary version from epoch. + */ + c3_o + u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w); + /* u3_disk_migrate(): migrates disk format. */ c3_o From 1b952d06aecc24dde76f9944466c71149fd905d2 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 16 May 2023 12:02:01 -0400 Subject: [PATCH 14/87] c3: add `c3_link` --- pkg/c3/defs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/c3/defs.h b/pkg/c3/defs.h index 38b39263a9..bbf8d91ef7 100644 --- a/pkg/c3/defs.h +++ b/pkg/c3/defs.h @@ -149,6 +149,8 @@ mkdir(a, b);}) # define c3_rmdir(a) ({ \ rmdir(a);}) +# define c3_link(a, b) ({ \ + link(a, b);}) # define c3_unlink(a) ({ \ unlink(a);}) # define c3_fopen(a, b) ({ \ From b0da9beb58ee47ac306fe03d01e8ac461156ce13 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 18 May 2023 13:37:08 -0400 Subject: [PATCH 15/87] disk: make migration idempotent (crash safe) --- pkg/vere/disk.c | 212 +++++++++++++++++++++++++++++++++++++----------- pkg/vere/main.c | 4 +- pkg/vere/vere.h | 5 ++ 3 files changed, 173 insertions(+), 48 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 866e6b9391..3985528493 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -962,6 +962,87 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return log_u; } +/* u3_disk_epoc_good: check for valid epoch. +*/ +c3_o u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { + /* a "valid" epoch is currently defined as a writable folder in + * the /.urb/log directory named with a @ui and contains: + * - a writable data.mdb file which can be opened by lmdb (add db checking?) + * - a writable epoc.txt file + * - a writable vere.txt file + * + * XX: should we check if the correct event sequence exists in the data.mdb file? + * + * note that this does not check if the epoch even contains snapshot files, + * let alone whether they're valid or not + */ + + c3_o ret_o = c3y; // return code + + // file paths + c3_c epo_c[8193], dat_c[8193], epv_c[8193], biv_c[8193]; + snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, epo_d); + snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); + snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); + snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); + + c3_o dir_o = c3n; // directory is writable + c3_o dat_o = c3n; // data.mdb is writable + c3_o mdb_o = c3n; // data.mdb can be opened + c3_o epv_o = c3n; // epoc.txt is writable + c3_o biv_o = c3n; // vere.txt is writable + + // check if dir is writable + if ( 0 == access(epo_c, W_OK) ) { + dir_o = c3y; + } + + // check if data.mdb is writable + if ( 0 == access(dat_c, W_OK) ) { + dat_o = c3y; + // check if we can open data.mdb + MDB_env* env_u; + if ( 0 != (env_u = u3_lmdb_init(epo_c)) ) { + mdb_o = c3y; + } + u3_lmdb_exit(env_u); + } + + // check if epoc.txt is writable + if ( 0 == access(epv_c, W_OK) ) { + epv_o = c3y; + } + + // check if vere.txt is writable + if ( 0 == access(biv_c, W_OK) ) { + biv_o = c3y; + } + + // print error messages + if ( c3n == dir_o ) { + fprintf(stderr, "disk: epoch 0i%" PRIu64 " is not writable\r\n", epo_d); + ret_o = c3n; + } + if ( c3n == dat_o ) { + fprintf(stderr, "disk: epoch 0i%" PRIu64 "/data.mdb is not writable\r\n", epo_d); + ret_o = c3n; + } + if ( c3n == mdb_o ) { + fprintf(stderr, "disk: epoch 0i%" PRIu64 "/data.mdb can't be opened\r\n", epo_d); + ret_o = c3n; + } + if ( c3n == epv_o ) { + fprintf(stderr, "disk: epoch 0i%" PRIu64 "/epoc.txt is not writable\r\n", epo_d); + ret_o = c3n; + } + if ( c3n == biv_o ) { + fprintf(stderr, "disk: epoch 0i%" PRIu64 "/vere.txt is not writable\r\n", epo_d); + ret_o = c3n; + } + + return ret_o; +} + /* u3_disk_epoc_init: create new epoch. */ c3_o u3_disk_epoc_init(u3_disk* log_u) { @@ -969,8 +1050,14 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { c3_d lat_d, new_d; c3_o eps_o = u3_disk_epoc_last(log_u, &lat_d); if ( c3n == eps_o ) { - new_d = 0; // no epochs yet, so create first one 0i0 + // no epochs yet, so create first one 0i0 + new_d = 0; + } else if ( c3n == u3_disk_epoc_good(log_u, lat_d) ) { + // last epoch is invalid, so overwrite it + new_d = lat_d; } else { + // last epoch is valid, so create next one + // get first/last event numbers c3_d fir_d, las_d; if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { @@ -980,28 +1067,26 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { new_d = las_d; // create next epoch } - // create new epoch directory + // create new epoch directory if it doesn't exist c3_c epo_c[8193]; snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, new_d); - if ( 0 != c3_mkdir(epo_c, 0700) ) { + c3_d ret_d = c3_mkdir(epo_c, 0700); + if ( ( ret_d < 0 ) && ( errno != EEXIST ) ) { fprintf(stderr, "disk: failed to create epoch directory %" PRIu64 "\r\n", new_d); return c3n; } - // create epoch version file + // create epoch version file, overwriting any existing file c3_c epv_c[8193]; snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); - FILE* epv_f = fopen(epv_c, "a"); + FILE* epv_f = fopen(epv_c, "w"); fprintf(epv_f, "%d\n", U3D_VER1); fclose(epv_f); - // create binary version file - // XX make sure if you've updated your binary, a new epoch is created - // so that events within an epoch are guaranteed to have been processed - // by the binary version specified in the file + // create binary version file, overwriting any existing file c3_c biv_c[8193]; snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); - FILE* biv_f = fopen(biv_c, "a"); + FILE* biv_f = fopen(biv_c, "w"); fprintf(biv_f, URBIT_VERSION); fclose(biv_f); @@ -1013,7 +1098,7 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { } } - // get metadata from old epoch's db + // get metadata from old epoch or unmigrated event log's db c3_d who_d[2]; c3_o fak_o; c3_w lif_w; @@ -1025,7 +1110,13 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { } // initialize db of new epoch - { + if ( c3y == u3_Host.ops_u.nuu || new_d > 0 ) { + c3_c dat_c[8193]; + snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); + // if ( c3n == c3_unlink(dat_c) ) { + // fprintf(stderr, "disk: failed to rm 0i%" PRIu64 "/data.mdb\r\n", new_d); + // goto fail; + // }; if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); @@ -1093,7 +1184,7 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { while ( den_u ) { c3_d epo_d = 0; if ( 1 == sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { - ret_d = c3y; // return yes if at least one epoch directory exists + ret_d = c3y; // NB: returns yes if the directory merely exists } *lat_d = c3_max(epo_d, *lat_d); // update the latest epoch number den_u = den_u->nex_u; @@ -1129,19 +1220,42 @@ u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) { */ c3_o u3_disk_migrate(u3_disk* log_u) { - // check if data.mdb exists in log directory + /* migration steps: + * 0. detect whether we need to migrate or not + * a. if it's a fresh boot via u3_Host.ops_u.nuu -> skip migration + * b. if data.mdb is readable in log directory -> execute migration + * 1. initialize epoch 0i0 (first call to u3_disk_epoc_init()) + * a. creates epoch directory + * b. creates epoch version file + * c. creates binary version file + * d. initializes database + * e. reads metadata from old database + * f. writes metadata to new database + * g. loads new epoch directory and sets it in log_u + * 2. create hard links to data.mdb and lock.mdb in 0i0/ + * 3. rollover to new epoch (second call to u3_disk_epoc_init()) + * a. same as 1a-g but also copies current snapshot between c/d steps + * 4. delete backup snapshot (c3_unlink() and c3_rmdir() calls) + * 5. delete old data.mdb and lock.mdb files (c3_unlink() calls) + */ + + // check if data.mdb is readable in log directory c3_o dat_o = c3n; c3_c dat_c[8193]; snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", log_u->com_u->pax_c); - if ( 0 == access(dat_c, F_OK) ) { + if ( 0 == access(dat_c, R_OK) ) { dat_o = c3y; } - // check if any epochs exist - c3_d lat_d; - c3_o epo_o = u3_disk_epoc_last(log_u, &lat_d); + // check if lock.mdb is readable in log directory + c3_o lok_o = c3n; + c3_c lok_c[8193]; + snprintf(lok_c, sizeof(dat_c), "%s/data.mdb", log_u->com_u->pax_c); + if ( 0 == access(dat_c, R_OK) ) { + lok_o = c3y; + } - if ( c3n == epo_o && c3n == dat_o ) { + if ( c3y == u3_Host.ops_u.nuu ) { // initialize disk v1 on fresh boots fprintf(stderr, "disk: initializing disk with v%d format\r\n", U3D_VER1); @@ -1150,13 +1264,14 @@ c3_o u3_disk_migrate(u3_disk* log_u) fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); return c3n; } - } else if ( c3n == epo_o ) { - // migrate existing pier + } else if ( c3y == dat_o ) { + // migrate existing pier which has either: + // - not started the migration, or + // - crashed before completing the migration // initialize pre-migrated lmdb - MDB_env* old_u; { - if ( 0 == (old_u = u3_lmdb_init(log_u->com_u->pax_c)) ) { + if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_u->com_u->pax_c)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); return c3n; } @@ -1164,15 +1279,17 @@ c3_o u3_disk_migrate(u3_disk* log_u) // get first/last event numbers from pre-migrated lmdb c3_d fir_d, las_d; - if ( c3n == u3_lmdb_gulf(old_u, &fir_d, &las_d) ) { + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); return c3n; } - // ensure there's a current snapshot without the below code + // ensure there's a current snapshot if ( u3_Host.eve_d != las_d ) { fprintf(stderr, "disk: migrate: error: snapshot is out of date, please " "start/shutdown your pier gracefully first\r\n"); + fprintf(stderr, "disk: migrate: eve_d (%" PRIu64 ") != las_d (%" PRIu64 ")\r\n", + u3_Host.eve_d, las_d); return c3n; } @@ -1182,47 +1299,41 @@ c3_o u3_disk_migrate(u3_disk* log_u) return c3n; } - // move data.mdb and lock.mdb to 0i0/ - c3_c dut_c[8193], luk_c[8193]; + // create hard links to data.mdb and lock.mdb in 0i0/ + c3_c dut_c[8193], luk_c[8193]; // old paths snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); snprintf(luk_c, sizeof(luk_c), "%s/lock.mdb", log_u->com_u->pax_c); - c3_c epo_c[8193], dat_c[8193], lok_c[8193]; + c3_c epo_c[8193], dat_c[8193], lok_c[8193]; // new paths snprintf(epo_c, sizeof(epo_c), "%s/0i0", log_u->com_u->pax_c); snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); snprintf(lok_c, sizeof(lok_c), "%s/lock.mdb", epo_c); - if ( 0 != c3_rename(dut_c, dat_c) ) { - fprintf(stderr, "disk: migrate: failed to move data.mdb\r\n"); - u3_disk_epoc_last(log_u, &lat_d); - u3_disk_epoc_kill(log_u, lat_d); + if ( 0 < c3_link(dut_c, dat_c) ) { + fprintf(stderr, "disk: migrate: failed to create data.mdb hard link\r\n"); + fprintf(stderr, "errno %d: %s\r\n", errno, strerror(errno)); return c3n; } - if ( 0 != c3_rename(luk_c, lok_c) ) { - fprintf(stderr, "disk: migrate: failed to move lock.mdb\r\n"); - c3_rename(dat_c, dut_c); - u3_disk_epoc_last(log_u, &lat_d); - u3_disk_epoc_kill(log_u, lat_d); - return c3n; + if ( c3y == lok_o ) { // only link lock.mdb if it exists + if ( 0 < c3_link(luk_c, lok_c) ) { + fprintf(stderr, "disk: migrate: failed to create lock.mdb hard link\r\n"); + c3_rename(dat_c, dut_c); + return c3n; + } } // rollover to new epoch - log_u->mdb_u = old_u; + // log_u->mdb_u = old_u; if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); - u3_disk_epoc_last(log_u, &lat_d); - u3_disk_epoc_kill(log_u, lat_d); return c3n; } - // delete backup snapshot; migration still succeeds if this fails - c3_c bhk_c[8193]; + // delete backup snapshot + c3_c bhk_c[8193], nop_c[8193], sop_c[8193]; snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3_Host.dir_c); - - c3_c nop_c[8193], sop_c[8193]; snprintf(nop_c, sizeof(nop_c), "%s/north.bin", bhk_c); snprintf(sop_c, sizeof(sop_c), "%s/south.bin", bhk_c); - if ( c3n == c3_unlink(nop_c) ) { fprintf(stderr, "disk: migrate: failed to delete bhk/north.bin\r\n"); } else if ( c3n == c3_unlink(sop_c) ) { @@ -1233,6 +1344,15 @@ c3_o u3_disk_migrate(u3_disk* log_u) } } + // delete old lock.mdb and data.mdb files + if ( 0 != c3_unlink(luk_c) ) { + fprintf(stderr, "disk: migrate: failed to unlink lock.mdb\r\n"); + } + if ( 0 != c3_unlink(dut_c) ) { + fprintf(stderr, "disk: migrate: failed to unlink data.mdb\r\n"); + return c3n; // migration succeeds only if we can unlink data.mdb + } + // success fprintf(stderr, "disk: migrated disk to v%d format\r\n", U3D_VER1); } diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 838cac5388..7d69ed179f 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2220,7 +2220,7 @@ _cw_roll(c3_i argc, c3_c* argv[]) // success c3_d epo_d = log_u->dun_d + 1; - fprintf(stderr, "roll: epoch rollover complete"); + fprintf(stderr, "roll: epoch rollover complete\r\n"); } /* _cw_vere(): download vere @@ -2659,7 +2659,7 @@ main(c3_i argc, // we need the current snapshot's latest event number to // validate whether we can execute disk migration - if ( c3n == u3_Host.ops_u.nuu ) { + if ( u3_Host.ops_u.nuu == c3n ) { u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); // XX u3e_close() } diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index f54fa2a6d6..1e76053d10 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -982,6 +982,11 @@ */ void u3_disk_plan(u3_disk* log_u, u3_fact* tac_u); + + /* u3_disk_epoc_good(): check for valid epoch. + */ + c3_o + u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d); /* u3_disk_epoc_init(): create new epoch. */ From 3b1ee9a0d2b8c5217c16b7bae563c924a7aae751 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 25 May 2023 15:08:04 -0400 Subject: [PATCH 16/87] cli: fix `chop` bug --- pkg/vere/disk.c | 1 + pkg/vere/main.c | 64 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 3985528493..ce6930ea89 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1224,6 +1224,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) * 0. detect whether we need to migrate or not * a. if it's a fresh boot via u3_Host.ops_u.nuu -> skip migration * b. if data.mdb is readable in log directory -> execute migration + * if not -> skip migration * 1. initialize epoch 0i0 (first call to u3_disk_epoc_init()) * a. creates epoch directory * b. creates epoch version file diff --git a/pkg/vere/main.c b/pkg/vere/main.c index c3da6be457..7f9d360e9a 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2157,15 +2157,48 @@ _cw_chop(c3_i argc, c3_c* argv[]) fprintf(stderr, "chop: failed to get first/last events\r\n"); exit(1); } - if ( fir_d == las_d ) { - fprintf(stderr, "chop: latest epoch already empty\r\n"); - exit(1); - } - else if ( c3n == u3_disk_epoc_init(log_u) ) { + + // create new epoch if latest isn't empty + if ( (fir_d != las_d) && (c3n == u3_disk_epoc_init(log_u)) ) { fprintf(stderr, "chop: failed to create new epoch\r\n"); exit(1); } + // sort epoch directories in descending order + u3_dire* ned_u = u3_foil_folder(log_u->com_u->pax_c); + u3_dent* den_u = ned_u->dil_u; + c3_z len_z = 0; + while ( den_u ) { // count epochs + len_z++; + den_u = den_u->nex_u; + } + c3_d* sot_d = c3_malloc(len_z * sizeof(c3_d)); + len_z = 0; + den_u = ned_u->dil_u; + while ( den_u ) { + if ( 1 == sscanf(den_u->nam_c, "0i%" PRIu64, (sot_d + len_z)) ) { + len_z++; + } + den_u = den_u->nex_u; + } + + if ( len_z <= 2 ) { + fprintf(stderr, "chop: nothing to do, have a great day\r\n"); + exit(0); // enjoy + } + + // sort sot_d naively in descending order + c3_d tmp_d; + for ( c3_z i_z = 0; i_z < len_z; i_z++ ) { + for ( c3_z j_z = i_z + 1; j_z < len_z; j_z++ ) { + if ( sot_d[i_z] < sot_d[j_z] ) { + tmp_d = sot_d[i_z]; + sot_d[i_z] = sot_d[j_z]; + sot_d[j_z] = tmp_d; + } + } + } + // get latest epoch number prior to creating a new one c3_d pos_d; if ( c3n == u3_disk_epoc_last(log_u, &pos_d) ) { @@ -2174,20 +2207,25 @@ _cw_chop(c3_i argc, c3_c* argv[]) } // delete all but the last two epochs - u3_dent* den_u = log_u->com_u->dil_u; + // XX parameterize the number of epochs to chop + for ( c3_z i_z = 2; i_z < len_z; i_z++ ) { + fprintf(stderr, "chop: deleting epoch 0i%" PRIu64 "\r\n", sot_d[i_z]); + if ( c3y != u3_disk_epoc_kill(log_u, sot_d[i_z]) ) { + fprintf(stderr, "chop: failed to delete epoch 0i%" PRIu64 "\r\n", sot_d[i_z]); + exit(1); + } + } + c3_d epo_d = 0; while ( den_u ) { - c3_d res_d = sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d); - if ( (1 == res_d) && (epo_d != pre_d) && (epo_d != pos_d) ) { - fprintf(stderr, "chop: deleting epoch 0i%" PRIu64 "\r\n", epo_d); - if ( c3y != u3_disk_epoc_kill(log_u, epo_d) ) { - fprintf(stderr, "chop: failed to delete epoch 0i%" PRIu64 "\r\n", epo_d); - } + c3_i res_i = sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d); + if ( (1 == res_i) && (epo_d < pre_d) && (epo_d < pos_d) ) { } den_u = den_u->nex_u; } // cleanup + u3_dire_free(ned_u); u3_disk_exit(log_u); u3m_stop(); @@ -2269,7 +2307,7 @@ _cw_roll(c3_i argc, c3_c* argv[]) if ( fir_d == las_d ) { fprintf(stderr, "roll: latest epoch already empty\r\n"); - exit(1); + exit(0); } else if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "roll: failed to create new epoch\r\n"); From b8b52c239e4f2c3de03a119999a6c7408039f8f3 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 26 May 2023 09:43:55 -0400 Subject: [PATCH 17/87] disk: move format version to `version.h` --- pkg/noun/version.h | 6 ++++++ pkg/vere/disk.c | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/noun/version.h b/pkg/noun/version.h index f64d0a398e..125abd684c 100644 --- a/pkg/noun/version.h +++ b/pkg/noun/version.h @@ -18,4 +18,10 @@ typedef c3_w u3e_version; #define U3E_VER1 1 #define U3E_VERLAT U3E_VER1 +/* DISK FORMAT + */ + +#define U3D_VER1 1 +#define U3D_VERLAT U3L_VER1 + #endif /* ifndef U3_VERSION_H */ diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index ce6930ea89..2138ed4205 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -23,12 +23,6 @@ struct _cd_save { struct _u3_disk* log_u; }; -/* DISK FORMAT - */ - -#define U3D_VER1 1 -#define U3D_VERLAT U3L_VER1 - #undef VERBOSE_DISK #undef DISK_TRACE_JAM #undef DISK_TRACE_CUE From 6582f14ad1be153d2ed636ae8077efd90fc26a03 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 30 May 2023 11:47:23 -0400 Subject: [PATCH 18/87] disk: use `PRIc3_d` instead of `PRIu64` --- pkg/vere/disk.c | 36 ++++++++++++++++-------------------- pkg/vere/main.c | 10 +++++----- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 2138ed4205..27c7b14f66 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -905,7 +905,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) // set path to latest epoch c3_c epo_c[8193]; - snprintf(epo_c, 8192, "%s/0i%" PRIu64, log_c, lat_d); + snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_c, lat_d); // initialize latest epoch's db if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { @@ -913,7 +913,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) c3_free(log_u); return 0; } - fprintf(stderr, "disk: loaded epoch 0i%" PRIu64 "\r\n", lat_d); + fprintf(stderr, "disk: loaded epoch 0i%" PRIc3_d "\r\n", lat_d); // get first/last event numbers from lmdb c3_d fir_d, las_d; @@ -975,7 +975,7 @@ c3_o u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { // file paths c3_c epo_c[8193], dat_c[8193], epv_c[8193], biv_c[8193]; - snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, epo_d); + snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, epo_d); snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); @@ -1014,23 +1014,23 @@ c3_o u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { // print error messages if ( c3n == dir_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIu64 " is not writable\r\n", epo_d); + fprintf(stderr, "disk: epoch 0i%" PRIc3_d " is not writable\r\n", epo_d); ret_o = c3n; } if ( c3n == dat_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIu64 "/data.mdb is not writable\r\n", epo_d); + fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/data.mdb is not writable\r\n", epo_d); ret_o = c3n; } if ( c3n == mdb_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIu64 "/data.mdb can't be opened\r\n", epo_d); + fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/data.mdb can't be opened\r\n", epo_d); ret_o = c3n; } if ( c3n == epv_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIu64 "/epoc.txt is not writable\r\n", epo_d); + fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/epoc.txt is not writable\r\n", epo_d); ret_o = c3n; } if ( c3n == biv_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIu64 "/vere.txt is not writable\r\n", epo_d); + fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/vere.txt is not writable\r\n", epo_d); ret_o = c3n; } @@ -1063,10 +1063,10 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { // create new epoch directory if it doesn't exist c3_c epo_c[8193]; - snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, new_d); + snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, new_d); c3_d ret_d = c3_mkdir(epo_c, 0700); if ( ( ret_d < 0 ) && ( errno != EEXIST ) ) { - fprintf(stderr, "disk: failed to create epoch directory %" PRIu64 "\r\n", new_d); + fprintf(stderr, "disk: failed to create epoch directory %" PRIc3_d "\r\n", new_d); return c3n; } @@ -1107,10 +1107,6 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { if ( c3y == u3_Host.ops_u.nuu || new_d > 0 ) { c3_c dat_c[8193]; snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); - // if ( c3n == c3_unlink(dat_c) ) { - // fprintf(stderr, "disk: failed to rm 0i%" PRIu64 "/data.mdb\r\n", new_d); - // goto fail; - // }; if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); @@ -1144,7 +1140,7 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { c3_o u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { // get epoch directory c3_c epo_c[8193]; - snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIu64, log_u->com_u->pax_c, epo_d); + snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, epo_d); // delete files in epoch directory u3_dire* dir_u = u3_foil_folder(epo_c); @@ -1177,7 +1173,7 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { u3_dent* den_u = u3_foil_folder(log_u->com_u->pax_c)->dil_u; while ( den_u ) { c3_d epo_d = 0; - if ( 1 == sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d) ) { + if ( 1 == sscanf(den_u->nam_c, "0i%" PRIc3_d, &epo_d) ) { ret_d = c3y; // NB: returns yes if the directory merely exists } *lat_d = c3_max(epo_d, *lat_d); // update the latest epoch number @@ -1192,18 +1188,18 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { c3_o u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) { c3_c ver_c[8193]; - snprintf(ver_c, sizeof(ver_c), "%s/0i%" PRIu64 "/vere.txt", + snprintf(ver_c, sizeof(ver_c), "%s/0i%" PRIc3_d "/vere.txt", log_u->com_u->pax_c, epo_d); FILE* fil_u = fopen(ver_c, "r"); if ( NULL == fil_u ) { - fprintf(stderr, "disk: failed to open vere.txt in epoch 0i%" PRIu64 + fprintf(stderr, "disk: failed to open vere.txt in epoch 0i%" PRIc3_d "\r\n", epo_d); return c3n; } if ( 1 != fscanf(fil_u, "%s", ver_w) ) { - fprintf(stderr, "disk: failed to read vere.txt in epoch 0i%" PRIu64 + fprintf(stderr, "disk: failed to read vere.txt in epoch 0i%" PRIc3_d "\r\n", epo_d); return c3n; } @@ -1283,7 +1279,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) if ( u3_Host.eve_d != las_d ) { fprintf(stderr, "disk: migrate: error: snapshot is out of date, please " "start/shutdown your pier gracefully first\r\n"); - fprintf(stderr, "disk: migrate: eve_d (%" PRIu64 ") != las_d (%" PRIu64 ")\r\n", + fprintf(stderr, "disk: migrate: eve_d (%" PRIc3_d ") != las_d (%" PRIc3_d ")\r\n", u3_Host.eve_d, las_d); return c3n; } diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 7f9d360e9a..71bd981cbb 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2140,7 +2140,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) if ( log_u->dun_d != u3A->eve_d ) { fprintf(stderr, "chop: error: snapshot is out of date, please " "start/shutdown your pier gracefully first\r\n"); - fprintf(stderr, "chop: eve_d: %" PRIu64 ", dun_d: %" PRIu64 "\r\n", u3A->eve_d, log_u->dun_d); + fprintf(stderr, "chop: eve_d: %" PRIc3_d ", dun_d: %" PRIc3_d "\r\n", u3A->eve_d, log_u->dun_d); exit(1); } @@ -2176,7 +2176,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) len_z = 0; den_u = ned_u->dil_u; while ( den_u ) { - if ( 1 == sscanf(den_u->nam_c, "0i%" PRIu64, (sot_d + len_z)) ) { + if ( 1 == sscanf(den_u->nam_c, "0i%" PRIc3_d, (sot_d + len_z)) ) { len_z++; } den_u = den_u->nex_u; @@ -2209,7 +2209,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) // delete all but the last two epochs // XX parameterize the number of epochs to chop for ( c3_z i_z = 2; i_z < len_z; i_z++ ) { - fprintf(stderr, "chop: deleting epoch 0i%" PRIu64 "\r\n", sot_d[i_z]); + fprintf(stderr, "chop: deleting epoch 0i%" PRIc3_d "\r\n", sot_d[i_z]); if ( c3y != u3_disk_epoc_kill(log_u, sot_d[i_z]) ) { fprintf(stderr, "chop: failed to delete epoch 0i%" PRIu64 "\r\n", sot_d[i_z]); exit(1); @@ -2218,7 +2218,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) c3_d epo_d = 0; while ( den_u ) { - c3_i res_i = sscanf(den_u->nam_c, "0i%" PRIu64, &epo_d); + c3_i res_i = sscanf(den_u->nam_c, "0i%" PRIc3_d, &epo_d); if ( (1 == res_i) && (epo_d < pre_d) && (epo_d < pos_d) ) { } den_u = den_u->nex_u; @@ -2293,7 +2293,7 @@ _cw_roll(c3_i argc, c3_c* argv[]) if ( log_u->dun_d != u3A->eve_d ) { fprintf(stderr, "roll: error: snapshot is out of date, please " "start/shutdown your pier gracefully first\r\n"); - fprintf(stderr, "roll: eve_d: %" PRIu64 ", dun_d: %" PRIu64 "\r\n", \ + fprintf(stderr, "roll: eve_d: %" PRIc3_d ", dun_d: %" PRIc3_d "\r\n", \ u3A->eve_d, log_u->dun_d); exit(1); } From b35b413f9aaabd71924524657d91cc03dcf70144 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 31 May 2023 15:34:17 -0400 Subject: [PATCH 19/87] disk: various epoch improvements --- pkg/noun/manage.c | 1 + pkg/vere/disk.c | 43 ++++++++++++++++++++++++++----------------- pkg/vere/main.c | 11 ++--------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 166dcdf8df..2d467c11ce 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -2054,6 +2054,7 @@ extern void u3je_secp_stop(void); void u3m_stop() { + // XX make sure to cleanup snapshot file descriptors if necessary u3je_secp_stop(); } diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 27c7b14f66..6f7ce2176f 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -896,8 +896,8 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } // get binary version from latest epoch - c3_c ver_w[8193]; - if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_w) ) { + c3_c ver_c[8193]; + if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_c) ) { fprintf(stderr, "disk: failed to load epoch version\r\n"); c3_free(log_u); return 0; @@ -936,7 +936,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) // if binary version of latest epoch is not the same as the // running binary, then we need to create a new epoch - if ( 0 != strcmp(ver_w, URBIT_VERSION) ) { + if ( 0 != strcmp(ver_c, URBIT_VERSION) ) { if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "disk: failed to initialize epoch\r\n"); c3_free(log_u); @@ -1161,6 +1161,9 @@ c3_o u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { return c3n; } + // cleanup + u3_dire_free(dir_u); + // success return c3y; } @@ -1168,25 +1171,31 @@ c3_o u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { /* u3_disk_epoc_last: get latest epoch number. */ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { - c3_o ret_d = c3n; // return no if no epoch directories exist + c3_o ret_o = c3n; // return no if no epoch directories exist *lat_d = 0; // initialize lat_d to 0 - u3_dent* den_u = u3_foil_folder(log_u->com_u->pax_c)->dil_u; + u3_dire* die_u = u3_foil_folder(log_u->com_u->pax_c); + u3_dent* den_u = die_u->dil_u; while ( den_u ) { c3_d epo_d = 0; if ( 1 == sscanf(den_u->nam_c, "0i%" PRIc3_d, &epo_d) ) { - ret_d = c3y; // NB: returns yes if the directory merely exists + ret_o = c3y; // NB: returns yes if the directory merely exists + *lat_d = c3_max(epo_d, *lat_d); // update the latest epoch number } - *lat_d = c3_max(epo_d, *lat_d); // update the latest epoch number den_u = den_u->nex_u; } + + u3_dire_free(die_u); - return ret_d; + return ret_o; } /* u3_disk_epoc_vere: get binary version from epoch. */ c3_o u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) { + // XX check implementation (similar code is in king.c, _king_get_pace) + // should probably write a generic function to read a string from + // a file into malloc'd memory, with an optional whitespace trimming c3_c ver_c[8193]; snprintf(ver_c, sizeof(ver_c), "%s/0i%" PRIc3_d "/vere.txt", log_u->com_u->pax_c, epo_d); @@ -1210,12 +1219,12 @@ u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) { */ c3_o u3_disk_migrate(u3_disk* log_u) { - /* migration steps: + /* migration steps (* indicates breakpoint set): * 0. detect whether we need to migrate or not - * a. if it's a fresh boot via u3_Host.ops_u.nuu -> skip migration - * b. if data.mdb is readable in log directory -> execute migration - * if not -> skip migration - * 1. initialize epoch 0i0 (first call to u3_disk_epoc_init()) + * a. if it's a fresh boot via u3_Host.ops_u.nuu -> skip migration (returns yes) + * b. if data.mdb is readable in log directory -> execute migration (returns yes or no) + * if not -> skip migration (returns yes) + * 1. initialize epoch 0i0 (first call to u3_disk_epoc_init()) * * a. creates epoch directory * b. creates epoch version file * c. creates binary version file @@ -1224,10 +1233,10 @@ c3_o u3_disk_migrate(u3_disk* log_u) * f. writes metadata to new database * g. loads new epoch directory and sets it in log_u * 2. create hard links to data.mdb and lock.mdb in 0i0/ - * 3. rollover to new epoch (second call to u3_disk_epoc_init()) + * 3. rollover to new epoch (second call to u3_disk_epoc_init()) * * a. same as 1a-g but also copies current snapshot between c/d steps - * 4. delete backup snapshot (c3_unlink() and c3_rmdir() calls) - * 5. delete old data.mdb and lock.mdb files (c3_unlink() calls) + * 4. delete backup snapshot (c3_unlink() and c3_rmdir() calls) * + * 5. delete old data.mdb and lock.mdb files (c3_unlink() calls) * */ // check if data.mdb is readable in log directory @@ -1252,7 +1261,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) // initialize first epoch "0i0" if ( c3n == u3_disk_epoc_init(log_u) ) { - fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); + fprintf(stderr, "disk: failed to initialize first epoch\r\n"); return c3n; } } else if ( c3y == dat_o ) { diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 71bd981cbb..79a1a0fe92 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2216,14 +2216,6 @@ _cw_chop(c3_i argc, c3_c* argv[]) } } - c3_d epo_d = 0; - while ( den_u ) { - c3_i res_i = sscanf(den_u->nam_c, "0i%" PRIc3_d, &epo_d); - if ( (1 == res_i) && (epo_d < pre_d) && (epo_d < pos_d) ) { - } - den_u = den_u->nex_u; - } - // cleanup u3_dire_free(ned_u); u3_disk_exit(log_u); @@ -2769,7 +2761,8 @@ main(c3_i argc, // validate whether we can execute disk migration if ( u3_Host.ops_u.nuu == c3n ) { u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); - // XX u3e_close() + u3m_stop(); + // XX unmap loom, else parts of the snapshot could be left in memory } // starting u3m configures OpenSSL memory functions, so we must do it From ba1a3af7f1f7ee122e7cdb56382975730b701b32 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 31 May 2023 18:01:43 -0400 Subject: [PATCH 20/87] disk: function style fixes --- pkg/vere/disk.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 6f7ce2176f..9a5f8dfacc 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -958,7 +958,8 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) /* u3_disk_epoc_good: check for valid epoch. */ -c3_o u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { +c3_o +u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { /* a "valid" epoch is currently defined as a writable folder in * the /.urb/log directory named with a @ui and contains: * - a writable data.mdb file which can be opened by lmdb (add db checking?) @@ -1039,7 +1040,8 @@ c3_o u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { /* u3_disk_epoc_init: create new epoch. */ -c3_o u3_disk_epoc_init(u3_disk* log_u) { +c3_o +u3_disk_epoc_init(u3_disk* log_u) { // set new epoch number c3_d lat_d, new_d; c3_o eps_o = u3_disk_epoc_last(log_u, &lat_d); @@ -1137,7 +1139,8 @@ c3_o u3_disk_epoc_init(u3_disk* log_u) { /* u3_disk_epoc_kill: delete an epoch. */ -c3_o u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { +c3_o +u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { // get epoch directory c3_c epo_c[8193]; snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, epo_d); @@ -1170,7 +1173,8 @@ c3_o u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { /* u3_disk_epoc_last: get latest epoch number. */ -c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { +c3_o +u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { c3_o ret_o = c3n; // return no if no epoch directories exist *lat_d = 0; // initialize lat_d to 0 u3_dire* die_u = u3_foil_folder(log_u->com_u->pax_c); @@ -1358,4 +1362,4 @@ c3_o u3_disk_migrate(u3_disk* log_u) } return c3y; -} \ No newline at end of file +} From 9b45ad20ec0d0f94437b6afe2ec8eec387459687 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 1 Jun 2023 09:14:16 -0400 Subject: [PATCH 21/87] u3: remove snapshot backup in `u3e_save` and unused `u3m_backup` --- pkg/noun/events.c | 4 ---- pkg/noun/manage.c | 10 ---------- 2 files changed, 14 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 5e16182307..287ac92d82 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1379,10 +1379,6 @@ u3e_save(u3_post low_p, u3_post hig_p) pgs_w, ptr_v, strerror(errno)); } } - - c3_c bhk_c[8193]; - snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3P.dir_c); - u3e_backup(bhk_c, c3n); } /* u3e_live(): start the checkpointing system. diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 2d467c11ce..ee93ed5568 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -1748,16 +1748,6 @@ _cm_limits(void) # endif } -/* u3m_backup(): copy snapshot to .urb/bhk (if it doesn't exist yet). -*/ -c3_o -u3m_backup(c3_o ovw_o) -{ - c3_c bhk_c[2048]; - snprintf(bhk_c, 2048, "%s/.urb/bhk", u3P.dir_c); - return u3e_backup(bhk_c, ovw_o); -} - /* u3m_fault(): handle a memory event with libsigsegv protocol. */ c3_i From fb762b2fb24846a8a4e50d852c4ca18149df3c9c Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 1 Jun 2023 09:40:45 -0400 Subject: [PATCH 22/87] disk: add event check to `u3_disk_epoc_good` --- pkg/vere/disk.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 9a5f8dfacc..70661b6634 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -983,6 +983,7 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { c3_o dir_o = c3n; // directory is writable c3_o dat_o = c3n; // data.mdb is writable + c3_o len_o = c3n; // data.mdb has events c3_o mdb_o = c3n; // data.mdb can be opened c3_o epv_o = c3n; // epoc.txt is writable c3_o biv_o = c3n; // vere.txt is writable @@ -1000,6 +1001,17 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { if ( 0 != (env_u = u3_lmdb_init(epo_c)) ) { mdb_o = c3y; } + + // check if there are any events in the database + c3_d low_d, hig_d; + if ( 0 != u3_lmdb_gulf(env_u, &low_d, &hig_d) ) { + fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); + ret_o = c3n; + } else { + if ( low_d == hig_d == 0 ) { + len_o = c3y; // yes, data.mdb has events + } + } u3_lmdb_exit(env_u); } @@ -1026,6 +1038,10 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/data.mdb can't be opened\r\n", epo_d); ret_o = c3n; } + if ( c3n == len_o ) { + fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/data.mdb has no events\r\n", epo_d); + ret_o = c3n; + } if ( c3n == epv_o ) { fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/epoc.txt is not writable\r\n", epo_d); ret_o = c3n; From 83b57376bcfc4a54d9959ebc5e027b68d268daf1 Mon Sep 17 00:00:00 2001 From: barter-simsum Date: Thu, 1 Jun 2023 10:18:14 -0400 Subject: [PATCH 23/87] cleanup whitespace --- pkg/noun/events.c | 2 +- pkg/vere/disk.c | 22 +++++++++++----------- pkg/vere/main.c | 4 ++-- pkg/vere/vere.h | 10 +++++----- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 287ac92d82..89013cecd9 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1220,7 +1220,7 @@ u3e_backup(c3_c* pax_c, c3_o ovw_o) { u3e_image nop_u = { .nam_c = "north", .pgs_w = 0 }; u3e_image sop_u = { .nam_c = "south", .pgs_w = 0 }; - + c3_i mod_i = O_RDWR | O_CREAT; if ( !pax_c ) { diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 70661b6634..6e18eebef9 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -929,8 +929,8 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } else { // not first epoch log_u->dun_d = lat_d; // set dun_d to last event in prev epoch } - } else { // not fresh epoch - log_u->dun_d = las_d; // set dun_d to last event in lmdb + } else { // not fresh epoch + log_u->dun_d = las_d; // set dun_d to last event in lmdb } log_u->sen_d = log_u->dun_d; @@ -960,7 +960,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) */ c3_o u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { - /* a "valid" epoch is currently defined as a writable folder in + /* a "valid" epoch is currently defined as a writable folder in * the /.urb/log directory named with a @ui and contains: * - a writable data.mdb file which can be opened by lmdb (add db checking?) * - a writable epoc.txt file @@ -968,7 +968,7 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { * * XX: should we check if the correct event sequence exists in the data.mdb file? * - * note that this does not check if the epoch even contains snapshot files, + * note that this does not check if the epoch even contains snapshot files, * let alone whether they're valid or not */ @@ -1053,7 +1053,7 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { return ret_o; } - + /* u3_disk_epoc_init: create new epoch. */ c3_o @@ -1203,7 +1203,7 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { } den_u = den_u->nex_u; } - + u3_dire_free(die_u); return ret_o; @@ -1214,21 +1214,21 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { c3_o u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) { // XX check implementation (similar code is in king.c, _king_get_pace) - // should probably write a generic function to read a string from + // should probably write a generic function to read a string from // a file into malloc'd memory, with an optional whitespace trimming c3_c ver_c[8193]; - snprintf(ver_c, sizeof(ver_c), "%s/0i%" PRIc3_d "/vere.txt", + snprintf(ver_c, sizeof(ver_c), "%s/0i%" PRIc3_d "/vere.txt", log_u->com_u->pax_c, epo_d); FILE* fil_u = fopen(ver_c, "r"); if ( NULL == fil_u ) { - fprintf(stderr, "disk: failed to open vere.txt in epoch 0i%" PRIc3_d + fprintf(stderr, "disk: failed to open vere.txt in epoch 0i%" PRIc3_d "\r\n", epo_d); return c3n; } if ( 1 != fscanf(fil_u, "%s", ver_w) ) { - fprintf(stderr, "disk: failed to read vere.txt in epoch 0i%" PRIc3_d + fprintf(stderr, "disk: failed to read vere.txt in epoch 0i%" PRIc3_d "\r\n", epo_d); return c3n; } @@ -1286,7 +1286,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) } } else if ( c3y == dat_o ) { // migrate existing pier which has either: - // - not started the migration, or + // - not started the migration, or // - crashed before completing the migration // initialize pre-migrated lmdb diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 79a1a0fe92..cacb37d285 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -317,7 +317,7 @@ _main_getopt(c3_i argc, c3_c** argv) return c3n; } else { u3_Host.ops_u.sap_w = arg_w * 60; - if ( 0 == u3_Host.ops_u.sap_w) + if ( 0 == u3_Host.ops_u.sap_w) return c3n; } break; @@ -2757,7 +2757,7 @@ main(c3_i argc, } } - // we need the current snapshot's latest event number to + // we need the current snapshot's latest event number to // validate whether we can execute disk migration if ( u3_Host.ops_u.nuu == c3n ) { u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index fbb28c1ef7..f3e47a98b6 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -988,27 +988,27 @@ */ c3_o u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d); - + /* u3_disk_epoc_init(): create new epoch. */ c3_o u3_disk_epoc_init(u3_disk* log_u); - + /* u3_disk_epoc_kill(): delete an epoch. */ c3_o u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d); - + /* u3_disk_epoc_last(): get latest epoch number. */ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d); - + /* u3_disk_epoc_vere(): get binary version from epoch. */ c3_o u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w); - + /* u3_disk_migrate(): migrates disk format. */ c3_o From 6dc1bd6e0a8537e2ba6c3eedf97ee68b85139fc4 Mon Sep 17 00:00:00 2001 From: barter-simsum Date: Thu, 1 Jun 2023 11:21:45 -0400 Subject: [PATCH 24/87] data.mdb -> lock.mdb --- pkg/vere/disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 6e18eebef9..56383a76b2 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1270,7 +1270,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) // check if lock.mdb is readable in log directory c3_o lok_o = c3n; c3_c lok_c[8193]; - snprintf(lok_c, sizeof(dat_c), "%s/data.mdb", log_u->com_u->pax_c); + snprintf(lok_c, sizeof(dat_c), "%s/lock.mdb", log_u->com_u->pax_c); if ( 0 == access(dat_c, R_OK) ) { lok_o = c3y; } From a0d239bb0d85f8084d96bb10092c6910b8ae873d Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 1 Jun 2023 14:09:17 -0400 Subject: [PATCH 25/87] disk: add event check in `u3_disk_epoc_good` --- pkg/vere/disk.c | 178 +++++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 85 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 56383a76b2..f0807bbedf 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -959,15 +959,14 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) /* u3_disk_epoc_good: check for valid epoch. */ c3_o -u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { +u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) +{ /* a "valid" epoch is currently defined as a writable folder in * the /.urb/log directory named with a @ui and contains: - * - a writable data.mdb file which can be opened by lmdb (add db checking?) + * - a writable data.mdb file which can be opened by lmdb and contains 1+ events * - a writable epoc.txt file * - a writable vere.txt file * - * XX: should we check if the correct event sequence exists in the data.mdb file? - * * note that this does not check if the epoch even contains snapshot files, * let alone whether they're valid or not */ @@ -1057,7 +1056,8 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { /* u3_disk_epoc_init: create new epoch. */ c3_o -u3_disk_epoc_init(u3_disk* log_u) { +u3_disk_epoc_init(u3_disk* log_u) +{ // set new epoch number c3_d lat_d, new_d; c3_o eps_o = u3_disk_epoc_last(log_u, &lat_d); @@ -1156,7 +1156,8 @@ u3_disk_epoc_init(u3_disk* log_u) { /* u3_disk_epoc_kill: delete an epoch. */ c3_o -u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { +u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) +{ // get epoch directory c3_c epo_c[8193]; snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, epo_d); @@ -1190,7 +1191,8 @@ u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) { /* u3_disk_epoc_last: get latest epoch number. */ c3_o -u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { +u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) +{ c3_o ret_o = c3n; // return no if no epoch directories exist *lat_d = 0; // initialize lat_d to 0 u3_dire* die_u = u3_foil_folder(log_u->com_u->pax_c); @@ -1212,7 +1214,8 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { /* u3_disk_epoc_vere: get binary version from epoch. */ c3_o -u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) { +u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) +{ // XX check implementation (similar code is in king.c, _king_get_pace) // should probably write a generic function to read a string from // a file into malloc'd memory, with an optional whitespace trimming @@ -1275,8 +1278,8 @@ c3_o u3_disk_migrate(u3_disk* log_u) lok_o = c3y; } + // if fresh boot, initialize disk v1 if ( c3y == u3_Host.ops_u.nuu ) { - // initialize disk v1 on fresh boots fprintf(stderr, "disk: initializing disk with v%d format\r\n", U3D_VER1); // initialize first epoch "0i0" @@ -1284,98 +1287,103 @@ c3_o u3_disk_migrate(u3_disk* log_u) fprintf(stderr, "disk: failed to initialize first epoch\r\n"); return c3n; } - } else if ( c3y == dat_o ) { - // migrate existing pier which has either: - // - not started the migration, or - // - crashed before completing the migration - - // initialize pre-migrated lmdb - { - if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_u->com_u->pax_c)) ) { - fprintf(stderr, "disk: failed to initialize database\r\n"); - return c3n; - } - } - // get first/last event numbers from pre-migrated lmdb - c3_d fir_d, las_d; - if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { - fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); - return c3n; - } + return c3y; + } + + // if data.mdb is not readable, skip migration + if ( c3n == dat_o ) return c3y; - // ensure there's a current snapshot - if ( u3_Host.eve_d != las_d ) { - fprintf(stderr, "disk: migrate: error: snapshot is out of date, please " - "start/shutdown your pier gracefully first\r\n"); - fprintf(stderr, "disk: migrate: eve_d (%" PRIc3_d ") != las_d (%" PRIc3_d ")\r\n", - u3_Host.eve_d, las_d); - return c3n; - } + // migrate existing pier which has either: + // - not started the migration, or + // - crashed before completing the migration - // initialize first epoch "0i0" - if ( c3n == u3_disk_epoc_init(log_u) ) { - fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); + // initialize pre-migrated lmdb + { + if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_u->com_u->pax_c)) ) { + fprintf(stderr, "disk: failed to initialize database\r\n"); return c3n; } + } - // create hard links to data.mdb and lock.mdb in 0i0/ - c3_c dut_c[8193], luk_c[8193]; // old paths - snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); - snprintf(luk_c, sizeof(luk_c), "%s/lock.mdb", log_u->com_u->pax_c); + // get first/last event numbers from pre-migrated lmdb + c3_d fir_d, las_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { + fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); + return c3n; + } - c3_c epo_c[8193], dat_c[8193], lok_c[8193]; // new paths - snprintf(epo_c, sizeof(epo_c), "%s/0i0", log_u->com_u->pax_c); - snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); - snprintf(lok_c, sizeof(lok_c), "%s/lock.mdb", epo_c); + // ensure there's a current snapshot + if ( u3_Host.eve_d != las_d ) { + fprintf(stderr, "disk: migrate: error: snapshot is out of date, please " + "start/shutdown your pier gracefully first\r\n"); + fprintf(stderr, "disk: migrate: eve_d (%" PRIc3_d ") != las_d (%" PRIc3_d ")\r\n", + u3_Host.eve_d, las_d); + return c3n; + } - if ( 0 < c3_link(dut_c, dat_c) ) { - fprintf(stderr, "disk: migrate: failed to create data.mdb hard link\r\n"); - fprintf(stderr, "errno %d: %s\r\n", errno, strerror(errno)); - return c3n; - } - if ( c3y == lok_o ) { // only link lock.mdb if it exists - if ( 0 < c3_link(luk_c, lok_c) ) { - fprintf(stderr, "disk: migrate: failed to create lock.mdb hard link\r\n"); - c3_rename(dat_c, dut_c); - return c3n; - } - } + // initialize first epoch "0i0" + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); + return c3n; + } - // rollover to new epoch - // log_u->mdb_u = old_u; - if ( c3n == u3_disk_epoc_init(log_u) ) { - fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); + // create hard links to data.mdb and lock.mdb in 0i0/ + c3_c dut_c[8193], luk_c[8193]; // old paths + snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); + snprintf(luk_c, sizeof(luk_c), "%s/lock.mdb", log_u->com_u->pax_c); + + c3_c epo_c[8193]; + snprintf(epo_c, sizeof(epo_c), "%s/0i0", log_u->com_u->pax_c); + snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); + snprintf(lok_c, sizeof(lok_c), "%s/lock.mdb", epo_c); + + if ( 0 < c3_link(dut_c, dat_c) ) { + fprintf(stderr, "disk: migrate: failed to create data.mdb hard link\r\n"); + fprintf(stderr, "errno %d: %s\r\n", errno, strerror(errno)); + return c3n; + } + if ( c3y == lok_o ) { // only link lock.mdb if it exists + if ( 0 < c3_link(luk_c, lok_c) ) { + fprintf(stderr, "disk: migrate: failed to create lock.mdb hard link\r\n"); + c3_rename(dat_c, dut_c); return c3n; } + } - // delete backup snapshot - c3_c bhk_c[8193], nop_c[8193], sop_c[8193]; - snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3_Host.dir_c); - snprintf(nop_c, sizeof(nop_c), "%s/north.bin", bhk_c); - snprintf(sop_c, sizeof(sop_c), "%s/south.bin", bhk_c); - if ( c3n == c3_unlink(nop_c) ) { - fprintf(stderr, "disk: migrate: failed to delete bhk/north.bin\r\n"); - } else if ( c3n == c3_unlink(sop_c) ) { - fprintf(stderr, "disk: migrate: failed to delete bhk/south.bin\r\n"); - } else { - if ( c3n == c3_rmdir(bhk_c) ) { - fprintf(stderr, "disk: migrate: failed to delete bhk/\r\n"); - } - } + // rollover to new epoch + // log_u->mdb_u = old_u; + if ( c3n == u3_disk_epoc_init(log_u) ) { + fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); + return c3n; + } - // delete old lock.mdb and data.mdb files - if ( 0 != c3_unlink(luk_c) ) { - fprintf(stderr, "disk: migrate: failed to unlink lock.mdb\r\n"); - } - if ( 0 != c3_unlink(dut_c) ) { - fprintf(stderr, "disk: migrate: failed to unlink data.mdb\r\n"); - return c3n; // migration succeeds only if we can unlink data.mdb + // delete backup snapshot + c3_c bhk_c[8193], nop_c[8193], sop_c[8193]; + snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3_Host.dir_c); + snprintf(nop_c, sizeof(nop_c), "%s/north.bin", bhk_c); + snprintf(sop_c, sizeof(sop_c), "%s/south.bin", bhk_c); + if ( c3n == c3_unlink(nop_c) ) { + fprintf(stderr, "disk: migrate: failed to delete bhk/north.bin\r\n"); + } else if ( c3n == c3_unlink(sop_c) ) { + fprintf(stderr, "disk: migrate: failed to delete bhk/south.bin\r\n"); + } else { + if ( c3n == c3_rmdir(bhk_c) ) { + fprintf(stderr, "disk: migrate: failed to delete bhk/\r\n"); } + } - // success - fprintf(stderr, "disk: migrated disk to v%d format\r\n", U3D_VER1); + // delete old lock.mdb and data.mdb files + if ( 0 != c3_unlink(luk_c) ) { + fprintf(stderr, "disk: migrate: failed to unlink lock.mdb\r\n"); } + if ( 0 != c3_unlink(dut_c) ) { + fprintf(stderr, "disk: migrate: failed to unlink data.mdb\r\n"); + return c3n; // migration succeeds only if we can unlink data.mdb + } + + // success + fprintf(stderr, "disk: migrated disk to v%d format\r\n", U3D_VER1); return c3y; } From d6fcb9875f800c8583241736a972f41ef580ef56 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 2 Jun 2023 10:36:17 -0400 Subject: [PATCH 26/87] disk: fix duplicate code --- pkg/vere/disk.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index f0807bbedf..5046a3a1c6 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1263,19 +1263,19 @@ c3_o u3_disk_migrate(u3_disk* log_u) */ // check if data.mdb is readable in log directory - c3_o dat_o = c3n; - c3_c dat_c[8193]; - snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", log_u->com_u->pax_c); - if ( 0 == access(dat_c, R_OK) ) { - dat_o = c3y; + c3_o dut_o = c3n; + c3_c dut_c[8193]; + snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); + if ( 0 == access(dut_c, R_OK) ) { + dut_o = c3y; } // check if lock.mdb is readable in log directory - c3_o lok_o = c3n; - c3_c lok_c[8193]; - snprintf(lok_c, sizeof(dat_c), "%s/lock.mdb", log_u->com_u->pax_c); - if ( 0 == access(dat_c, R_OK) ) { - lok_o = c3y; + c3_o luk_o = c3n; + c3_c luk_c[8193]; + snprintf(luk_c, sizeof(luk_c), "%s/lock.mdb", log_u->com_u->pax_c); + if ( 0 == access(luk_c, R_OK) ) { + luk_o = c3y; } // if fresh boot, initialize disk v1 @@ -1291,8 +1291,8 @@ c3_o u3_disk_migrate(u3_disk* log_u) return c3y; } - // if data.mdb is not readable, skip migration - if ( c3n == dat_o ) return c3y; + // if .urb/log/data.mdb is not readable, skip migration + if ( c3n == dut_o ) return c3y; // migrate existing pier which has either: // - not started the migration, or @@ -1329,11 +1329,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) } // create hard links to data.mdb and lock.mdb in 0i0/ - c3_c dut_c[8193], luk_c[8193]; // old paths - snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); - snprintf(luk_c, sizeof(luk_c), "%s/lock.mdb", log_u->com_u->pax_c); - - c3_c epo_c[8193]; + c3_c epo_c[8193], dat_c[8193], lok_c[8193]; snprintf(epo_c, sizeof(epo_c), "%s/0i0", log_u->com_u->pax_c); snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); snprintf(lok_c, sizeof(lok_c), "%s/lock.mdb", epo_c); @@ -1343,7 +1339,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) fprintf(stderr, "errno %d: %s\r\n", errno, strerror(errno)); return c3n; } - if ( c3y == lok_o ) { // only link lock.mdb if it exists + if ( c3y == luk_o ) { // only link lock.mdb if it exists if ( 0 < c3_link(luk_c, lok_c) ) { fprintf(stderr, "disk: migrate: failed to create lock.mdb hard link\r\n"); c3_rename(dat_c, dut_c); From 1886844f4abbd4aac66cc91ec80c661d256c1817 Mon Sep 17 00:00:00 2001 From: barter-simsum Date: Fri, 2 Jun 2023 10:48:33 -0400 Subject: [PATCH 27/87] remove redundant dut_o in u3_disk_migrate --- pkg/vere/disk.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 5046a3a1c6..81eb3a600d 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1263,11 +1263,12 @@ c3_o u3_disk_migrate(u3_disk* log_u) */ // check if data.mdb is readable in log directory - c3_o dut_o = c3n; c3_c dut_c[8193]; snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); - if ( 0 == access(dut_c, R_OK) ) { - dut_o = c3y; + if ( !_(u3_Host.ops_u.nuu) + && 0 != access(dut_c, R_OK) ) { + // if .urb/log/data.mdb is not readable, skip migration + return c3y; } // check if lock.mdb is readable in log directory @@ -1290,9 +1291,6 @@ c3_o u3_disk_migrate(u3_disk* log_u) return c3y; } - - // if .urb/log/data.mdb is not readable, skip migration - if ( c3n == dut_o ) return c3y; // migrate existing pier which has either: // - not started the migration, or From d59b0af5497add0f3c36a72d4deb86d138e0453a Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 5 Jun 2023 11:05:40 -0400 Subject: [PATCH 28/87] disk: make `u3_disk_epoc_vere` safer --- pkg/vere/disk.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 81eb3a600d..eb1b25792c 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1216,25 +1216,38 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) c3_o u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) { - // XX check implementation (similar code is in king.c, _king_get_pace) - // should probably write a generic function to read a string from - // a file into malloc'd memory, with an optional whitespace trimming - c3_c ver_c[8193]; - snprintf(ver_c, sizeof(ver_c), "%s/0i%" PRIc3_d "/vere.txt", - log_u->com_u->pax_c, epo_d); - - FILE* fil_u = fopen(ver_c, "r"); - if ( NULL == fil_u ) { + struct stat buf_u; + c3_c* ver_c; + c3_w red_w, len_w; + c3_i ret_i, fid_i; + ret_i = asprintf(&ver_c, "%s/0i%" PRIc3_d "/vere.txt", + log_u->com_u->pax_c, epo_d); + u3_assert( ret_i > 0 ); + + fid_i = c3_open(ver_c, O_RDONLY, 0644); + + if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) { fprintf(stderr, "disk: failed to open vere.txt in epoch 0i%" PRIc3_d "\r\n", epo_d); return c3n; } - if ( 1 != fscanf(fil_u, "%s", ver_w) ) { + len_w = buf_u.st_size; + red_w = read(fid_i, ver_w, len_w); + close(fid_i); + + if ( len_w != red_w ) { fprintf(stderr, "disk: failed to read vere.txt in epoch 0i%" PRIc3_d "\r\n", epo_d); return c3n; } + + // trim trailing whitespace + ver_w[len_w] = 0; + while ( len_w-- && isspace(ver_w[len_w]) ) { + ver_w[len_w] = 0; + } + return c3y; } From c50906de6e69cf11a94ed9df245b51371783858b Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 5 Jun 2023 11:29:17 -0400 Subject: [PATCH 29/87] disk: cleanup `#include` directives --- pkg/noun/noun.h | 1 - pkg/noun/urth.c | 1 - pkg/vere/disk.c | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/noun/noun.h b/pkg/noun/noun.h index b493307288..965330a519 100644 --- a/pkg/noun/noun.h +++ b/pkg/noun/noun.h @@ -15,7 +15,6 @@ #include "types.h" #include "vortex.h" #include "zave.h" -#include "events.h" #include "imprison.h" #include "log.h" #include "nock.h" diff --git a/pkg/noun/urth.c b/pkg/noun/urth.c index a4a52e2522..05ca4db33c 100644 --- a/pkg/noun/urth.c +++ b/pkg/noun/urth.c @@ -8,7 +8,6 @@ #include #include "allocate.h" -#include "events.h" #include "hashtable.h" #include "imprison.h" #include "jets.h" diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index eb1b25792c..23be66ba4b 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1,6 +1,7 @@ /// @file #include "noun.h" +#include "events.h" #include "vere.h" #include "version.h" #include "db/lmdb.h" From 611856662e9624bbe3f0a4f3466af209d44c87fc Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 5 Jun 2023 11:34:53 -0400 Subject: [PATCH 30/87] lmdb: restore `siz_i` parameter in `u3_lmdb_init` --- pkg/vere/db/lmdb.c | 11 +---------- pkg/vere/db/lmdb.h | 2 +- pkg/vere/disk.c | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/pkg/vere/db/lmdb.c b/pkg/vere/db/lmdb.c index d9fed4c0de..8f8864b77f 100644 --- a/pkg/vere/db/lmdb.c +++ b/pkg/vere/db/lmdb.c @@ -38,20 +38,11 @@ intmax_t mdb_get_filesize(mdb_filehandle_t han_u); /* u3_lmdb_init(): open lmdb at [pax_c], mmap up to [siz_i]. */ MDB_env* -u3_lmdb_init(const c3_c* pax_c) +u3_lmdb_init(const c3_c* pax_c, size_t siz_i) { MDB_env* env_u; c3_w ret_w; - // calculate db size based on architecture - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif - if ( (ret_w = mdb_env_create(&env_u)) ) { mdb_logerror(stderr, ret_w, "lmdb: init fail"); return 0; diff --git a/pkg/vere/db/lmdb.h b/pkg/vere/db/lmdb.h index 7aa996001f..aab4e6c9f7 100644 --- a/pkg/vere/db/lmdb.h +++ b/pkg/vere/db/lmdb.h @@ -22,7 +22,7 @@ /* u3_lmdb_init(): open lmdb at [pax_c], mmap up to [siz_i]. */ MDB_env* - u3_lmdb_init(const c3_c* pax_c); + u3_lmdb_init(const c3_c* pax_c, size_t siz_i); /* u3_lmdb_exit(): close lmdb. */ diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 23be66ba4b..d34c5b852a 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -909,7 +909,14 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_c, lat_d); // initialize latest epoch's db - if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { + const size_t siz_i = + // 500 GiB is as large as musl on aarch64 wants to allow + #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) + 0x7d00000000; + #else + 0x10000000000; + #endif + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); return 0; @@ -998,7 +1005,14 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) dat_o = c3y; // check if we can open data.mdb MDB_env* env_u; - if ( 0 != (env_u = u3_lmdb_init(epo_c)) ) { + const size_t siz_i = + // 500 GiB is as large as musl on aarch64 wants to allow + #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) + 0x7d00000000; + #else + 0x10000000000; + #endif + if ( 0 != (env_u = u3_lmdb_init(epo_c, siz_i)) ) { mdb_o = c3y; } @@ -1126,7 +1140,14 @@ u3_disk_epoc_init(u3_disk* log_u) if ( c3y == u3_Host.ops_u.nuu || new_d > 0 ) { c3_c dat_c[8193]; snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); - if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c)) ) { + const size_t siz_i = + // 500 GiB is as large as musl on aarch64 wants to allow + #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) + 0x7d00000000; + #else + 0x10000000000; + #endif + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); goto fail; @@ -1312,7 +1333,14 @@ c3_o u3_disk_migrate(u3_disk* log_u) // initialize pre-migrated lmdb { - if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_u->com_u->pax_c)) ) { + const size_t siz_i = + // 500 GiB is as large as musl on aarch64 wants to allow + #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) + 0x7d00000000; + #else + 0x10000000000; + #endif + if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_u->com_u->pax_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); return c3n; } From d5aff59e419ff5f4674eb7c6471dc5d2d2924218 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 6 Jun 2023 14:29:37 -0400 Subject: [PATCH 31/87] disk: define `siz_i` as a global, static constant --- pkg/vere/disk.c | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index d34c5b852a..7ad6420a6c 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -24,6 +24,15 @@ struct _cd_save { struct _u3_disk* log_u; }; +// for u3_lmdb_init() calls +static const size_t siz_i = +#if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) + // 500 GiB is as large as musl on aarch64 wants to allow + 0x7d00000000; +#else + 0x10000000000; +#endif + #undef VERBOSE_DISK #undef DISK_TRACE_JAM #undef DISK_TRACE_CUE @@ -909,13 +918,6 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_c, lat_d); // initialize latest epoch's db - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); @@ -1005,13 +1007,6 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) dat_o = c3y; // check if we can open data.mdb MDB_env* env_u; - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif if ( 0 != (env_u = u3_lmdb_init(epo_c, siz_i)) ) { mdb_o = c3y; } @@ -1140,13 +1135,6 @@ u3_disk_epoc_init(u3_disk* log_u) if ( c3y == u3_Host.ops_u.nuu || new_d > 0 ) { c3_c dat_c[8193]; snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); @@ -1333,13 +1321,6 @@ c3_o u3_disk_migrate(u3_disk* log_u) // initialize pre-migrated lmdb { - const size_t siz_i = - // 500 GiB is as large as musl on aarch64 wants to allow - #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) - 0x7d00000000; - #else - 0x10000000000; - #endif if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_u->com_u->pax_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); return c3n; @@ -1382,13 +1363,11 @@ c3_o u3_disk_migrate(u3_disk* log_u) if ( c3y == luk_o ) { // only link lock.mdb if it exists if ( 0 < c3_link(luk_c, lok_c) ) { fprintf(stderr, "disk: migrate: failed to create lock.mdb hard link\r\n"); - c3_rename(dat_c, dut_c); return c3n; } } // rollover to new epoch - // log_u->mdb_u = old_u; if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); return c3n; From cc2557cd8e11018d38d319afebdf6c8df0fed8f9 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 9 Jun 2023 16:09:34 -0400 Subject: [PATCH 32/87] disk: pare down `u3_disk_epoc_good` --- pkg/vere/disk.c | 104 +++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 77 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 7ad6420a6c..9459fecedc 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -5,6 +5,7 @@ #include "vere.h" #include "version.h" #include "db/lmdb.h" +#include struct _cd_read { uv_timer_t tim_u; @@ -905,14 +906,6 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } - // get binary version from latest epoch - c3_c ver_c[8193]; - if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_c) ) { - fprintf(stderr, "disk: failed to load epoch version\r\n"); - c3_free(log_u); - return 0; - } - // set path to latest epoch c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_c, lat_d); @@ -946,6 +939,12 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) // if binary version of latest epoch is not the same as the // running binary, then we need to create a new epoch + c3_c ver_c[8193]; + if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_c) ) { + fprintf(stderr, "disk: failed to load epoch version\r\n"); + c3_free(log_u); + return 0; + } if ( 0 != strcmp(ver_c, URBIT_VERSION) ) { if ( c3n == u3_disk_epoc_init(log_u) ) { fprintf(stderr, "disk: failed to initialize epoch\r\n"); @@ -971,14 +970,10 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) c3_o u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) { - /* a "valid" epoch is currently defined as a writable folder in - * the /.urb/log directory named with a @ui and contains: - * - a writable data.mdb file which can be opened by lmdb and contains 1+ events - * - a writable epoc.txt file - * - a writable vere.txt file - * - * note that this does not check if the epoch even contains snapshot files, - * let alone whether they're valid or not + /* this function is used to check whether or not we can overwrite + * an epoch. if the epoch contains an openable data.mdb file that + * also contains events, then we consider it good and *cannot* + * overwrite it. if not, then we consider it bad and *can* overwrite it. */ c3_o ret_o = c3y; // return code @@ -987,78 +982,33 @@ u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) c3_c epo_c[8193], dat_c[8193], epv_c[8193], biv_c[8193]; snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, epo_d); snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); - snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); - snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); - c3_o dir_o = c3n; // directory is writable - c3_o dat_o = c3n; // data.mdb is writable - c3_o len_o = c3n; // data.mdb has events - c3_o mdb_o = c3n; // data.mdb can be opened - c3_o epv_o = c3n; // epoc.txt is writable - c3_o biv_o = c3n; // vere.txt is writable - - // check if dir is writable - if ( 0 == access(epo_c, W_OK) ) { - dir_o = c3y; - } - - // check if data.mdb is writable - if ( 0 == access(dat_c, W_OK) ) { - dat_o = c3y; - // check if we can open data.mdb - MDB_env* env_u; - if ( 0 != (env_u = u3_lmdb_init(epo_c, siz_i)) ) { - mdb_o = c3y; - } + c3_o len_o = c3n; // data.mdb is empty - // check if there are any events in the database - c3_d low_d, hig_d; - if ( 0 != u3_lmdb_gulf(env_u, &low_d, &hig_d) ) { - fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); - ret_o = c3n; - } else { - if ( low_d == hig_d == 0 ) { - len_o = c3y; // yes, data.mdb has events - } - } - u3_lmdb_exit(env_u); - } - - // check if epoc.txt is writable - if ( 0 == access(epv_c, W_OK) ) { - epv_o = c3y; + // check if we can open data.mdb + MDB_env* env_u; + if ( 0 == (env_u = u3_lmdb_init(epo_c, siz_i)) ) { + fprintf(stderr, "disk: failed to open epoch 0i%" PRIc3_d "/data.mdb\r\n", epo_d); + exit(1); } - // check if vere.txt is writable - if ( 0 == access(biv_c, W_OK) ) { - biv_o = c3y; + // check if there are any events in the database + c3_d low_d, hig_d; + if ( 0 != u3_lmdb_gulf(env_u, &low_d, &hig_d) ) { + fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); + ret_o = c3n; + } else { + if ( low_d == hig_d == 0 ) { + len_o = c3y; // yes, data.mdb is empty + } } + u3_lmdb_exit(env_u); // print error messages - if ( c3n == dir_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIc3_d " is not writable\r\n", epo_d); - ret_o = c3n; - } - if ( c3n == dat_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/data.mdb is not writable\r\n", epo_d); - ret_o = c3n; - } - if ( c3n == mdb_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/data.mdb can't be opened\r\n", epo_d); - ret_o = c3n; - } if ( c3n == len_o ) { fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/data.mdb has no events\r\n", epo_d); ret_o = c3n; } - if ( c3n == epv_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/epoc.txt is not writable\r\n", epo_d); - ret_o = c3n; - } - if ( c3n == biv_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/vere.txt is not writable\r\n", epo_d); - ret_o = c3n; - } return ret_o; } From 8703f11fd12df5883e5b24f05b7dee6e2103aa96 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 12 Jun 2023 10:23:28 -0400 Subject: [PATCH 33/87] disk: remove `u3_disk_epoc_good` and add argument to `u3_disk_epoc_init` --- pkg/vere/disk.c | 114 ++++++++++-------------------------------------- pkg/vere/main.c | 4 +- pkg/vere/vere.h | 7 +-- 3 files changed, 27 insertions(+), 98 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 9459fecedc..41da47653d 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -946,7 +946,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } if ( 0 != strcmp(ver_c, URBIT_VERSION) ) { - if ( c3n == u3_disk_epoc_init(log_u) ) { + if ( c3n == u3_disk_epoc_init(log_u, log_u->dun_d) ) { fprintf(stderr, "disk: failed to initialize epoch\r\n"); c3_free(log_u); return 0; @@ -965,86 +965,21 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return log_u; } -/* u3_disk_epoc_good: check for valid epoch. -*/ -c3_o -u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d) -{ - /* this function is used to check whether or not we can overwrite - * an epoch. if the epoch contains an openable data.mdb file that - * also contains events, then we consider it good and *cannot* - * overwrite it. if not, then we consider it bad and *can* overwrite it. - */ - - c3_o ret_o = c3y; // return code - - // file paths - c3_c epo_c[8193], dat_c[8193], epv_c[8193], biv_c[8193]; - snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, epo_d); - snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); - - c3_o len_o = c3n; // data.mdb is empty - - // check if we can open data.mdb - MDB_env* env_u; - if ( 0 == (env_u = u3_lmdb_init(epo_c, siz_i)) ) { - fprintf(stderr, "disk: failed to open epoch 0i%" PRIc3_d "/data.mdb\r\n", epo_d); - exit(1); - } - - // check if there are any events in the database - c3_d low_d, hig_d; - if ( 0 != u3_lmdb_gulf(env_u, &low_d, &hig_d) ) { - fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); - ret_o = c3n; - } else { - if ( low_d == hig_d == 0 ) { - len_o = c3y; // yes, data.mdb is empty - } - } - u3_lmdb_exit(env_u); - - // print error messages - if ( c3n == len_o ) { - fprintf(stderr, "disk: epoch 0i%" PRIc3_d "/data.mdb has no events\r\n", epo_d); - ret_o = c3n; - } - - return ret_o; -} - /* u3_disk_epoc_init: create new epoch. */ c3_o -u3_disk_epoc_init(u3_disk* log_u) +u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) { - // set new epoch number - c3_d lat_d, new_d; + // check if any epoch directories exist + c3_d lat_d; c3_o eps_o = u3_disk_epoc_last(log_u, &lat_d); - if ( c3n == eps_o ) { - // no epochs yet, so create first one 0i0 - new_d = 0; - } else if ( c3n == u3_disk_epoc_good(log_u, lat_d) ) { - // last epoch is invalid, so overwrite it - new_d = lat_d; - } else { - // last epoch is valid, so create next one - - // get first/last event numbers - c3_d fir_d, las_d; - if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { - fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); - return c3n; - } - new_d = las_d; // create next epoch - } // create new epoch directory if it doesn't exist c3_c epo_c[8193]; - snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, new_d); + snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, epo_d); c3_d ret_d = c3_mkdir(epo_c, 0700); if ( ( ret_d < 0 ) && ( errno != EEXIST ) ) { - fprintf(stderr, "disk: failed to create epoch directory %" PRIc3_d "\r\n", new_d); + fprintf(stderr, "disk: failed to create epoch directory %" PRIc3_d "\r\n", epo_d); return c3n; } @@ -1063,7 +998,7 @@ u3_disk_epoc_init(u3_disk* log_u) fclose(biv_f); // copy snapshot (skip if first epoch) - if ( new_d > 0 ) { + if ( epo_d > 0 ) { if ( c3n == u3e_backup(epo_c, c3y) ) { fprintf(stderr, "disk: failed to copy snapshot to new epoch\r\n"); goto fail; @@ -1074,7 +1009,7 @@ u3_disk_epoc_init(u3_disk* log_u) c3_d who_d[2]; c3_o fak_o; c3_w lif_w; - if ( c3y == eps_o ) { + if ( c3y == eps_o ) { // skip if no epochs yet if ( c3y != u3_disk_read_meta(log_u->mdb_u, who_d, &fak_o, &lif_w) ) { fprintf(stderr, "disk: failed to read metadata\r\n"); goto fail; @@ -1082,7 +1017,7 @@ u3_disk_epoc_init(u3_disk* log_u) } // initialize db of new epoch - if ( c3y == u3_Host.ops_u.nuu || new_d > 0 ) { + if ( c3y == u3_Host.ops_u.nuu || epo_d > 0 ) { c3_c dat_c[8193]; snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { @@ -1153,7 +1088,7 @@ u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { - c3_o ret_o = c3n; // return no if no epoch directories exist + c3_o ret_o = c3n; // return c3n if no epoch directories exist *lat_d = 0; // initialize lat_d to 0 u3_dire* die_u = u3_foil_folder(log_u->com_u->pax_c); u3_dent* den_u = die_u->dil_u; @@ -1257,7 +1192,7 @@ c3_o u3_disk_migrate(u3_disk* log_u) fprintf(stderr, "disk: initializing disk with v%d format\r\n", U3D_VER1); // initialize first epoch "0i0" - if ( c3n == u3_disk_epoc_init(log_u) ) { + if ( c3n == u3_disk_epoc_init(log_u, 0) ) { fprintf(stderr, "disk: failed to initialize first epoch\r\n"); return c3n; } @@ -1286,16 +1221,16 @@ c3_o u3_disk_migrate(u3_disk* log_u) // ensure there's a current snapshot if ( u3_Host.eve_d != las_d ) { - fprintf(stderr, "disk: migrate: error: snapshot is out of date, please " + fprintf(stderr, "disk: snapshot is out of date, please " "start/shutdown your pier gracefully first\r\n"); - fprintf(stderr, "disk: migrate: eve_d (%" PRIc3_d ") != las_d (%" PRIc3_d ")\r\n", + fprintf(stderr, "disk: eve_d (%" PRIc3_d ") != las_d (%" PRIc3_d ")\r\n", u3_Host.eve_d, las_d); return c3n; } // initialize first epoch "0i0" - if ( c3n == u3_disk_epoc_init(log_u) ) { - fprintf(stderr, "disk: migrate: failed to initialize first epoch\r\n"); + if ( c3n == u3_disk_epoc_init(log_u, 0) ) { + fprintf(stderr, "disk: failed to initialize first epoch\r\n"); return c3n; } @@ -1306,20 +1241,19 @@ c3_o u3_disk_migrate(u3_disk* log_u) snprintf(lok_c, sizeof(lok_c), "%s/lock.mdb", epo_c); if ( 0 < c3_link(dut_c, dat_c) ) { - fprintf(stderr, "disk: migrate: failed to create data.mdb hard link\r\n"); - fprintf(stderr, "errno %d: %s\r\n", errno, strerror(errno)); + fprintf(stderr, "disk: failed to create data.mdb hard link\r\n"); return c3n; } if ( c3y == luk_o ) { // only link lock.mdb if it exists if ( 0 < c3_link(luk_c, lok_c) ) { - fprintf(stderr, "disk: migrate: failed to create lock.mdb hard link\r\n"); + fprintf(stderr, "disk: failed to create lock.mdb hard link\r\n"); return c3n; } } // rollover to new epoch - if ( c3n == u3_disk_epoc_init(log_u) ) { - fprintf(stderr, "roll: error: failed to initialize new epoch\r\n"); + if ( c3n == u3_disk_epoc_init(log_u, las_d) ) { + fprintf(stderr, "disk: failed to initialize new epoch\r\n"); return c3n; } @@ -1329,21 +1263,21 @@ c3_o u3_disk_migrate(u3_disk* log_u) snprintf(nop_c, sizeof(nop_c), "%s/north.bin", bhk_c); snprintf(sop_c, sizeof(sop_c), "%s/south.bin", bhk_c); if ( c3n == c3_unlink(nop_c) ) { - fprintf(stderr, "disk: migrate: failed to delete bhk/north.bin\r\n"); + fprintf(stderr, "disk: failed to delete bhk/north.bin\r\n"); } else if ( c3n == c3_unlink(sop_c) ) { - fprintf(stderr, "disk: migrate: failed to delete bhk/south.bin\r\n"); + fprintf(stderr, "disk: failed to delete bhk/south.bin\r\n"); } else { if ( c3n == c3_rmdir(bhk_c) ) { - fprintf(stderr, "disk: migrate: failed to delete bhk/\r\n"); + fprintf(stderr, "disk: failed to delete bhk/\r\n"); } } // delete old lock.mdb and data.mdb files if ( 0 != c3_unlink(luk_c) ) { - fprintf(stderr, "disk: migrate: failed to unlink lock.mdb\r\n"); + fprintf(stderr, "disk: failed to unlink lock.mdb\r\n"); } if ( 0 != c3_unlink(dut_c) ) { - fprintf(stderr, "disk: migrate: failed to unlink data.mdb\r\n"); + fprintf(stderr, "disk: failed to unlink data.mdb\r\n"); return c3n; // migration succeeds only if we can unlink data.mdb } diff --git a/pkg/vere/main.c b/pkg/vere/main.c index dc9d3819ef..d29d8fba20 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2160,7 +2160,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) } // create new epoch if latest isn't empty - if ( (fir_d != las_d) && (c3n == u3_disk_epoc_init(log_u)) ) { + if ( (fir_d != las_d) && (c3n == u3_disk_epoc_init(log_u, las_d)) ) { fprintf(stderr, "chop: failed to create new epoch\r\n"); exit(1); } @@ -2302,7 +2302,7 @@ _cw_roll(c3_i argc, c3_c* argv[]) fprintf(stderr, "roll: latest epoch already empty\r\n"); exit(0); } - else if ( c3n == u3_disk_epoc_init(log_u) ) { + else if ( c3n == u3_disk_epoc_init(log_u, las_d) ) { fprintf(stderr, "roll: failed to create new epoch\r\n"); exit(1); } diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index f3e47a98b6..8d613e77b8 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -984,15 +984,10 @@ void u3_disk_plan(u3_disk* log_u, u3_fact* tac_u); - /* u3_disk_epoc_good(): check for valid epoch. - */ - c3_o - u3_disk_epoc_good(u3_disk* log_u, c3_d epo_d); - /* u3_disk_epoc_init(): create new epoch. */ c3_o - u3_disk_epoc_init(u3_disk* log_u); + u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d); /* u3_disk_epoc_kill(): delete an epoch. */ From 52f76bc93390122aa28711f6c44b15ae560264f2 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 15 Jun 2023 14:24:05 -0400 Subject: [PATCH 34/87] wip --- pkg/vere/main.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 0333d4d8f7..bb5b514bcc 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2096,6 +2096,28 @@ _cw_play(c3_i argc, c3_c* argv[]) u3C.wag_w |= u3o_hashless; + // replaying events with the epoch system + // + // there should be one process that accounts for what is actually available + // in the pier and replays the least events possible to produce a valid, + // up-to-date snapshot. + // + // this replay process also uses the chk/ folder as a place to + // "accumulate" snapshots over the course of a replay if it needs to, + // overwriting the existing .bin files as it goes. + // + // 0. try loading the snapshot in chk/ + // a. if it is valid and up-to-date with the log + // i. if we executed via `urbit play`, exit 0 + // ii. if we executed via `urbit`, boot into live mode + // b. if it is invalid, try loading a snapshot from + // i. the snapshot in the latest epoch + // 1. if it is valid, replay the events and save the resulting + // snapshot into chk/, exit 0 or boot into live mode as before + // 2. if it is invalid, return an error that informs the user of + // his need for a serious surgical operation + // + // XX this should restore the epoch snapshot and replay that // if ( c3y == ful_o ) { From 20a3af06cf59581e1eafa2518db0c485f3b4589e Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 20 Jun 2023 12:35:32 -0400 Subject: [PATCH 35/87] disk: set `epo_u` --- pkg/vere/disk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 7371f5a3fa..b06ea35fec 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1105,6 +1105,9 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } } + // mark the latest epoch directory + log_u->epo_u = u3_foil_folder(epo_c); + // mark the log as live log_u->liv_o = c3y; } From e5723adbe3ef4e08034eb7548ddcb5971a8bd2ba Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 21 Jun 2023 11:58:42 -0400 Subject: [PATCH 36/87] disk: `urbit play` with epochs --- .gitignore | 4 +++ pkg/noun/events.c | 92 +++++++++++++++++++++++++++++++++-------------- pkg/noun/events.h | 5 +-- pkg/vere/disk.c | 6 ++-- pkg/vere/main.c | 19 +++++----- 5 files changed, 85 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index 251a0d7f0f..da5bf8e6c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# IDEs. +/.vscode +/.idea + # Bazel. /.user.bazelrc /bazel-* diff --git a/pkg/noun/events.c b/pkg/noun/events.c index efb506f072..6da639e476 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -312,26 +312,44 @@ _ce_image_stat(u3e_image* img_u, c3_w* pgs_w) } } -/* _ce_image_open(): open or create image. +/* _ce_image_open(): open or create image, creating directories if necessary. */ static c3_o -_ce_image_open(u3e_image* img_u) +_ce_image_open(u3e_image* img_u, c3_c* ful_c) { c3_i mod_i = O_RDWR | O_CREAT; - c3_c ful_c[8193]; - snprintf(ful_c, 8192, "%s", u3P.dir_c); - c3_mkdir(ful_c, 0700); + // create directories if necessary + // + { + c3_c pax_c[8192]; + c3_c* end_c = pax_c + 8192; + c3_c* cur_c = pax_c + snprintf(pax_c, 8192, "%s", ful_c); - snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c); - c3_mkdir(ful_c, 0700); + while ( cur_c < end_c ) { + c3_c* nxt_c = strchr(cur_c, '/'); - snprintf(ful_c, 8192, "%s/.urb/chk", u3P.dir_c); - c3_mkdir(ful_c, 0700); + if ( !nxt_c ) { + break; + } + else { + *nxt_c = 0; + + if ( 0 != mkdir(pax_c, 0777) && EEXIST != errno ) { + fprintf(stderr, "loom: mkdir %s: %s\r\n", pax_c, strerror(errno)); + return c3n; + } - snprintf(ful_c, 8192, "%s/.urb/chk/%s.bin", u3P.dir_c, img_u->nam_c); - if ( -1 == (img_u->fid_i = c3_open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); + *nxt_c = '/'; + cur_c = nxt_c + 1; + } + } + } + + c3_c pax_c[8192]; + snprintf(pax_c, 8192, "%s/%s.bin", ful_c, img_u->nam_c); + if ( -1 == (img_u->fid_i = c3_open(pax_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", pax_c, strerror(errno)); return c3n; } else if ( c3n == _ce_image_stat(img_u, &img_u->pgs_w) ) { @@ -1231,17 +1249,24 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) return c3y; } -/* u3e_backup(): copy snapshot to pax_c, overwrite optionally. +/* u3e_backup(): copy snapshot from [pux_c] to [pax_c], + * overwriting optionally. note that image files must + * be named "north" and "south". */ c3_o -u3e_backup(c3_c* pax_c, c3_o ovw_o) +u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) { - u3e_image nop_u = { .nam_c = "north", .pgs_w = 0 }; - u3e_image sop_u = { .nam_c = "south", .pgs_w = 0 }; + // source image files from [pux_c] + u3e_image nux_u = { .nam_c = "north", .pgs_w = 0 }; + u3e_image sux_u = { .nam_c = "south", .pgs_w = 0 }; + + // destination image files to [pax_c] + u3e_image nax_u = { .nam_c = "north" }; + u3e_image sax_u = { .nam_c = "south" }; c3_i mod_i = O_RDWR | O_CREAT; - if ( !pax_c ) { + if ( !pux_c || !pax_c ) { fprintf(stderr, "loom: image backup: bad path\r\n"); return c3n; } @@ -1253,24 +1278,35 @@ u3e_backup(c3_c* pax_c, c3_o ovw_o) return c3n; } + // open source image files + // + if ( c3n == _ce_image_open(&nux_u, pux_c) ) { + fprintf(stderr, "loom: couldn't open north image at %s\r\n", pux_c); + return c3n; + } + if ( c3n == _ce_image_open(&sux_u, pux_c) ) { + fprintf(stderr, "loom: couldn't open south image at %s\r\n", pux_c); + return c3n; + } + c3_c nop_c[8193]; - snprintf(nop_c, 8192, "%s/%s.bin", pax_c, nop_u.nam_c); + snprintf(nop_c, 8192, "%s/%s.bin", pax_c, nax_u.nam_c); - if ( -1 == (nop_u.fid_i = c3_open(nop_c, mod_i, 0666)) ) { + if ( -1 == (nax_u.fid_i = c3_open(nop_c, mod_i, 0666)) ) { fprintf(stderr, "loom: c3_open %s: %s\r\n", nop_c, strerror(errno)); return c3n; } c3_c sop_c[8193]; - snprintf(sop_c, 8192, "%s/%s.bin", pax_c, sop_u.nam_c); + snprintf(sop_c, 8192, "%s/%s.bin", pax_c, sax_u.nam_c); - if ( -1 == (sop_u.fid_i = c3_open(sop_c, mod_i, 0666)) ) { + if ( -1 == (sax_u.fid_i = c3_open(sop_c, mod_i, 0666)) ) { fprintf(stderr, "loom: c3_open %s: %s\r\n", sop_c, strerror(errno)); return c3n; } - if ( (c3n == _ce_image_copy(&u3P.nor_u, &nop_u)) - || (c3n == _ce_image_copy(&u3P.sou_u, &sop_u)) ) + if ( (c3n == _ce_image_copy(&nux_u, &nax_u)) + || (c3n == _ce_image_copy(&sux_u, &sax_u)) ) { c3_unlink(nop_c); c3_unlink(sop_c); @@ -1278,8 +1314,8 @@ u3e_backup(c3_c* pax_c, c3_o ovw_o) return c3n; } - close(nop_u.fid_i); - close(sop_u.fid_i); + close(nax_u.fid_i); + close(sax_u.fid_i); fprintf(stderr, "loom: image backup complete\r\n"); return c3y; } @@ -1431,8 +1467,10 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) { // Open image files. // - if ( (c3n == _ce_image_open(&u3P.nor_u)) || - (c3n == _ce_image_open(&u3P.sou_u)) ) + c3_c chk_c[8193]; + snprintf(chk_c, 8193, "%s/.urb/chk", u3P.dir_c); + if ( (c3n == _ce_image_open(&u3P.nor_u, chk_c)) || + (c3n == _ce_image_open(&u3P.sou_u, chk_c)) ) { fprintf(stderr, "boot: image failed\r\n"); exit(1); diff --git a/pkg/noun/events.h b/pkg/noun/events.h index d3a2b58a0b..462372cd28 100644 --- a/pkg/noun/events.h +++ b/pkg/noun/events.h @@ -73,10 +73,11 @@ /** Functions. **/ - /* u3e_backup(): copy the snapshot to pax_c, overwrite optional. + /* u3e_backup(): copy the snapshot from [pux_c] to [pax_c], + * overwriting optional. */ c3_o - u3e_backup(c3_c* pax_c, c3_o ovw_o); + u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o); /* u3e_fault(): handle a memory fault. */ diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index b06ea35fec..103f85a484 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1152,9 +1152,11 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) fprintf(biv_f, URBIT_VERSION); fclose(biv_f); - // copy snapshot (skip if first epoch) + // copy snapshot files (skip if first epoch) if ( epo_d > 0 ) { - if ( c3n == u3e_backup(epo_c, c3y) ) { + c3_c chk_c[8193]; + snprintf(chk_c, 8192, "%s/.urb/chk", u3_Host.dir_c); + if ( c3n == u3e_backup(epo_c, chk_c, c3y) ) { fprintf(stderr, "disk: failed to copy snapshot to new epoch\r\n"); goto fail; } diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 0f552b0252..e3da6e9291 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2118,20 +2118,19 @@ _cw_play(c3_i argc, c3_c* argv[]) // his need for a serious surgical operation // - // XX this should restore the epoch snapshot and replay that - // if ( c3y == ful_o ) { + // copy the latest epoch's snapshot files into chk/ u3l_log("mars: preparing for full replay"); - u3m_init((size_t)1 << u3_Host.ops_u.lom_y); - u3e_live(c3n, u3_Host.dir_c); - u3m_foul(); - u3m_pave(c3y); - u3j_boot(c3y); - } - else { - u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + c3_c chk_c[8193]; + snprintf(chk_c, 8193, "%s/.urb/chk", u3_Host.dir_c); + if ( 0 != u3e_backup(log_u->epo_u->pax_c, chk_c, c3y) ) { + fprintf(stderr, "mars: failed to copy snapshot\r\n"); + exit(1); + } } + u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + u3C.slog_f = _cw_play_slog; { From c9a624d2b299d290ee97cd1699f9b9e3d2e9032d Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 21 Jun 2023 12:59:03 -0400 Subject: [PATCH 37/87] events: better path naming --- pkg/noun/events.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 6da639e476..f9c3904432 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1289,27 +1289,27 @@ u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) return c3n; } - c3_c nop_c[8193]; - snprintf(nop_c, 8192, "%s/%s.bin", pax_c, nax_u.nam_c); + c3_c nax_c[8193]; + snprintf(nax_c, 8192, "%s/%s.bin", pax_c, nax_u.nam_c); - if ( -1 == (nax_u.fid_i = c3_open(nop_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: c3_open %s: %s\r\n", nop_c, strerror(errno)); + if ( -1 == (nax_u.fid_i = c3_open(nax_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", nax_c, strerror(errno)); return c3n; } - c3_c sop_c[8193]; - snprintf(sop_c, 8192, "%s/%s.bin", pax_c, sax_u.nam_c); + c3_c sax_c[8193]; + snprintf(sax_c, 8192, "%s/%s.bin", pax_c, sax_u.nam_c); - if ( -1 == (sax_u.fid_i = c3_open(sop_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: c3_open %s: %s\r\n", sop_c, strerror(errno)); + if ( -1 == (sax_u.fid_i = c3_open(sax_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", sax_c, strerror(errno)); return c3n; } if ( (c3n == _ce_image_copy(&nux_u, &nax_u)) || (c3n == _ce_image_copy(&sux_u, &sax_u)) ) { - c3_unlink(nop_c); - c3_unlink(sop_c); + c3_unlink(nax_c); + c3_unlink(sax_c); fprintf(stderr, "loom: image backup failed\r\n"); return c3n; } From 01ecd2e40fa4d828d4614c092b61825d442d5b41 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 22 Jun 2023 09:41:51 -0400 Subject: [PATCH 38/87] disk: fix merge error --- pkg/vere/disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 73f92ac43a..7bfb89fff8 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1156,7 +1156,7 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) if ( epo_d > 0 ) { c3_c chk_c[8193]; snprintf(chk_c, 8192, "%s/.urb/chk", u3_Host.dir_c); - if ( c3n == u3e_backup(epo_c, chk_c, c3y) ) { + if ( c3n == u3e_backup(chk_c, epo_c, c3y) ) { fprintf(stderr, "disk: failed to copy snapshot to new epoch\r\n"); goto fail; } From 4336422ae061abd7cc234d2cb6abbdfc0d14e75e Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 22 Jun 2023 14:38:23 -0400 Subject: [PATCH 39/87] events: remove unnecessary/erroneous `mkdir -p` implementation --- pkg/noun/events.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index f3fd13e5ab..afc1d04001 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -402,33 +402,6 @@ _ce_image_open(u3e_image* img_u, c3_c* ful_c) { c3_i mod_i = O_RDWR | O_CREAT; - // create directories if necessary - // - { - c3_c pax_c[8192]; - c3_c* end_c = pax_c + 8192; - c3_c* cur_c = pax_c + snprintf(pax_c, 8192, "%s", ful_c); - - while ( cur_c < end_c ) { - c3_c* nxt_c = strchr(cur_c, '/'); - - if ( !nxt_c ) { - break; - } - else { - *nxt_c = 0; - - if ( 0 != mkdir(pax_c, 0777) && EEXIST != errno ) { - fprintf(stderr, "loom: mkdir %s: %s\r\n", pax_c, strerror(errno)); - return c3n; - } - - *nxt_c = '/'; - cur_c = nxt_c + 1; - } - } - } - c3_c pax_c[8192]; snprintf(pax_c, 8192, "%s/%s.bin", ful_c, img_u->nam_c); if ( -1 == (img_u->fid_i = c3_open(pax_c, mod_i, 0666)) ) { From ac3dd768a7fce2e057ab13ccf965d6dd248bc183 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 22 Jun 2023 14:41:44 -0400 Subject: [PATCH 40/87] trim trailing whitespace --- pkg/noun/events.c | 4 ++-- pkg/noun/events.h | 4 ++-- pkg/vere/main.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index afc1d04001..3078345e16 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1336,8 +1336,8 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) return c3y; } -/* u3e_backup(): copy snapshot from [pux_c] to [pax_c], - * overwriting optionally. note that image files must +/* u3e_backup(): copy snapshot from [pux_c] to [pax_c], + * overwriting optionally. note that image files must * be named "north" and "south". */ c3_o diff --git a/pkg/noun/events.h b/pkg/noun/events.h index 0d6a1e351b..7442c9df94 100644 --- a/pkg/noun/events.h +++ b/pkg/noun/events.h @@ -74,10 +74,10 @@ /** Functions. **/ - /* u3e_backup(): copy the snapshot from [pux_c] to [pax_c], + /* u3e_backup(): copy the snapshot from [pux_c] to [pax_c], * overwriting optional. */ - c3_o + c3_o u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o); /* u3e_fault(): handle a memory fault. diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 5df8125eef..cb2b59f02c 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2234,11 +2234,11 @@ _cw_play(c3_i argc, c3_c* argv[]) // replaying events with the epoch system // - // there should be one process that accounts for what is actually available + // there should be one process that accounts for what is actually available // in the pier and replays the least events possible to produce a valid, // up-to-date snapshot. // - // this replay process also uses the chk/ folder as a place to + // this replay process also uses the chk/ folder as a place to // "accumulate" snapshots over the course of a replay if it needs to, // overwriting the existing .bin files as it goes. // @@ -2250,7 +2250,7 @@ _cw_play(c3_i argc, c3_c* argv[]) // i. the snapshot in the latest epoch // 1. if it is valid, replay the events and save the resulting // snapshot into chk/, exit 0 or boot into live mode as before - // 2. if it is invalid, return an error that informs the user of + // 2. if it is invalid, return an error that informs the user of // his need for a serious surgical operation // From 6c6ac0c0c4c4c37c0cc01790cdc41b402e79c5c2 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 22 Jun 2023 20:31:40 -0400 Subject: [PATCH 41/87] events: `mkdir -p` for `_ce_image_open` (needed for boot) --- pkg/noun/events.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 3078345e16..8d7910eb26 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -402,6 +402,23 @@ _ce_image_open(u3e_image* img_u, c3_c* ful_c) { c3_i mod_i = O_RDWR | O_CREAT; + // create directories recursively like `mkdir -p` + // + { + c3_c* dir_c = ful_c; + c3_c* end_c = ful_c + strlen(ful_c); + + while ( dir_c < end_c ) { + if ( '/' == *dir_c ) { + *dir_c = 0; + c3_mkdir(ful_c, 0700); + *dir_c = '/'; + } + dir_c++; + } + c3_mkdir(ful_c, 0700); + } + c3_c pax_c[8192]; snprintf(pax_c, 8192, "%s/%s.bin", ful_c, img_u->nam_c); if ( -1 == (img_u->fid_i = c3_open(pax_c, mod_i, 0666)) ) { From 64c54543315263698d50a333b8084add9b830b1f Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 22 Jun 2023 20:45:42 -0400 Subject: [PATCH 42/87] events: prevent `0B` snapshot files from being created during `play` --- pkg/noun/events.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 8d7910eb26..8dcf529c09 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1382,13 +1382,21 @@ u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) return c3n; } - // open source image files + // open source image files if they exist // - if ( c3n == _ce_image_open(&nux_u, pux_c) ) { + + // check if file exists with access + // + + c3_c nux_c[8193]; + snprintf(nux_c, 8192, "%s/%s.bin", pux_c, nux_u.nam_c); + if ( (0 < access(nux_c, F_OK)) && (c3n == _ce_image_open(&nux_u, pux_c)) ) { fprintf(stderr, "loom: couldn't open north image at %s\r\n", pux_c); return c3n; } - if ( c3n == _ce_image_open(&sux_u, pux_c) ) { + c3_c sux_c[8193]; + snprintf(sux_c, 8192, "%s/%s.bin", pux_c, sux_u.nam_c); + if ( (0 < access(sux_c, F_OK)) && (c3n == _ce_image_open(&sux_u, pux_c)) ) { fprintf(stderr, "loom: couldn't open south image at %s\r\n", pux_c); return c3n; } From b6541b73dc6fdc7772bece5d24bf7bccca760837 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 23 Jun 2023 10:14:09 -0400 Subject: [PATCH 43/87] events: remove `mkdir -p` functionality from `_ce_image_open` --- pkg/noun/events.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 8dcf529c09..8e53f30daa 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -402,23 +402,6 @@ _ce_image_open(u3e_image* img_u, c3_c* ful_c) { c3_i mod_i = O_RDWR | O_CREAT; - // create directories recursively like `mkdir -p` - // - { - c3_c* dir_c = ful_c; - c3_c* end_c = ful_c + strlen(ful_c); - - while ( dir_c < end_c ) { - if ( '/' == *dir_c ) { - *dir_c = 0; - c3_mkdir(ful_c, 0700); - *dir_c = '/'; - } - dir_c++; - } - c3_mkdir(ful_c, 0700); - } - c3_c pax_c[8192]; snprintf(pax_c, 8192, "%s/%s.bin", ful_c, img_u->nam_c); if ( -1 == (img_u->fid_i = c3_open(pax_c, mod_i, 0666)) ) { @@ -1384,10 +1367,6 @@ u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) // open source image files if they exist // - - // check if file exists with access - // - c3_c nux_c[8193]; snprintf(nux_c, 8192, "%s/%s.bin", pux_c, nux_u.nam_c); if ( (0 < access(nux_c, F_OK)) && (c3n == _ce_image_open(&nux_u, pux_c)) ) { From 299c6edb02201dbda3c366c86ceee1ca86d7d4f3 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Fri, 23 Jun 2023 10:14:40 -0400 Subject: [PATCH 44/87] disk: create `.urb/chk` on init; simplify `log_u->dun_d` setting --- pkg/vere/disk.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 7bfb89fff8..b9b5b9d1b7 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1028,6 +1028,10 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) strcat(dir_c, "/.urb/get"); c3_mkdir(dir_c, 0700); + strcpy(dir_c, pax_c); + strcat(dir_c, "/.urb/chk"); + c3_mkdir(dir_c, 0700); + c3_free(dir_c); } @@ -1078,14 +1082,10 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } // initialize dun_d/sen_d values - if ( 0 == las_d ) { // fresh epoch (no events in lmdb yet) - if ( 0 == lat_d ) { // first epoch - log_u->dun_d = 0; - } else { // not first epoch - log_u->dun_d = lat_d; // set dun_d to last event in prev epoch - } - } else { // not fresh epoch - log_u->dun_d = las_d; // set dun_d to last event in lmdb + if ( 0 == las_d ) { // first epoch (no events in lmdb yet) + log_u->dun_d = lat_d; // set dun_d to last event in prev epoch + } else { + log_u->dun_d = las_d; // set dun_d to last event in lmdb } log_u->sen_d = log_u->dun_d; @@ -1307,12 +1307,12 @@ u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) */ c3_o u3_disk_migrate(u3_disk* log_u) { - /* migration steps (* indicates breakpoint set): + /* migration steps: * 0. detect whether we need to migrate or not - * a. if it's a fresh boot via u3_Host.ops_u.nuu -> skip migration (returns yes) - * b. if data.mdb is readable in log directory -> execute migration (returns yes or no) + * a. if it's a fresh boot via u3_Host.ops_u.nuu -> skip migration + * b. if data.mdb is readable in log directory -> execute migration * if not -> skip migration (returns yes) - * 1. initialize epoch 0i0 (first call to u3_disk_epoc_init()) * + * 1. initialize epoch 0i0 (first call to u3_disk_epoc_init()) * a. creates epoch directory * b. creates epoch version file * c. creates binary version file @@ -1321,10 +1321,10 @@ c3_o u3_disk_migrate(u3_disk* log_u) * f. writes metadata to new database * g. loads new epoch directory and sets it in log_u * 2. create hard links to data.mdb and lock.mdb in 0i0/ - * 3. rollover to new epoch (second call to u3_disk_epoc_init()) * + * 3. rollover to new epoch (second call to u3_disk_epoc_init()) * a. same as 1a-g but also copies current snapshot between c/d steps - * 4. delete backup snapshot (c3_unlink() and c3_rmdir() calls) * - * 5. delete old data.mdb and lock.mdb files (c3_unlink() calls) * + * 4. delete backup snapshot (c3_unlink() and c3_rmdir() calls) + * 5. delete old data.mdb and lock.mdb files (c3_unlink() calls) */ // check if data.mdb is readable in log directory From 8a3df1dd3df59b190ebe5e70cffe40fbd278c686 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 27 Jun 2023 11:06:56 -0400 Subject: [PATCH 45/87] play: full replay when only epoch 0 exists --- pkg/vere/disk.c | 17 ++++++----------- pkg/vere/main.c | 47 ++++++++++++++++++++++------------------------- pkg/vere/vere.h | 2 +- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index b9b5b9d1b7..615634eb30 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1082,15 +1082,15 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } // initialize dun_d/sen_d values - if ( 0 == las_d ) { // first epoch (no events in lmdb yet) - log_u->dun_d = lat_d; // set dun_d to last event in prev epoch - } else { - log_u->dun_d = las_d; // set dun_d to last event in lmdb - } + log_u->dun_d = ( 0 != las_d ) ? las_d : lat_d; log_u->sen_d = log_u->dun_d; + // mark the latest epoch directory + log_u->epo_d = lat_d; + // if binary version of latest epoch is not the same as the // running binary, then we need to create a new epoch + // XX move this into its own function and call it in `u3_pier_stay()` c3_c ver_c[8193]; if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_c) ) { fprintf(stderr, "disk: failed to load epoch version\r\n"); @@ -1105,9 +1105,6 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } } - // mark the latest epoch directory - log_u->epo_u = u3_foil_folder(epo_c); - // mark the log as live log_u->liv_o = c3y; } @@ -1193,7 +1190,7 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) } // load new epoch directory and set it in log_u - log_u->epo_u = u3_foil_folder(epo_c); + log_u->epo_d = epo_d; // success return c3y; @@ -1346,8 +1343,6 @@ c3_o u3_disk_migrate(u3_disk* log_u) // if fresh boot, initialize disk v1 if ( c3y == u3_Host.ops_u.nuu ) { - fprintf(stderr, "disk: initializing disk with v%d format\r\n", U3D_VER1); - // initialize first epoch "0i0" if ( c3n == u3_disk_epoc_init(log_u, 0) ) { fprintf(stderr, "disk: failed to initialize first epoch\r\n"); diff --git a/pkg/vere/main.c b/pkg/vere/main.c index cb2b59f02c..ee09777c29 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2232,34 +2232,31 @@ _cw_play(c3_i argc, c3_c* argv[]) u3C.wag_w |= u3o_hashless; - // replaying events with the epoch system - // - // there should be one process that accounts for what is actually available - // in the pier and replays the least events possible to produce a valid, - // up-to-date snapshot. - // - // this replay process also uses the chk/ folder as a place to - // "accumulate" snapshots over the course of a replay if it needs to, - // overwriting the existing .bin files as it goes. - // - // 0. try loading the snapshot in chk/ - // a. if it is valid and up-to-date with the log - // i. if we executed via `urbit play`, exit 0 - // ii. if we executed via `urbit`, boot into live mode - // b. if it is invalid, try loading a snapshot from - // i. the snapshot in the latest epoch - // 1. if it is valid, replay the events and save the resulting - // snapshot into chk/, exit 0 or boot into live mode as before - // 2. if it is invalid, return an error that informs the user of - // his need for a serious surgical operation - // - if ( c3y == ful_o ) { - // copy the latest epoch's snapshot files into chk/ u3l_log("mars: preparing for full replay"); - c3_c chk_c[8193]; + + c3_c chk_c[8193], epo_c[8193]; snprintf(chk_c, 8193, "%s/.urb/chk", u3_Host.dir_c); - if ( 0 != u3e_backup(log_u->epo_u->pax_c, chk_c, c3y) ) { + snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_u->com_u->pax_c, log_u->epo_d); + + // if epoch 0 is the latest, delete the snapshot files in chk/ + if ( 0 == log_u->epo_d ) { + c3_c nor_c[8193], sop_c[8193]; + snprintf(nor_c, 8193, "%s/.urb/chk/north.bin", u3_Host.dir_c); + snprintf(sop_c, 8193, "%s/.urb/chk/south.bin", u3_Host.dir_c); + if ( c3_unlink(nor_c) && (ENOENT != errno) ) { + fprintf(stderr, "mars: failed to unlink %s: %s\r\n", + nor_c, strerror(errno)); + exit(1); + } + if ( c3_unlink(sop_c) && (ENOENT != errno) ) { + fprintf(stderr, "mars: failed to unlink %s: %s\r\n", + sop_c, strerror(errno)); + exit(1); + } + } + else if ( 0 != u3e_backup(epo_c, chk_c, c3y) ) { + // copy the latest epoch's snapshot files into chk/ fprintf(stderr, "mars: failed to copy snapshot\r\n"); exit(1); } diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index 4e3ea2757c..58685ac4e6 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -539,11 +539,11 @@ u3_dire* dir_u; // main pier directory u3_dire* urb_u; // urbit system data u3_dire* com_u; // log directory - u3_dire* epo_u; // current epoch directory c3_o liv_o; // live void* mdb_u; // lmdb env of current epoch c3_d sen_d; // commit requested c3_d dun_d; // committed + c3_d epo_d; // current epoch number u3_disk_cb cb_u; // callbacks u3_read* red_u; // read requests union { // write thread/request From fa9cdddda45008feb63fcda1bd3d397ba2deb321 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 28 Jun 2023 11:23:06 -0400 Subject: [PATCH 46/87] events/disk/pier: implement `u3_disk_vere_diff` --- pkg/noun/events.c | 12 ++++------ pkg/vere/disk.c | 49 ++++++++++++++++++++++++--------------- pkg/vere/main.c | 59 ++++++++++++++++++++++++++--------------------- pkg/vere/pier.c | 10 +++++++- pkg/vere/vere.h | 5 ++++ 5 files changed, 82 insertions(+), 53 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 8e53f30daa..15db40605a 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1344,8 +1344,8 @@ c3_o u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) { // source image files from [pux_c] - u3e_image nux_u = { .nam_c = "north", .pgs_w = 0 }; - u3e_image sux_u = { .nam_c = "south", .pgs_w = 0 }; + u3e_image nux_u = { .nam_c = "north" }; + u3e_image sux_u = { .nam_c = "south" }; // destination image files to [pax_c] u3e_image nax_u = { .nam_c = "north" }; @@ -1369,28 +1369,26 @@ u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) // c3_c nux_c[8193]; snprintf(nux_c, 8192, "%s/%s.bin", pux_c, nux_u.nam_c); - if ( (0 < access(nux_c, F_OK)) && (c3n == _ce_image_open(&nux_u, pux_c)) ) { + if ( (0 != access(nux_c, F_OK)) || (c3n == _ce_image_open(&nux_u, pux_c)) ) { fprintf(stderr, "loom: couldn't open north image at %s\r\n", pux_c); return c3n; } c3_c sux_c[8193]; snprintf(sux_c, 8192, "%s/%s.bin", pux_c, sux_u.nam_c); - if ( (0 < access(sux_c, F_OK)) && (c3n == _ce_image_open(&sux_u, pux_c)) ) { + if ( (0 != access(sux_c, F_OK)) || (c3n == _ce_image_open(&sux_u, pux_c)) ) { fprintf(stderr, "loom: couldn't open south image at %s\r\n", pux_c); return c3n; } + // open destination image files c3_c nax_c[8193]; snprintf(nax_c, 8192, "%s/%s.bin", pax_c, nax_u.nam_c); - if ( -1 == (nax_u.fid_i = c3_open(nax_c, mod_i, 0666)) ) { fprintf(stderr, "loom: c3_open %s: %s\r\n", nax_c, strerror(errno)); return c3n; } - c3_c sax_c[8193]; snprintf(sax_c, 8192, "%s/%s.bin", pax_c, sax_u.nam_c); - if ( -1 == (sax_u.fid_i = c3_open(sax_c, mod_i, 0666)) ) { fprintf(stderr, "loom: c3_open %s: %s\r\n", sax_c, strerror(errno)); return c3n; diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 615634eb30..4d95a9516e 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1088,23 +1088,6 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) // mark the latest epoch directory log_u->epo_d = lat_d; - // if binary version of latest epoch is not the same as the - // running binary, then we need to create a new epoch - // XX move this into its own function and call it in `u3_pier_stay()` - c3_c ver_c[8193]; - if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_c) ) { - fprintf(stderr, "disk: failed to load epoch version\r\n"); - c3_free(log_u); - return 0; - } - if ( 0 != strcmp(ver_c, URBIT_VERSION) ) { - if ( c3n == u3_disk_epoc_init(log_u, log_u->dun_d) ) { - fprintf(stderr, "disk: failed to initialize epoch\r\n"); - c3_free(log_u); - return 0; - } - } - // mark the log as live log_u->liv_o = c3y; } @@ -1416,9 +1399,11 @@ c3_o u3_disk_migrate(u3_disk* log_u) snprintf(sop_c, sizeof(sop_c), "%s/south.bin", bhk_c); if ( c3n == c3_unlink(nop_c) ) { fprintf(stderr, "disk: failed to delete bhk/north.bin\r\n"); - } else if ( c3n == c3_unlink(sop_c) ) { + } + else if ( c3n == c3_unlink(sop_c) ) { fprintf(stderr, "disk: failed to delete bhk/south.bin\r\n"); - } else { + } + else { if ( c3n == c3_rmdir(bhk_c) ) { fprintf(stderr, "disk: failed to delete bhk/\r\n"); } @@ -1438,3 +1423,29 @@ c3_o u3_disk_migrate(u3_disk* log_u) return c3y; } + + +/* u3_disk_vere_diff(): checks if vere version mismatches latest epoch's. +*/ +c3_o +u3_disk_vere_diff(u3_disk* log_u) +{ + c3_d lat_d; + if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { + fprintf(stderr, "disk: failed to load last epoch\r\n"); + c3_free(log_u); + return 0; + } + + c3_c ver_c[8193]; + if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_c) ) { + fprintf(stderr, "disk: failed to load epoch version\r\n"); + c3_free(log_u); + return 0; + } + if ( 0 != strcmp(ver_c, URBIT_VERSION) ) { + return c3y; + } + + return c3n; +} \ No newline at end of file diff --git a/pkg/vere/main.c b/pkg/vere/main.c index ee09777c29..0cc3b4afc8 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2109,6 +2109,38 @@ _cw_play_slog(u3_noun hod) u3z(hod); } +/* _cw_play_snap(): prepare snapshot for full replay. +*/ +static void +_cw_play_snap(u3_disk* log_u) +{ + c3_c chk_c[8193], epo_c[8193]; + snprintf(chk_c, 8193, "%s/.urb/chk", u3_Host.dir_c); + snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_u->com_u->pax_c, log_u->epo_d); + + if ( 0 == log_u->epo_d ) { + // if epoch 0 is the latest, delete the snapshot files in chk/ + c3_c nor_c[8193], sop_c[8193]; + snprintf(nor_c, 8193, "%s/.urb/chk/north.bin", u3_Host.dir_c); + snprintf(sop_c, 8193, "%s/.urb/chk/south.bin", u3_Host.dir_c); + if ( c3_unlink(nor_c) && (ENOENT != errno) ) { + fprintf(stderr, "mars: failed to unlink %s: %s\r\n", + nor_c, strerror(errno)); + exit(1); + } + if ( c3_unlink(sop_c) && (ENOENT != errno) ) { + fprintf(stderr, "mars: failed to unlink %s: %s\r\n", + sop_c, strerror(errno)); + exit(1); + } + } + else if ( 0 != u3e_backup(epo_c, chk_c, c3y) ) { + // copy the latest epoch's snapshot files into chk/ + fprintf(stderr, "mars: failed to copy snapshot\r\n"); + exit(1); + } +} + /* _cw_play_exit(): exit immediately. */ static void @@ -2234,32 +2266,7 @@ _cw_play(c3_i argc, c3_c* argv[]) if ( c3y == ful_o ) { u3l_log("mars: preparing for full replay"); - - c3_c chk_c[8193], epo_c[8193]; - snprintf(chk_c, 8193, "%s/.urb/chk", u3_Host.dir_c); - snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_u->com_u->pax_c, log_u->epo_d); - - // if epoch 0 is the latest, delete the snapshot files in chk/ - if ( 0 == log_u->epo_d ) { - c3_c nor_c[8193], sop_c[8193]; - snprintf(nor_c, 8193, "%s/.urb/chk/north.bin", u3_Host.dir_c); - snprintf(sop_c, 8193, "%s/.urb/chk/south.bin", u3_Host.dir_c); - if ( c3_unlink(nor_c) && (ENOENT != errno) ) { - fprintf(stderr, "mars: failed to unlink %s: %s\r\n", - nor_c, strerror(errno)); - exit(1); - } - if ( c3_unlink(sop_c) && (ENOENT != errno) ) { - fprintf(stderr, "mars: failed to unlink %s: %s\r\n", - sop_c, strerror(errno)); - exit(1); - } - } - else if ( 0 != u3e_backup(epo_c, chk_c, c3y) ) { - // copy the latest epoch's snapshot files into chk/ - fprintf(stderr, "mars: failed to copy snapshot\r\n"); - exit(1); - } + _cw_play_snap(log_u); } u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 263af55e1a..c2e7c47026 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -782,7 +782,7 @@ _pier_on_lord_wyrd_bail(void* ptr_v, u3_ovum* egg_u, u3_noun lud) #endif } -/* _pier_wyrd_init(): construct %wyrd. +/* _pier_wyrd_card(): construct %wyrd. */ static u3_noun _pier_wyrd_card(u3_pier* pir_u) @@ -825,6 +825,14 @@ _pier_wyrd_card(u3_pier* pir_u) static void _pier_wyrd_init(u3_pier* pir_u) { + // create a new epoch if current version mismatches the latest epoch's + if ( c3y == u3_disk_vere_diff(pir_u->log_u) ) { + if ( c3n == u3_disk_epoc_init(pir_u->log_u, pir_u->log_u->dun_d) ) { + fprintf(stderr, "disk: failed to initialize epoch\r\n"); + exit(1); + } + } + u3_noun cad = _pier_wyrd_card(pir_u); u3_noun wir = u3nc(c3__arvo, u3_nul); diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index 58685ac4e6..c72417f86d 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -1025,6 +1025,11 @@ c3_o u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w); + /* u3_disk_vere_diff(): checks if vere version mismatches latest epoch's. + */ + c3_o + u3_disk_vere_diff(u3_disk* log_u); + /* u3_disk_migrate(): migrates disk format. */ c3_o From 4d35ba25b3300b82a00b3b82b4d76d1cc9581407 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 28 Jun 2023 11:43:22 -0400 Subject: [PATCH 47/87] pier: move `.urb/chk` creation into `u3m_pier` --- pkg/noun/manage.c | 38 +++++++++++++++++++++++++++++++++++++- pkg/noun/manage.h | 5 +++++ pkg/vere/disk.c | 4 ---- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 9b2450af12..2e3ce7accd 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -2068,6 +2068,42 @@ u3m_stop() u3je_secp_stop(); } +/* u3m_pier(): make a pier. +*/ +c3_c* +u3m_pier(c3_c* dir_c) +{ + c3_c ful_c[8193]; + + u3C.dir_c = dir_c; + + snprintf(ful_c, 8192, "%s", dir_c); + if ( c3_mkdir(ful_c, 0700) ) { + if ( EEXIST != errno ) { + fprintf(stderr, "loom: pier create: %s\r\n", strerror(errno)); + exit(1); + } + } + + snprintf(ful_c, 8192, "%s/.urb", dir_c); + if ( c3_mkdir(ful_c, 0700) ) { + if ( EEXIST != errno ) { + fprintf(stderr, "loom: .urb create: %s\r\n", strerror(errno)); + exit(1); + } + } + + snprintf(ful_c, 8192, "%s/.urb/chk", dir_c); + if ( c3_mkdir(ful_c, 0700) ) { + if ( EEXIST != errno ) { + fprintf(stderr, "loom: .urb/chk create: %s\r\n", strerror(errno)); + exit(1); + } + } + + return strdup(dir_c); +} + /* u3m_boot(): start the u3 system. return next event, starting from 1. */ c3_d @@ -2083,7 +2119,7 @@ u3m_boot(c3_c* dir_c, size_t len_i) /* Activate the storage system. */ - nuu_o = u3e_live(c3n, dir_c); + nuu_o = u3e_live(c3n, u3m_pier(dir_c)); /* Activate tracing. */ diff --git a/pkg/noun/manage.h b/pkg/noun/manage.h index 297585c486..56d4ca7901 100644 --- a/pkg/noun/manage.h +++ b/pkg/noun/manage.h @@ -14,6 +14,11 @@ c3_d u3m_boot(c3_c* dir_c, size_t len_i); + /* u3m_pier(): make a pier. + */ + c3_c* + u3m_pier(c3_c* dir_c); + /* u3m_boot_lite(): start without checkpointing. */ c3_d diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 4d95a9516e..2085262bd7 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1028,10 +1028,6 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) strcat(dir_c, "/.urb/get"); c3_mkdir(dir_c, 0700); - strcpy(dir_c, pax_c); - strcat(dir_c, "/.urb/chk"); - c3_mkdir(dir_c, 0700); - c3_free(dir_c); } From 8668d732bbed6896d800e6bccf12687d47160d1d Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 29 Jun 2023 21:11:38 -0400 Subject: [PATCH 48/87] cli: subcommands auto-migrate disk format --- pkg/vere/main.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 0cc3b4afc8..2291ed3b4f 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -1561,11 +1561,11 @@ _cw_info(c3_i argc, c3_c* argv[]) exit(1); } - c3_d eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); fprintf(stderr, "\r\nurbit: %s at event %" PRIu64 "\r\n", - u3_Host.dir_c, eve_d); + u3_Host.dir_c, u3_Host.eve_d); u3_disk_slog(log_u); printf("\n"); @@ -1720,17 +1720,17 @@ _cw_cram(c3_i argc, c3_c* argv[]) exit(1); } - c3_d eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock c3_o ret_o; fprintf(stderr, "urbit: cram: preparing\r\n"); - if ( c3n == (ret_o = u3u_cram(u3_Host.dir_c, eve_d)) ) { + if ( c3n == (ret_o = u3u_cram(u3_Host.dir_c, u3_Host.eve_d)) ) { fprintf(stderr, "urbit: cram: unable to jam state\r\n"); } else { - fprintf(stderr, "urbit: cram: rock saved at event %" PRIu64 "\r\n", eve_d); + fprintf(stderr, "urbit: cram: rock saved at event %" PRIu64 "\r\n", u3_Host.eve_d); } // save even on failure, as we just did all the work of deduplication @@ -1832,12 +1832,11 @@ _cw_queu(c3_i argc, c3_c* argv[]) exit(1); } else { + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock fprintf(stderr, "urbit: queu: preparing\r\n"); - u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); - // XX can spuriously fail do to corrupt memory-image checkpoint, // need a u3m_half_boot equivalent // workaround is to delete/move the checkpoint in case of corruption @@ -1925,11 +1924,11 @@ _cw_meld(c3_i argc, c3_c* argv[]) exit(1); } + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock c3_w pre_w; u3C.wag_w |= u3o_hashless; - u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); pre_w = u3a_open(u3R); u3u_meld(); @@ -2090,9 +2089,9 @@ _cw_pack(c3_i argc, c3_c* argv[]) exit(1); } + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock - u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3a_print_memory(stderr, "urbit: pack: gained", u3m_pack()); u3m_save(); @@ -2246,6 +2245,7 @@ _cw_play(c3_i argc, c3_c* argv[]) // XX handle SIGTSTP so that the lockfile is not orphaned? // + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock // Handle SIGTSTP as if it was SIGINT. @@ -2269,8 +2269,6 @@ _cw_play(c3_i argc, c3_c* argv[]) _cw_play_snap(log_u); } - u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); - u3C.slog_f = _cw_play_slog; { @@ -2435,19 +2433,9 @@ _cw_chop(c3_i argc, c3_c* argv[]) } // gracefully shutdown the pier if it's running + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); - // note: this includes patch applications (if any) - u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); - - // check if there's a *current* snapshot - if ( log_u->dun_d != u3A->eve_d ) { - fprintf(stderr, "chop: error: snapshot is out of date, please " - "start/shutdown your pier gracefully first\r\n"); - fprintf(stderr, "chop: eve_d: %" PRIc3_d ", dun_d: %" PRIc3_d "\r\n", u3A->eve_d, log_u->dun_d); - exit(1); - } - // get latest epoch number prior to creating a new one c3_d pre_d; if ( c3n == u3_disk_epoc_last(log_u, &pre_d) ) { @@ -2523,7 +2511,6 @@ _cw_chop(c3_i argc, c3_c* argv[]) // cleanup u3_dire_free(ned_u); u3_disk_exit(log_u); - u3m_stop(); // success fprintf(stderr, "chop: event log truncation complete\r\n"); @@ -2580,11 +2567,9 @@ _cw_roll(c3_i argc, c3_c* argv[]) } // gracefully shutdown the pier if it's running + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); - // note: this includes patch applications (if any) - u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); - // check if there's a *current* snapshot if ( log_u->dun_d != u3A->eve_d ) { fprintf(stderr, "roll: error: snapshot is out of date, please " From 5e3f25358bad01beb63f50bf5aaca5d02c3bd403 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Sun, 2 Jul 2023 07:57:06 -0400 Subject: [PATCH 49/87] cli: fix `play` boot --- pkg/vere/main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 2291ed3b4f..fd7f6703d4 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -342,7 +342,7 @@ _main_getopt(c3_i argc, c3_c** argv) return c3n; } else { u3_Host.ops_u.sap_w = arg_w * 60; - if ( 0 == u3_Host.ops_u.sap_w) + if ( 0 == u3_Host.ops_u.sap_w ) return c3n; } break; @@ -1197,7 +1197,7 @@ _cw_disk_init(c3_c* dir_c) u3_disk* log_u = u3_disk_init(dir_c, cb_u); if ( !log_u ) { - fprintf(stderr, "unable to open event log\n");; + fprintf(stderr, "unable to open event log\n"); exit(1); } @@ -1924,12 +1924,12 @@ _cw_meld(c3_i argc, c3_c* argv[]) exit(1); } + u3C.wag_w |= u3o_hashless; + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock c3_w pre_w; - u3C.wag_w |= u3o_hashless; - pre_w = u3a_open(u3R); u3u_meld(); u3a_print_memory(stderr, "urbit: meld: gained", u3u_meld()); @@ -2245,7 +2245,6 @@ _cw_play(c3_i argc, c3_c* argv[]) // XX handle SIGTSTP so that the lockfile is not orphaned? // - u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock // Handle SIGTSTP as if it was SIGINT. @@ -2269,6 +2268,8 @@ _cw_play(c3_i argc, c3_c* argv[]) _cw_play_snap(log_u); } + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + u3C.slog_f = _cw_play_slog; { From 1140c4e0da4fff6c13ec3a83c1b28342c092d175 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 5 Jul 2023 14:55:42 -0400 Subject: [PATCH 50/87] play: support full replay of unmigrated piers without valid snapshot --- pkg/vere/disk.c | 20 ++++++++++++++++---- pkg/vere/main.c | 14 +++++++++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 2085262bd7..56f9a81a30 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1043,11 +1043,23 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } - // migrate to the correct disk format if necessary + // try migrating the disk format if ( c3n == u3_disk_migrate(log_u) ) { - fprintf(stderr, "disk: failed to migrate to v%d\r\n", U3D_VER1); - c3_free(log_u); - return 0; + fprintf(stderr, "disk: loading old format\r\n"); + + if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { + fprintf(stderr, "disk: failed to initialize lmdb\r\n"); + c3_free(log_u); + } + + c3_d fir_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { + fprintf(stderr, "disk: failed to load latest event from lmdb\r\n"); + c3_free(log_u); + return 0; + } + + return log_u; } // get latest epoch number diff --git a/pkg/vere/main.c b/pkg/vere/main.c index fd7f6703d4..36cdd6c456 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -1924,12 +1924,12 @@ _cw_meld(c3_i argc, c3_c* argv[]) exit(1); } - u3C.wag_w |= u3o_hashless; - u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock c3_w pre_w; + u3C.wag_w |= u3o_hashless; + pre_w = u3a_open(u3R); u3u_meld(); u3a_print_memory(stderr, "urbit: meld: gained", u3u_meld()); @@ -2245,7 +2245,11 @@ _cw_play(c3_i argc, c3_c* argv[]) // XX handle SIGTSTP so that the lockfile is not orphaned? // - u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock + u3_disk* log_u; + if ( 0 == (log_u = _cw_disk_init(u3_Host.dir_c)) ) { + fprintf(stderr, "mars: failed to load event log\r\n"); + exit(1); + } // Handle SIGTSTP as if it was SIGINT. // @@ -2281,6 +2285,10 @@ _cw_play(c3_i argc, c3_c* argv[]) }; u3_mars_play(&mar_u, eve_d, sap_d); + + // migrate after replay, if necessary + u3_Host.eve_d = mar_u.dun_d; + u3_disk_migrate(log_u); } u3_disk_exit(log_u); From fcd9bcc74c59a8d2f0c6762ed4be24dab12e9757 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 6 Jul 2023 17:09:42 -0400 Subject: [PATCH 51/87] always replay synchronously on restart --- pkg/vere/disk.c | 71 +++++++++++++++++++---------- pkg/vere/main.c | 119 +++++++++++++++++++++++++++--------------------- pkg/vere/pier.c | 2 +- pkg/vere/vere.h | 8 +++- 4 files changed, 120 insertions(+), 80 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 56f9a81a30..cc07da2827 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -975,7 +975,7 @@ u3_disk_slog(u3_disk* log_u) /* u3_disk_init(): load or create pier directories and event log. */ u3_disk* -u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) +u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) { u3_disk* log_u = c3_calloc(sizeof(*log_u)); log_u->liv_o = c3n; @@ -1043,23 +1043,33 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } - // try migrating the disk format - if ( c3n == u3_disk_migrate(log_u) ) { - fprintf(stderr, "disk: loading old format\r\n"); - - if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { - fprintf(stderr, "disk: failed to initialize lmdb\r\n"); - c3_free(log_u); + if ( c3y == u3_disk_need_migrate(log_u) ) { + if ( c3y == mig_o ) { + if ( c3n == u3_disk_migrate(log_u) ) { + fprintf(stderr, "disk: failed to migrate log\r\n"); + c3_free(log_u); + return 0; + } } + else { + fprintf(stderr, "disk: loading old format\r\n"); - c3_d fir_d; - if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { - fprintf(stderr, "disk: failed to load latest event from lmdb\r\n"); - c3_free(log_u); - return 0; - } + if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { + fprintf(stderr, "disk: failed to initialize lmdb\r\n"); + c3_free(log_u); + } - return log_u; + c3_d fir_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { + fprintf(stderr, "disk: failed to load latest event from lmdb\r\n"); + c3_free(log_u); + return 0; + } + + log_u->sen_d = log_u->dun_d; + + return log_u; + } } // get latest epoch number @@ -1291,9 +1301,27 @@ u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) return c3y; } +/* u3_disk_need_migrate: does the desk need to be migrated? +*/ +c3_o +u3_disk_need_migrate(u3_disk* log_u) +{ + // check if data.mdb is readable in log directory + c3_c dut_c[8193]; + snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); + if ( !_(u3_Host.ops_u.nuu) + && 0 != access(dut_c, R_OK) ) { + // if .urb/log/data.mdb is not readable, skip migration + return c3n; + } + + return c3y; +} + /* u3_disk_migrate: migrates disk format. */ -c3_o u3_disk_migrate(u3_disk* log_u) +c3_o +u3_disk_migrate(u3_disk* log_u) { /* migration steps: * 0. detect whether we need to migrate or not @@ -1315,14 +1343,6 @@ c3_o u3_disk_migrate(u3_disk* log_u) * 5. delete old data.mdb and lock.mdb files (c3_unlink() calls) */ - // check if data.mdb is readable in log directory - c3_c dut_c[8193]; - snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); - if ( !_(u3_Host.ops_u.nuu) - && 0 != access(dut_c, R_OK) ) { - // if .urb/log/data.mdb is not readable, skip migration - return c3y; - } // check if lock.mdb is readable in log directory c3_o luk_o = c3n; @@ -1378,8 +1398,9 @@ c3_o u3_disk_migrate(u3_disk* log_u) } // create hard links to data.mdb and lock.mdb in 0i0/ - c3_c epo_c[8193], dat_c[8193], lok_c[8193]; + c3_c epo_c[8193], dut_c[8193], dat_c[8193], lok_c[8193]; snprintf(epo_c, sizeof(epo_c), "%s/0i0", log_u->com_u->pax_c); + snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); snprintf(lok_c, sizeof(lok_c), "%s/lock.mdb", epo_c); diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 36cdd6c456..abda7a5f14 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -1194,7 +1194,7 @@ static u3_disk* _cw_disk_init(c3_c* dir_c) { u3_disk_cb cb_u = {0}; - u3_disk* log_u = u3_disk_init(dir_c, cb_u); + u3_disk* log_u = u3_disk_init(dir_c, cb_u, c3y); if ( !log_u ) { fprintf(stderr, "unable to open event log\n"); @@ -2151,6 +2151,69 @@ _cw_play_exit(c3_i int_i) raise(SIGINT); } +/* _cw_play_impl(): replay events, but better. +*/ +static void +_cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) +{ + // XX factor this into its own function for calling here and + // from main() (urbit play and boot replay) + + // XX handle SIGTSTP so that the lockfile is not orphaned? + // + u3_disk* log_u; + if ( 0 == (log_u = u3_disk_init(u3_Host.dir_c, (u3_disk_cb){0}, c3n)) ) { + fprintf(stderr, "mars: failed to load event log\r\n"); + exit(1); + } + + // Handle SIGTSTP as if it was SIGINT. + // + // Configured here using signal() so as to be immediately available. + // + signal(SIGTSTP, _cw_play_exit); + + // XX source these from a shared struct ops_u + if ( c3y == mel_o ) { + u3C.wag_w |= u3o_auto_meld; + } + + if ( c3y == sof_o ) { + u3C.wag_w |= u3o_soft_mugs; + } + + u3C.wag_w |= u3o_hashless; + + if ( c3y == ful_o ) { + u3l_log("mars: preparing for full replay"); + _cw_play_snap(log_u); + } + + u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + + u3C.slog_f = _cw_play_slog; + + { + u3_mars mar_u = { + .log_u = log_u, + .dir_c = u3_Host.dir_c, + .sen_d = u3A->eve_d, + .dun_d = u3A->eve_d, + }; + + u3_mars_play(&mar_u, eve_d, sap_d); + + // migrate after replay, if necessary + u3_Host.eve_d = mar_u.dun_d; + if ( c3y == u3_disk_need_migrate(log_u) ) { + u3_disk_migrate(log_u); + } + } + + u3_disk_exit(log_u); + u3m_stop(); +} + /* _cw_play(): replay events, but better. */ static void @@ -2243,56 +2306,7 @@ _cw_play(c3_i argc, c3_c* argv[]) exit(1); } - // XX handle SIGTSTP so that the lockfile is not orphaned? - // - u3_disk* log_u; - if ( 0 == (log_u = _cw_disk_init(u3_Host.dir_c)) ) { - fprintf(stderr, "mars: failed to load event log\r\n"); - exit(1); - } - - // Handle SIGTSTP as if it was SIGINT. - // - // Configured here using signal() so as to be immediately available. - // - signal(SIGTSTP, _cw_play_exit); - - if ( c3y == mel_o ) { - u3C.wag_w |= u3o_auto_meld; - } - - if ( c3y == sof_o ) { - u3C.wag_w |= u3o_soft_mugs; - } - - u3C.wag_w |= u3o_hashless; - - if ( c3y == ful_o ) { - u3l_log("mars: preparing for full replay"); - _cw_play_snap(log_u); - } - - u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); - - u3C.slog_f = _cw_play_slog; - - { - u3_mars mar_u = { - .log_u = log_u, - .dir_c = u3_Host.dir_c, - .sen_d = u3A->eve_d, - .dun_d = u3A->eve_d, - }; - - u3_mars_play(&mar_u, eve_d, sap_d); - - // migrate after replay, if necessary - u3_Host.eve_d = mar_u.dun_d; - u3_disk_migrate(log_u); - } - - u3_disk_exit(log_u); - u3m_stop(); + _cw_play_impl(eve_d, sap_d, mel_o, sof_o, ful_o); } /* _cw_prep(): prepare for upgrade @@ -3085,8 +3099,7 @@ main(c3_i argc, // we need the current snapshot's latest event number to // validate whether we can execute disk migration if ( u3_Host.ops_u.nuu == c3n ) { - u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); - u3m_stop(); + _cw_play_impl(0, 0, c3n, c3n, c3n); // XX unmap loom, else parts of the snapshot could be left in memory } diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index c2e7c47026..81e744e4f7 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -1643,7 +1643,7 @@ _pier_init(c3_w wag_w, c3_c* pax_c) .write_bail_f = _pier_on_disk_write_bail }; - if ( !(pir_u->log_u = u3_disk_init(pax_c, cb_u)) ) { + if ( !(pir_u->log_u = u3_disk_init(pax_c, cb_u, c3n)) ) { c3_free(pir_u); return 0; } diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index c72417f86d..9cb9e88d8b 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -8,6 +8,7 @@ #include "noun.h" #include "serf.h" #include "uv.h" +#include /** Quasi-tunable parameters. **/ @@ -935,7 +936,7 @@ /* u3_disk_init(): load or create pier directories and event log. */ u3_disk* - u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u); + u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o); /* u3_disk_etch(): serialize an event for persistence. RETAIN [eve] */ @@ -1030,6 +1031,11 @@ c3_o u3_disk_vere_diff(u3_disk* log_u); + /* u3_disk_need_migrate(): does the disk need migration? + */ + c3_o + u3_disk_need_migrate(u3_disk* log_u); + /* u3_disk_migrate(): migrates disk format. */ c3_o From f229c4db9542fc104c3ff527add24a8ac0031fe0 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Thu, 6 Jul 2023 17:13:16 -0400 Subject: [PATCH 52/87] deprecated async replay codepath --- pkg/vere/pier.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 81e744e4f7..44e9ee4d35 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -1408,6 +1408,8 @@ _pier_on_lord_live(void* ptr_v) // XX print bootstrap commit complete // XX s/b boot_complete_cb // + // XX this codepath should never be hit due to sync replay + u3l_log("pier: warning: async replay"); _pier_play_init(pir_u, log_u->dun_d); } } From 3c8c0b219d3d926a32480149acdf37c8950e9406 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 12 Jul 2023 12:05:50 -0400 Subject: [PATCH 53/87] disk: fix migrate scenarios --- pkg/vere/disk.c | 4 ++-- pkg/vere/main.c | 3 --- pkg/vere/pier.c | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index cc07da2827..f87ce92154 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1310,8 +1310,8 @@ u3_disk_need_migrate(u3_disk* log_u) c3_c dut_c[8193]; snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); if ( !_(u3_Host.ops_u.nuu) - && 0 != access(dut_c, R_OK) ) { - // if .urb/log/data.mdb is not readable, skip migration + && 0 != access(dut_c, F_OK) ) { + // if .urb/log/data.mdb does not exist, skip migration return c3n; } diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 5cc44e0cfa..b09ccdd346 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2153,9 +2153,6 @@ _cw_play_exit(c3_i int_i) static void _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) { - // XX factor this into its own function for calling here and - // from main() (urbit play and boot replay) - // XX handle SIGTSTP so that the lockfile is not orphaned? // u3_disk* log_u; diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 44e9ee4d35..830a2c1e49 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -1645,7 +1645,7 @@ _pier_init(c3_w wag_w, c3_c* pax_c) .write_bail_f = _pier_on_disk_write_bail }; - if ( !(pir_u->log_u = u3_disk_init(pax_c, cb_u, c3n)) ) { + if ( !(pir_u->log_u = u3_disk_init(pax_c, cb_u, c3y)) ) { c3_free(pir_u); return 0; } From 1556567b3333b3af4847753d239e0662e06f5c39 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 18 Jul 2023 12:03:44 -0400 Subject: [PATCH 54/87] disk/events: simplify code --- pkg/noun/events.c | 8 ++++---- pkg/vere/disk.c | 10 ++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 8b8d98993e..0294f522ab 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1344,12 +1344,12 @@ c3_o u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) { // source image files from [pux_c] - u3e_image nux_u = { .nam_c = "north" }; - u3e_image sux_u = { .nam_c = "south" }; + u3e_image nux_u = { .nam_c = "north", .pgs_w = 0 }; + u3e_image sux_u = { .nam_c = "south", .pgs_w = 0 }; // destination image files to [pax_c] - u3e_image nax_u = { .nam_c = "north" }; - u3e_image sax_u = { .nam_c = "south" }; + u3e_image nax_u = { .nam_c = "north", .pgs_w = 0 }; + u3e_image sax_u = { .nam_c = "south", .pgs_w = 0 }; c3_i mod_i = O_RDWR | O_CREAT; diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index f87ce92154..e506b71153 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1044,12 +1044,10 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) } if ( c3y == u3_disk_need_migrate(log_u) ) { - if ( c3y == mig_o ) { - if ( c3n == u3_disk_migrate(log_u) ) { - fprintf(stderr, "disk: failed to migrate log\r\n"); - c3_free(log_u); - return 0; - } + if ( (c3y == mig_o) && (c3n == u3_disk_migrate(log_u)) ) { + fprintf(stderr, "disk: failed to migrate log\r\n"); + c3_free(log_u); + return 0; } else { fprintf(stderr, "disk: loading old format\r\n"); From f9a2d315c3354ca25d02493f48f5d67feed5d1ad Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 26 Jul 2023 10:20:09 -0400 Subject: [PATCH 55/87] disk: add "migration starting" printf --- pkg/vere/disk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index e506b71153..f24c11e11b 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1341,6 +1341,7 @@ u3_disk_migrate(u3_disk* log_u) * 5. delete old data.mdb and lock.mdb files (c3_unlink() calls) */ + fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); // check if lock.mdb is readable in log directory c3_o luk_o = c3n; From ea6f278bdf02b60d795489be04f35d471181769d Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Wed, 16 Aug 2023 08:40:56 -0600 Subject: [PATCH 56/87] disk: move `u3C.wag_w` assignment before boot call --- pkg/vere/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/vere/main.c b/pkg/vere/main.c index b09ccdd346..cca3081a9b 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -1924,11 +1924,11 @@ _cw_meld(c3_i argc, c3_c* argv[]) exit(1); } + u3C.wag_w |= u3o_hashless; + u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock - u3C.wag_w |= u3o_hashless; - u3a_print_memory(stderr, "urbit: meld: gained", u3u_meld()); u3m_save(); From 1221b6a3cbb56694966ff5fe74d39045777f3596 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Sat, 19 Aug 2023 18:20:13 -0400 Subject: [PATCH 57/87] build: upgrade `zlib` to v1.3 --- WORKSPACE.bazel | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index 56a347ed6d..2cad948ace 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -358,10 +358,10 @@ versioned_http_archive( versioned_http_archive( name = "zlib", build_file = "//bazel/third_party/zlib:zlib.BUILD", - sha256 = "b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30", + sha256 = "ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e", strip_prefix = "zlib-{version}", url = "https://www.zlib.net/zlib-{version}.tar.gz", - version = "1.2.13", + version = "1.3", ) # From 53a4664b75e7eb8390e0f2287e641ef3795f4050 Mon Sep 17 00:00:00 2001 From: Midlyx Hatrys Date: Fri, 5 May 2023 13:08:49 +0300 Subject: [PATCH 58/87] flake: update Otherwise devenv fails to work on newer NixOS'es, looks like because th glibc is too old. --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 12ffaf6f77..45c4d968fb 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1677383253, - "narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=", + "lastModified": 1683236849, + "narHash": "sha256-Y7PNBVLOBvZrmrFmHgXUBUA1lM72tl6JGIn1trOeuyE=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9952d6bc395f5841262b006fbace8dd7e143b634", + "rev": "374ffe54403c3c42d97a513ac7a14ce1b5b86e30", "type": "github" }, "original": { @@ -23,11 +23,11 @@ ] }, "locked": { - "lastModified": 1675933616, - "narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=", + "lastModified": 1682984683, + "narHash": "sha256-fSMthG+tp60AHhNmaHc4StT3ltfHkQsJtN8GhfLWmtI=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "47478a4a003e745402acf63be7f9a092d51b83d7", + "rev": "86684881e184f41aa322e653880e497b66429f3e", "type": "github" }, "original": { From 28f18498129173196158c18463e9320b71f2d36c Mon Sep 17 00:00:00 2001 From: Pyry Kovanen Date: Mon, 18 Sep 2023 17:00:34 +0300 Subject: [PATCH 59/87] Update VERSION to 3.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3e162f02ea..9f55b2ccb5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.12 +3.0 From d5dd64807c85f9d2f0a7cd217acf21b7f2aa6a26 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 22 Sep 2023 14:48:13 -0400 Subject: [PATCH 60/87] vere: support stack traces on failing boot / full replay --- pkg/noun/vortex.c | 7 +------ pkg/vere/mars.c | 25 +++++++++++++++++++++++++ pkg/vere/serf.c | 25 ++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/pkg/noun/vortex.c b/pkg/noun/vortex.c index 5981068b87..0bb9af8c29 100644 --- a/pkg/noun/vortex.c +++ b/pkg/noun/vortex.c @@ -39,18 +39,12 @@ c3_o u3v_boot(u3_noun eve) { c3_d len_d; - { u3_noun len = u3qb_lent(eve); u3_assert( c3y == u3r_safe_chub(len, &len_d) ); u3z(len); } - // ensure zero-initialized kernel - // - u3A->roc = 0; - u3A->eve_d = 0; - { u3_noun pro = u3m_soft(0, u3v_life, eve); @@ -59,6 +53,7 @@ u3v_boot(u3_noun eve) return c3n; } + u3z(u3A->roc); u3A->roc = u3k(u3t(pro)); u3A->eve_d = len_d; u3z(pro); diff --git a/pkg/vere/mars.c b/pkg/vere/mars.c index 37933bd49e..4751391bd9 100644 --- a/pkg/vere/mars.c +++ b/pkg/vere/mars.c @@ -6,6 +6,8 @@ #include "noun.h" #include "types.h" #include "vere.h" +#include "ivory.h" +#include "ur.h" #include "db/lmdb.h" #include #include @@ -179,6 +181,29 @@ _mars_do_boot(u3_disk* log_u, c3_d eve_d) // eve = u3m_love(u3ke_cue(u3ke_jam(eve))); + // install an ivory pill to support stack traces + // + // XX support -J + // + { + c3_d len_d = u3_Ivory_pill_len; + c3_y* byt_y = u3_Ivory_pill; + u3_cue_xeno* sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28); + u3_weak pil; + + if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) { + u3l_log("lite: unable to cue ivory pill"); + exit(1); + } + + u3s_cue_xeno_done(sil_u); + + if ( c3n == u3v_boot_lite(pil)) { + u3l_log("lite: boot failed"); + exit(1); + } + } + u3l_log("--------------- bootstrap starting ----------------"); u3l_log("boot: 1-%u", u3qb_lent(eve)); diff --git a/pkg/vere/serf.c b/pkg/vere/serf.c index 3a59005e00..cfbbc47be3 100644 --- a/pkg/vere/serf.c +++ b/pkg/vere/serf.c @@ -3,6 +3,8 @@ #include "noun.h" #include "vere.h" +#include "ivory.h" +#include "ur.h" /* |% @@ -538,11 +540,28 @@ _serf_play_life(u3_serf* sef_u, u3_noun eve) u3z(len); } - // ensure zero-initialized kernel + // install an ivory pill to support stack traces // - // XX assert? + // XX support -J // - u3A->roc = 0; + { + c3_d len_d = u3_Ivory_pill_len; + c3_y* byt_y = u3_Ivory_pill; + u3_cue_xeno* sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28); + u3_weak pil; + + if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) { + u3l_log("lite: unable to cue ivory pill"); + exit(1); + } + + u3s_cue_xeno_done(sil_u); + + if ( c3n == u3v_boot_lite(pil)) { + u3l_log("lite: boot failed"); + exit(1); + } + } gon = u3m_soft(0, u3v_life, eve); From 56fce75730a71a98f24bcc039934c9d32185e76b Mon Sep 17 00:00:00 2001 From: Amadeo Bellotti Date: Fri, 29 Sep 2023 10:52:36 -0400 Subject: [PATCH 61/87] fixed next/kelvin workflow to not upload to docker --- .github/workflows/next.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/next.yml b/.github/workflows/next.yml index e0dd8feeec..07250449e3 100644 --- a/.github/workflows/next.yml +++ b/.github/workflows/next.yml @@ -20,7 +20,3 @@ jobs: upload: true next: ${{ github.ref_name }} secrets: inherit - - docker: - uses: ./.github/workflows/docker-shared.yml - secrets: inherit From d27bfc114e58356433562ede352ba892e06fa721 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 2 Oct 2023 13:48:41 -0400 Subject: [PATCH 62/87] u3: fix warnings --- pkg/noun/trace.c | 2 +- pkg/noun/trace.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/noun/trace.c b/pkg/noun/trace.c index 8768531d62..fd33169e8d 100644 --- a/pkg/noun/trace.c +++ b/pkg/noun/trace.c @@ -299,7 +299,7 @@ u3t_flee(void) /* u3t_trace_open(): opens a trace file and writes the preamble. */ void -u3t_trace_open(c3_c* dir_c) +u3t_trace_open(const c3_c* dir_c) { c3_c fil_c[2048]; diff --git a/pkg/noun/trace.h b/pkg/noun/trace.h index 667cdfae4b..695a5fe133 100644 --- a/pkg/noun/trace.h +++ b/pkg/noun/trace.h @@ -103,7 +103,7 @@ /* u3t_trace_open(): opens the path for writing tracing information. */ void - u3t_trace_open(c3_c *dir_c); + u3t_trace_open(const c3_c *dir_c); /* u3t_trace_close(): closes the trace file. optional. */ From fa949077fe16c6690dc60bb4e96d537e56de7788 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 2 Oct 2023 13:49:43 -0400 Subject: [PATCH 63/87] mars: move replay no-op printf --- pkg/vere/main.c | 12 +++++++++--- pkg/vere/mars.c | 12 ++++++++---- pkg/vere/mars.h | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/pkg/vere/main.c b/pkg/vere/main.c index cca3081a9b..0590598414 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2150,9 +2150,11 @@ _cw_play_exit(c3_i int_i) /* _cw_play_impl(): replay events, but better. */ -static void +static c3_d _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) { + c3_d pay_d; + // XX handle SIGTSTP so that the lockfile is not orphaned? // u3_disk* log_u; @@ -2195,7 +2197,7 @@ _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) .dun_d = u3A->eve_d, }; - u3_mars_play(&mar_u, eve_d, sap_d); + pay_d = u3_mars_play(&mar_u, eve_d, sap_d); // migrate after replay, if necessary u3_Host.eve_d = mar_u.dun_d; @@ -2206,6 +2208,8 @@ _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) u3_disk_exit(log_u); u3m_stop(); + + return pay_d; } /* _cw_play(): replay events, but better. @@ -2300,7 +2304,9 @@ _cw_play(c3_i argc, c3_c* argv[]) exit(1); } - _cw_play_impl(eve_d, sap_d, mel_o, sof_o, ful_o); + if ( !_cw_play_impl(eve_d, sap_d, mel_o, sof_o, ful_o) ) { + fprintf(stderr, "mars: nothing to do!"); + } } /* _cw_prep(): prepare for upgrade diff --git a/pkg/vere/mars.c b/pkg/vere/mars.c index 37933bd49e..7c33e6fee9 100644 --- a/pkg/vere/mars.c +++ b/pkg/vere/mars.c @@ -195,10 +195,11 @@ _mars_do_boot(u3_disk* log_u, c3_d eve_d) /* u3_mars_play(): replay up to [eve_d], snapshot every [sap_d]. */ -void +c3_d u3_mars_play(u3_mars* mar_u, c3_d eve_d, c3_d sap_d) { u3_disk* log_u = mar_u->log_u; + c3_d pay_d = 0; if ( !eve_d ) { eve_d = log_u->dun_d; @@ -207,17 +208,18 @@ u3_mars_play(u3_mars* mar_u, c3_d eve_d, c3_d sap_d) u3l_log("mars: already computed %" PRIu64 "", eve_d); u3l_log(" state=%" PRIu64 ", log=%" PRIu64 "", mar_u->dun_d, log_u->dun_d); - return; + return pay_d; } else { eve_d = c3_min(eve_d, log_u->dun_d); } if ( mar_u->dun_d == log_u->dun_d ) { - u3l_log("mars: nothing to do!"); - return; + return pay_d; } + pay_d = eve_d - mar_u->dun_d; + if ( !mar_u->dun_d ) { c3_w lif_w; @@ -351,4 +353,6 @@ u3_mars_play(u3_mars* mar_u, c3_d eve_d, c3_d sap_d) u3l_log("---------------- playback complete ----------------"); u3m_save(); + + return pay_d; } diff --git a/pkg/vere/mars.h b/pkg/vere/mars.h index ba97f63614..552f1a9dea 100644 --- a/pkg/vere/mars.h +++ b/pkg/vere/mars.h @@ -15,7 +15,7 @@ /* u3_mars_play(): replay up to [eve_d], snapshot every [sap_d]. */ - void + c3_d u3_mars_play(u3_mars* mar_u, c3_d eve_d, c3_d sap_d); #endif /* ifndef U3_VERE_MARS_H */ From bf04ea6397bbbdf035e53f5fef4b37bf2d17156f Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 2 Oct 2023 13:50:53 -0400 Subject: [PATCH 64/87] vere: fix log initialization, remove spurious "migration" on boot --- pkg/vere/disk.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index f24c11e11b..f1f799c2d8 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1043,7 +1043,18 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) return 0; } - if ( c3y == u3_disk_need_migrate(log_u) ) { + + + // if fresh boot, initialize disk v1 + // + if ( c3y == u3_Host.ops_u.nuu ) { + // initialize first epoch "0i0" + if ( c3n == u3_disk_epoc_init(log_u, 0) ) { + fprintf(stderr, "disk: failed to initialize first epoch\r\n"); + return 0; + } + } + else if ( c3y == u3_disk_need_migrate(log_u) ) { if ( (c3y == mig_o) && (c3n == u3_disk_migrate(log_u)) ) { fprintf(stderr, "disk: failed to migrate log\r\n"); c3_free(log_u); @@ -1341,8 +1352,6 @@ u3_disk_migrate(u3_disk* log_u) * 5. delete old data.mdb and lock.mdb files (c3_unlink() calls) */ - fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); - // check if lock.mdb is readable in log directory c3_o luk_o = c3n; c3_c luk_c[8193]; @@ -1351,16 +1360,7 @@ u3_disk_migrate(u3_disk* log_u) luk_o = c3y; } - // if fresh boot, initialize disk v1 - if ( c3y == u3_Host.ops_u.nuu ) { - // initialize first epoch "0i0" - if ( c3n == u3_disk_epoc_init(log_u, 0) ) { - fprintf(stderr, "disk: failed to initialize first epoch\r\n"); - return c3n; - } - - return c3y; - } + fprintf(stderr, "disk: migrating disk to v%d format\r\n", U3D_VER1); // migrate existing pier which has either: // - not started the migration, or From fbf2492d85225e4d903303e618b77e6ab2e5c4e1 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 18:36:58 -0400 Subject: [PATCH 65/87] vere: fixes epoch runtime-version handling --- pkg/vere/disk.c | 115 +++++++++++++++++++++++++----------------------- pkg/vere/vere.h | 5 --- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index f1f799c2d8..7c2d82f313 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -972,6 +972,59 @@ u3_disk_slog(u3_disk* log_u) } } +/* _disk_epoc_meta: read metadata from epoch. +*/ +static c3_o +_disk_epoc_meta(u3_disk* log_u, + c3_d epo_d, + const c3_c* met_c, + c3_w max_w, + c3_c* buf_c) +{ + struct stat buf_u; + c3_w red_w, len_w; + c3_i ret_i, fid_i; + c3_c* pat_c; + + ret_i = asprintf(&pat_c, "%s/0i%" PRIc3_d "/%s.txt", + log_u->com_u->pax_c, epo_d, met_c); + u3_assert( ret_i > 0 ); + + fid_i = c3_open(pat_c, O_RDONLY, 0644); + c3_free(pat_c); + + if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) { + fprintf(stderr, "disk: failed to open %s.txt in epoch 0i%" PRIc3_d "\r\n", + met_c, epo_d); + return c3n; + } + else if ( buf_u.st_size >= max_w ) { + fprintf(stderr, "disk: %s.txt in epoch 0i%" PRIc3_d " too large " + "(%" PRIc3_z ")\r\n", + met_c, epo_d, (c3_z)buf_u.st_size); + return c3n; + } + + len_w = buf_u.st_size; + red_w = read(fid_i, buf_c, len_w); + close(fid_i); + + if ( len_w != red_w ) { + fprintf(stderr, "disk: failed to read %s.txt in epoch 0i%" PRIc3_d "\r\n", + met_c, epo_d); + return c3n; + } + + // trim trailing whitespace + // + do { + buf_c[len_w] = 0; + } + while ( len_w-- && isspace(buf_c[len_w]) ); + + return c3y; +} + /* u3_disk_init(): load or create pier directories and event log. */ u3_disk* @@ -1043,8 +1096,6 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) return 0; } - - // if fresh boot, initialize disk v1 // if ( c3y == u3_Host.ops_u.nuu ) { @@ -1270,46 +1321,6 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) return ret_o; } -/* u3_disk_epoc_vere: get binary version from epoch. -*/ -c3_o -u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w) -{ - struct stat buf_u; - c3_c* ver_c; - c3_w red_w, len_w; - c3_i ret_i, fid_i; - ret_i = asprintf(&ver_c, "%s/0i%" PRIc3_d "/vere.txt", - log_u->com_u->pax_c, epo_d); - u3_assert( ret_i > 0 ); - - fid_i = c3_open(ver_c, O_RDONLY, 0644); - - if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) { - fprintf(stderr, "disk: failed to open vere.txt in epoch 0i%" PRIc3_d - "\r\n", epo_d); - return c3n; - } - - len_w = buf_u.st_size; - red_w = read(fid_i, ver_w, len_w); - close(fid_i); - - if ( len_w != red_w ) { - fprintf(stderr, "disk: failed to read vere.txt in epoch 0i%" PRIc3_d - "\r\n", epo_d); - return c3n; - } - - // trim trailing whitespace - ver_w[len_w] = 0; - while ( len_w-- && isspace(ver_w[len_w]) ) { - ver_w[len_w] = 0; - } - - return c3y; -} - /* u3_disk_need_migrate: does the desk need to be migrated? */ c3_o @@ -1452,28 +1463,22 @@ u3_disk_migrate(u3_disk* log_u) return c3y; } - /* u3_disk_vere_diff(): checks if vere version mismatches latest epoch's. */ c3_o u3_disk_vere_diff(u3_disk* log_u) { - c3_d lat_d; - if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { - fprintf(stderr, "disk: failed to load last epoch\r\n"); - c3_free(log_u); - return 0; - } + c3_c ver_c[128]; - c3_c ver_c[8193]; - if ( c3n == u3_disk_epoc_vere(log_u, lat_d, ver_c) ) { - fprintf(stderr, "disk: failed to load epoch version\r\n"); - c3_free(log_u); - return 0; + if ( c3n == _disk_epoc_meta(log_u, log_u->epo_d, "vere", + sizeof(ver_c) - 1, ver_c) ) + { + return c3y; // assume mismatch if we can't read version } + if ( 0 != strcmp(ver_c, URBIT_VERSION) ) { return c3y; } return c3n; -} \ No newline at end of file +} diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index cc3d71f6ed..d242ccd21a 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -1021,11 +1021,6 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d); - /* u3_disk_epoc_vere(): get binary version from epoch. - */ - c3_o - u3_disk_epoc_vere(u3_disk* log_u, c3_d epo_d, c3_c* ver_w); - /* u3_disk_vere_diff(): checks if vere version mismatches latest epoch's. */ c3_o From 1c208c703a4dbe4650d86c71d4262b876b88794c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 19:53:59 -0400 Subject: [PATCH 66/87] vere: check epoch version on init --- pkg/vere/disk.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 7c2d82f313..654dadba51 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1122,6 +1122,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) c3_d fir_d; if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { fprintf(stderr, "disk: failed to load latest event from lmdb\r\n"); + // XX dispose mdb_u c3_free(log_u); return 0; } @@ -1140,13 +1141,40 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) return 0; } + // check latest epoc version + // + { + c3_c ver_c[8]; + c3_w ver_w; + if ( c3n == _disk_epoc_meta(log_u, lat_d, "epoc", + sizeof(ver_c) - 1, ver_c) ) + { + fprintf(stderr, "disk: failed to load epoch version\r\n"); + c3_free(log_u); + return 0; + } + + if ( 1 != sscanf(ver_c, "%d", &ver_w) ) { + fprintf(stderr, "disk: failed to parse epoch version: '%s'\r\n", ver_c); + c3_free(log_u); + return 0; + } + + if ( U3D_VER1 != ver_w ) { + fprintf(stderr, "disk: unknown epoch version: '%s', expected '%d'\r\n", + ver_c, U3D_VER1); + c3_free(log_u); + return 0; + } + } + // set path to latest epoch c3_c epo_c[8193]; snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_c, lat_d); // initialize latest epoch's db if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { - fprintf(stderr, "disk: failed to initialize database\r\n"); + fprintf(stderr, "disk: failed to initialize database at '%s' '%s' '%s'\r\n", pax_c, log_c, epo_c); c3_free(log_u); return 0; } @@ -1156,6 +1184,8 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) c3_d fir_d, las_d; if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); + // XX dispose mdb_u + c3_free(log_u); return 0; } @@ -1200,7 +1230,7 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) c3_c epv_c[8193]; snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); FILE* epv_f = fopen(epv_c, "w"); - fprintf(epv_f, "%d\n", U3D_VER1); + fprintf(epv_f, "%d", U3D_VER1); fclose(epv_f); // create binary version file, overwriting any existing file From 2abe6e487cb8387cd68b6b827182917023b9075b Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 21:53:08 -0400 Subject: [PATCH 67/87] vere: centralizes auto migration/rollover after replay --- pkg/vere/main.c | 12 ++++++++++-- pkg/vere/pier.c | 8 -------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 0590598414..7f200a8aa4 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2185,6 +2185,9 @@ _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) _cw_play_snap(log_u); } + // XX this should check that snapshot is within epoc, + // and load from the epoc / reboot if it is not + // u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3C.slog_f = _cw_play_slog; @@ -2198,12 +2201,17 @@ _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) }; pay_d = u3_mars_play(&mar_u, eve_d, sap_d); - - // migrate after replay, if necessary u3_Host.eve_d = mar_u.dun_d; + if ( c3y == u3_disk_need_migrate(log_u) ) { u3_disk_migrate(log_u); } + else if ( c3y == u3_disk_vere_diff(log_u) ) { + if ( c3n == u3_disk_epoc_init(log_u, log_u->dun_d) ) { + fprintf(stderr, "disk: failed to initialize epoch\r\n"); + exit(1); + } + } } u3_disk_exit(log_u); diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 970f9b4eb8..465e2da638 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -827,14 +827,6 @@ _pier_wyrd_card(u3_pier* pir_u) static void _pier_wyrd_init(u3_pier* pir_u) { - // create a new epoch if current version mismatches the latest epoch's - if ( c3y == u3_disk_vere_diff(pir_u->log_u) ) { - if ( c3n == u3_disk_epoc_init(pir_u->log_u, pir_u->log_u->dun_d) ) { - fprintf(stderr, "disk: failed to initialize epoch\r\n"); - exit(1); - } - } - u3_noun cad = _pier_wyrd_card(pir_u); u3_noun wir = u3nc(c3__arvo, u3_nul); From 529874a9b0ce33d448eb1502106d0f67546ec6de Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 22:00:04 -0400 Subject: [PATCH 68/87] vere: removes auto-migration from u3_disk_init() --- pkg/vere/disk.c | 38 +++++++++++++++++--------------------- pkg/vere/main.c | 8 ++------ pkg/vere/pier.c | 4 +++- pkg/vere/vere.h | 3 ++- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 654dadba51..c0d689d720 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1028,7 +1028,7 @@ _disk_epoc_meta(u3_disk* log_u, /* u3_disk_init(): load or create pier directories and event log. */ u3_disk* -u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) +u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) { u3_disk* log_u = c3_calloc(sizeof(*log_u)); log_u->liv_o = c3n; @@ -1106,31 +1106,25 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) } } else if ( c3y == u3_disk_need_migrate(log_u) ) { - if ( (c3y == mig_o) && (c3n == u3_disk_migrate(log_u)) ) { - fprintf(stderr, "disk: failed to migrate log\r\n"); + fprintf(stderr, "disk: loading old format\r\n"); + + if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { + fprintf(stderr, "disk: failed to initialize lmdb\r\n"); c3_free(log_u); - return 0; } - else { - fprintf(stderr, "disk: loading old format\r\n"); - if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { - fprintf(stderr, "disk: failed to initialize lmdb\r\n"); - c3_free(log_u); - } - - c3_d fir_d; - if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { - fprintf(stderr, "disk: failed to load latest event from lmdb\r\n"); - // XX dispose mdb_u - c3_free(log_u); - return 0; - } + c3_d fir_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { + fprintf(stderr, "disk: failed to load latest event from lmdb\r\n"); + // XX dispose mdb_u + c3_free(log_u); + return 0; + } - log_u->sen_d = log_u->dun_d; + log_u->sen_d = log_u->dun_d; + log_u->ver_w = 0; - return log_u; - } + return log_u; } // get latest epoch number @@ -1166,6 +1160,8 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o) c3_free(log_u); return 0; } + + log_u->ver_w = ver_w; } // set path to latest epoch diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 7f200a8aa4..3b44a6f8f3 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -1194,7 +1194,7 @@ static u3_disk* _cw_disk_init(c3_c* dir_c) { u3_disk_cb cb_u = {0}; - u3_disk* log_u = u3_disk_init(dir_c, cb_u, c3y); + u3_disk* log_u = u3_disk_init(dir_c, cb_u); if ( !log_u ) { fprintf(stderr, "unable to open event log\n"); @@ -2157,11 +2157,7 @@ _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) // XX handle SIGTSTP so that the lockfile is not orphaned? // - u3_disk* log_u; - if ( 0 == (log_u = u3_disk_init(u3_Host.dir_c, (u3_disk_cb){0}, c3n)) ) { - fprintf(stderr, "mars: failed to load event log\r\n"); - exit(1); - } + u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // Handle SIGTSTP as if it was SIGINT. // diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 465e2da638..bba434c4fd 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -1639,10 +1639,12 @@ _pier_init(c3_w wag_w, c3_c* pax_c) .write_bail_f = _pier_on_disk_write_bail }; - if ( !(pir_u->log_u = u3_disk_init(pax_c, cb_u, c3y)) ) { + if ( !(pir_u->log_u = u3_disk_init(pax_c, cb_u)) ) { c3_free(pir_u); return 0; } + + u3_assert( U3D_VER1 == pir_u->log_u->ver_w ); } // initialize compute diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index d242ccd21a..959391e96b 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -541,6 +541,7 @@ u3_dire* urb_u; // urbit system data u3_dire* com_u; // log directory c3_o liv_o; // live + c3_w ver_w; // pier version void* mdb_u; // lmdb env of current epoch c3_d sen_d; // commit requested c3_d dun_d; // committed @@ -936,7 +937,7 @@ /* u3_disk_init(): load or create pier directories and event log. */ u3_disk* - u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u, c3_o mig_o); + u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u); /* u3_disk_etch(): serialize an event for persistence. RETAIN [eve] */ From 222735f2dc055bb8efbe032e022441f4a5094b1b Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 22:10:58 -0400 Subject: [PATCH 69/87] vere: moves auto migration/rollover details inside disk.c --- pkg/vere/disk.c | 399 +++++++++++++++++++++++++----------------------- pkg/vere/main.c | 12 +- pkg/vere/vere.h | 15 +- 3 files changed, 215 insertions(+), 211 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index c0d689d720..65056d71e0 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1025,185 +1025,6 @@ _disk_epoc_meta(u3_disk* log_u, return c3y; } -/* u3_disk_init(): load or create pier directories and event log. -*/ -u3_disk* -u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) -{ - u3_disk* log_u = c3_calloc(sizeof(*log_u)); - log_u->liv_o = c3n; - log_u->ted_o = c3n; - log_u->cb_u = cb_u; - log_u->red_u = 0; - log_u->put_u.ent_u = log_u->put_u.ext_u = 0; - - // create/load pier directory - // - { - if ( 0 == (log_u->dir_u = u3_foil_folder(pax_c)) ) { - fprintf(stderr, "disk: failed to load pier at %s\r\n", pax_c); - c3_free(log_u); - return 0; - } - } - - // acquire lockfile. - // - u3_disk_acquire(pax_c); - - // create/load $pier/.urb - // - { - c3_c* urb_c = c3_malloc(6 + strlen(pax_c)); - - strcpy(urb_c, pax_c); - strcat(urb_c, "/.urb"); - - if ( 0 == (log_u->urb_u = u3_foil_folder(urb_c)) ) { - fprintf(stderr, "disk: failed to load /.urb in %s\r\n", pax_c); - c3_free(urb_c); - c3_free(log_u); - return 0; - } - c3_free(urb_c); - } - - // create/load $pier/.urb/put and $pier/.urb/get - // - { - c3_c* dir_c = c3_malloc(10 + strlen(pax_c)); - - strcpy(dir_c, pax_c); - strcat(dir_c, "/.urb/put"); - c3_mkdir(dir_c, 0700); - - strcpy(dir_c, pax_c); - strcat(dir_c, "/.urb/get"); - c3_mkdir(dir_c, 0700); - - c3_free(dir_c); - } - - // create/load $pier/.urb/log - // - { - c3_c log_c[8193]; - snprintf(log_c, sizeof(log_c), "%s/.urb/log", pax_c); - - if ( 0 == (log_u->com_u = u3_foil_folder(log_c)) ) { - fprintf(stderr, "disk: failed to load /.urb/log in %s\r\n", pax_c); - c3_free(log_u); - return 0; - } - - // if fresh boot, initialize disk v1 - // - if ( c3y == u3_Host.ops_u.nuu ) { - // initialize first epoch "0i0" - if ( c3n == u3_disk_epoc_init(log_u, 0) ) { - fprintf(stderr, "disk: failed to initialize first epoch\r\n"); - return 0; - } - } - else if ( c3y == u3_disk_need_migrate(log_u) ) { - fprintf(stderr, "disk: loading old format\r\n"); - - if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { - fprintf(stderr, "disk: failed to initialize lmdb\r\n"); - c3_free(log_u); - } - - c3_d fir_d; - if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { - fprintf(stderr, "disk: failed to load latest event from lmdb\r\n"); - // XX dispose mdb_u - c3_free(log_u); - return 0; - } - - log_u->sen_d = log_u->dun_d; - log_u->ver_w = 0; - - return log_u; - } - - // get latest epoch number - c3_d lat_d; - if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { - fprintf(stderr, "disk: failed to load epoch number\r\n"); - c3_free(log_u); - return 0; - } - - // check latest epoc version - // - { - c3_c ver_c[8]; - c3_w ver_w; - if ( c3n == _disk_epoc_meta(log_u, lat_d, "epoc", - sizeof(ver_c) - 1, ver_c) ) - { - fprintf(stderr, "disk: failed to load epoch version\r\n"); - c3_free(log_u); - return 0; - } - - if ( 1 != sscanf(ver_c, "%d", &ver_w) ) { - fprintf(stderr, "disk: failed to parse epoch version: '%s'\r\n", ver_c); - c3_free(log_u); - return 0; - } - - if ( U3D_VER1 != ver_w ) { - fprintf(stderr, "disk: unknown epoch version: '%s', expected '%d'\r\n", - ver_c, U3D_VER1); - c3_free(log_u); - return 0; - } - - log_u->ver_w = ver_w; - } - - // set path to latest epoch - c3_c epo_c[8193]; - snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_c, lat_d); - - // initialize latest epoch's db - if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { - fprintf(stderr, "disk: failed to initialize database at '%s' '%s' '%s'\r\n", pax_c, log_c, epo_c); - c3_free(log_u); - return 0; - } - fprintf(stderr, "disk: loaded epoch 0i%" PRIc3_d "\r\n", lat_d); - - // get first/last event numbers from lmdb - c3_d fir_d, las_d; - if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { - fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); - // XX dispose mdb_u - c3_free(log_u); - return 0; - } - - // initialize dun_d/sen_d values - log_u->dun_d = ( 0 != las_d ) ? las_d : lat_d; - log_u->sen_d = log_u->dun_d; - - // mark the latest epoch directory - log_u->epo_d = lat_d; - - // mark the log as live - log_u->liv_o = c3y; - } - - -#if defined(DISK_TRACE_JAM) || defined(DISK_TRACE_CUE) - u3t_trace_open(pax_c); -#endif - - return log_u; -} - /* u3_disk_epoc_init: create new epoch. */ c3_o @@ -1347,10 +1168,10 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) return ret_o; } -/* u3_disk_need_migrate: does the desk need to be migrated? +/* _disk_need_migrate: does the desk need to be migrated? */ -c3_o -u3_disk_need_migrate(u3_disk* log_u) +static c3_o +_disk_need_migrate(u3_disk* log_u) { // check if data.mdb is readable in log directory c3_c dut_c[8193]; @@ -1364,10 +1185,10 @@ u3_disk_need_migrate(u3_disk* log_u) return c3y; } -/* u3_disk_migrate: migrates disk format. +/* _disk_migrate: migrates disk format. */ -c3_o -u3_disk_migrate(u3_disk* log_u) +static c3_o +_disk_migrate(u3_disk* log_u, c3_d eve_d) { /* migration steps: * 0. detect whether we need to migrate or not @@ -1419,11 +1240,11 @@ u3_disk_migrate(u3_disk* log_u) } // ensure there's a current snapshot - if ( u3_Host.eve_d != las_d ) { + if ( eve_d != las_d ) { fprintf(stderr, "disk: snapshot is out of date, please " "start/shutdown your pier gracefully first\r\n"); fprintf(stderr, "disk: eve_d (%" PRIc3_d ") != las_d (%" PRIc3_d ")\r\n", - u3_Host.eve_d, las_d); + eve_d, las_d); return c3n; } @@ -1489,10 +1310,10 @@ u3_disk_migrate(u3_disk* log_u) return c3y; } -/* u3_disk_vere_diff(): checks if vere version mismatches latest epoch's. +/* _disk_vere_diff(): checks if vere version mismatches latest epoch's. */ -c3_o -u3_disk_vere_diff(u3_disk* log_u) +static c3_o +_disk_vere_diff(u3_disk* log_u) { c3_c ver_c[128]; @@ -1508,3 +1329,201 @@ u3_disk_vere_diff(u3_disk* log_u) return c3n; } + +/* u3_disk_kindly(): do the needful. +*/ +void +u3_disk_kindly(u3_disk* log_u, c3_d eve_d) +{ + if ( c3y == _disk_need_migrate(log_u) ) { + if ( c3n == _disk_migrate(log_u, eve_d) ) { + fprintf(stderr, "disk: failed to migrate event log\r\n"); + exit(1); + } + } + else if ( c3y == _disk_vere_diff(log_u) ) { + if ( c3n == u3_disk_epoc_init(log_u, log_u->dun_d) ) { + fprintf(stderr, "disk: failed to initialize epoch\r\n"); + exit(1); + } + } +} + +/* u3_disk_init(): load or create pier directories and event log. +*/ +u3_disk* +u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) +{ + u3_disk* log_u = c3_calloc(sizeof(*log_u)); + log_u->liv_o = c3n; + log_u->ted_o = c3n; + log_u->cb_u = cb_u; + log_u->red_u = 0; + log_u->put_u.ent_u = log_u->put_u.ext_u = 0; + + // create/load pier directory + // + { + if ( 0 == (log_u->dir_u = u3_foil_folder(pax_c)) ) { + fprintf(stderr, "disk: failed to load pier at %s\r\n", pax_c); + c3_free(log_u); + return 0; + } + } + + // acquire lockfile. + // + u3_disk_acquire(pax_c); + + // create/load $pier/.urb + // + { + c3_c* urb_c = c3_malloc(6 + strlen(pax_c)); + + strcpy(urb_c, pax_c); + strcat(urb_c, "/.urb"); + + if ( 0 == (log_u->urb_u = u3_foil_folder(urb_c)) ) { + fprintf(stderr, "disk: failed to load /.urb in %s\r\n", pax_c); + c3_free(urb_c); + c3_free(log_u); + return 0; + } + c3_free(urb_c); + } + + // create/load $pier/.urb/put and $pier/.urb/get + // + { + c3_c* dir_c = c3_malloc(10 + strlen(pax_c)); + + strcpy(dir_c, pax_c); + strcat(dir_c, "/.urb/put"); + c3_mkdir(dir_c, 0700); + + strcpy(dir_c, pax_c); + strcat(dir_c, "/.urb/get"); + c3_mkdir(dir_c, 0700); + + c3_free(dir_c); + } + + // create/load $pier/.urb/log + // + { + c3_c log_c[8193]; + snprintf(log_c, sizeof(log_c), "%s/.urb/log", pax_c); + + if ( 0 == (log_u->com_u = u3_foil_folder(log_c)) ) { + fprintf(stderr, "disk: failed to load /.urb/log in %s\r\n", pax_c); + c3_free(log_u); + return 0; + } + + // if fresh boot, initialize disk v1 + // + if ( c3y == u3_Host.ops_u.nuu ) { + // initialize first epoch "0i0" + if ( c3n == u3_disk_epoc_init(log_u, 0) ) { + fprintf(stderr, "disk: failed to initialize first epoch\r\n"); + return 0; + } + } + else if ( c3y == _disk_need_migrate(log_u) ) { + fprintf(stderr, "disk: loading old format\r\n"); + + if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_c, siz_i)) ) { + fprintf(stderr, "disk: failed to initialize lmdb\r\n"); + c3_free(log_u); + } + + c3_d fir_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &log_u->dun_d) ) { + fprintf(stderr, "disk: failed to load latest event from lmdb\r\n"); + // XX dispose mdb_u + c3_free(log_u); + return 0; + } + + log_u->sen_d = log_u->dun_d; + log_u->ver_w = 0; + + return log_u; + } + + // get latest epoch number + c3_d lat_d; + if ( c3n == u3_disk_epoc_last(log_u, &lat_d) ) { + fprintf(stderr, "disk: failed to load epoch number\r\n"); + c3_free(log_u); + return 0; + } + + // check latest epoc version + // + { + c3_c ver_c[8]; + c3_w ver_w; + if ( c3n == _disk_epoc_meta(log_u, lat_d, "epoc", + sizeof(ver_c) - 1, ver_c) ) + { + fprintf(stderr, "disk: failed to load epoch version\r\n"); + c3_free(log_u); + return 0; + } + + if ( 1 != sscanf(ver_c, "%d", &ver_w) ) { + fprintf(stderr, "disk: failed to parse epoch version: '%s'\r\n", ver_c); + c3_free(log_u); + return 0; + } + + if ( U3D_VER1 != ver_w ) { + fprintf(stderr, "disk: unknown epoch version: '%s', expected '%d'\r\n", + ver_c, U3D_VER1); + c3_free(log_u); + return 0; + } + + log_u->ver_w = ver_w; + } + + // set path to latest epoch + c3_c epo_c[8193]; + snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_c, lat_d); + + // initialize latest epoch's db + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { + fprintf(stderr, "disk: failed to initialize database at '%s' '%s' '%s'\r\n", pax_c, log_c, epo_c); + c3_free(log_u); + return 0; + } + fprintf(stderr, "disk: loaded epoch 0i%" PRIc3_d "\r\n", lat_d); + + // get first/last event numbers from lmdb + c3_d fir_d, las_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { + fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); + // XX dispose mdb_u + c3_free(log_u); + return 0; + } + + // initialize dun_d/sen_d values + log_u->dun_d = ( 0 != las_d ) ? las_d : lat_d; + log_u->sen_d = log_u->dun_d; + + // mark the latest epoch directory + log_u->epo_d = lat_d; + + // mark the log as live + log_u->liv_o = c3y; + } + + +#if defined(DISK_TRACE_JAM) || defined(DISK_TRACE_CUE) + u3t_trace_open(pax_c); +#endif + + return log_u; +} diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 3b44a6f8f3..c4c5932ee2 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2199,15 +2199,9 @@ _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) pay_d = u3_mars_play(&mar_u, eve_d, sap_d); u3_Host.eve_d = mar_u.dun_d; - if ( c3y == u3_disk_need_migrate(log_u) ) { - u3_disk_migrate(log_u); - } - else if ( c3y == u3_disk_vere_diff(log_u) ) { - if ( c3n == u3_disk_epoc_init(log_u, log_u->dun_d) ) { - fprintf(stderr, "disk: failed to initialize epoch\r\n"); - exit(1); - } - } + // migrate or rollover as needed + // + u3_disk_kindly(log_u, u3_Host.eve_d); } u3_disk_exit(log_u); diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index 959391e96b..bff229e2f3 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -1022,20 +1022,11 @@ c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d); - /* u3_disk_vere_diff(): checks if vere version mismatches latest epoch's. - */ - c3_o - u3_disk_vere_diff(u3_disk* log_u); - - /* u3_disk_need_migrate(): does the disk need migration? + /* u3_disk_kindly(): do the needful. */ - c3_o - u3_disk_need_migrate(u3_disk* log_u); + void + u3_disk_kindly(u3_disk* log_u, c3_d eve_d); - /* u3_disk_migrate(): migrates disk format. - */ - c3_o - u3_disk_migrate(u3_disk* log_u); /* u3_disk_read_list(): synchronously read a cons list of events. */ u3_weak From 6250339ffd9fd0b71bf54a89e8c448bdf376337f Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 22:51:33 -0400 Subject: [PATCH 70/87] vere: explicitly migrate if needed before chop and roll --- pkg/vere/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/vere/main.c b/pkg/vere/main.c index c4c5932ee2..0013ca3af7 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2457,6 +2457,8 @@ _cw_chop(c3_i argc, c3_c* argv[]) u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); + u3_disk_kindly(log_u, u3_Host.eve_d); + // get latest epoch number prior to creating a new one c3_d pre_d; if ( c3n == u3_disk_epoc_last(log_u, &pre_d) ) { @@ -2591,6 +2593,8 @@ _cw_roll(c3_i argc, c3_c* argv[]) u3_Host.eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); + u3_disk_kindly(log_u, u3_Host.eve_d); + // check if there's a *current* snapshot if ( log_u->dun_d != u3A->eve_d ) { fprintf(stderr, "roll: error: snapshot is out of date, please " From 7f84b73e47c387d016774f9c95e0bc91ab7490c3 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 22:15:38 -0400 Subject: [PATCH 71/87] u3: ensure snapshot file descriptors are closed in u3e_stop() --- pkg/noun/events.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 0294f522ab..96fb560623 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1671,6 +1671,9 @@ u3e_stop(void) close(u3P.eph_i); unlink(u3C.eph_c); } + + close(u3P.sou_u.fid_i); + close(u3P.sou_u.fid_i); } /* u3e_yolo(): disable dirty page tracking, read/write whole loom. @@ -1710,6 +1713,8 @@ u3e_init(void) { u3P.pag_w = u3C.wor_i >> u3a_page; + u3P.nor_u.fid_i = u3P.sou_u.fid_i = -1; + u3e_foul(); #ifdef U3_GUARD_PAGE From 0051160228bff157b3d59fe7df48f9d7885c4aa0 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 23:10:17 -0400 Subject: [PATCH 72/87] vere: automatically recover from pre-epoc downgrade --- pkg/vere/disk.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 65056d71e0..b5efe0c096 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1173,16 +1173,16 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) static c3_o _disk_need_migrate(u3_disk* log_u) { - // check if data.mdb is readable in log directory c3_c dut_c[8193]; snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_u->com_u->pax_c); - if ( !_(u3_Host.ops_u.nuu) - && 0 != access(dut_c, F_OK) ) { - // if .urb/log/data.mdb does not exist, skip migration - return c3n; + + // check if data.mdb is readable in log directory + // + if ( 0 == access(dut_c, F_OK)) { + return c3y; } - return c3y; + return c3n; } /* _disk_migrate: migrates disk format. @@ -1445,10 +1445,36 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } - log_u->sen_d = log_u->dun_d; - log_u->ver_w = 0; + // if a top-level log exists but is empty it's safe to remove. + // for extra safety, we only do this if we also have epochs. + // (the top-level log was most likely created by vere downgrade) + // + c3_d nop_d; + if ( !fir_d + && !log_u->dun_d + && (c3y == u3_disk_epoc_last(log_u, &nop_d)) ) + { + u3_lmdb_exit(log_u->mdb_u); + c3_c luk_c[8193]; c3_c dut_c[8193]; + snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_c); + snprintf(luk_c, sizeof(luk_c), "%s/lock.mdb", log_u->com_u->pax_c); + + if ( c3_unlink(dut_c) + || ( (0 == access(luk_c, R_OK)) + && c3_unlink(luk_c) )) + { + fprintf(stderr, "disk: failed to unlink empty, old log\r\n"); + } - return log_u; + // continue to epoc initialization + } + + else { + log_u->sen_d = log_u->dun_d; + log_u->ver_w = 0; + + return log_u; + } } // get latest epoch number From b889f77eb5ed1dbc8570208feae4a30ef68f6a11 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 3 Oct 2023 23:13:57 -0400 Subject: [PATCH 73/87] vere: clean up disk migration error handling --- pkg/vere/disk.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index b5efe0c096..424c7a6887 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1150,10 +1150,12 @@ u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d) c3_o u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) { - c3_o ret_o = c3n; // return c3n if no epoch directories exist - *lat_d = 0; // initialize lat_d to 0 u3_dire* die_u = u3_foil_folder(log_u->com_u->pax_c); u3_dent* den_u = die_u->dil_u; + c3_o ret_o = c3n; + + *lat_d = 0; + while ( den_u ) { c3_d epo_d = 0; if ( 1 == sscanf(den_u->nam_c, "0i%" PRIc3_d, &epo_d) ) { @@ -1283,24 +1285,29 @@ _disk_migrate(u3_disk* log_u, c3_d eve_d) snprintf(bhk_c, sizeof(bhk_c), "%s/.urb/bhk", u3_Host.dir_c); snprintf(nop_c, sizeof(nop_c), "%s/north.bin", bhk_c); snprintf(sop_c, sizeof(sop_c), "%s/south.bin", bhk_c); - if ( c3n == c3_unlink(nop_c) ) { - fprintf(stderr, "disk: failed to delete bhk/north.bin\r\n"); + if ( c3_unlink(nop_c) ) { + fprintf(stderr, "disk: failed to delete bhk/north.bin: %s\r\n", + strerror(errno)); } - else if ( c3n == c3_unlink(sop_c) ) { - fprintf(stderr, "disk: failed to delete bhk/south.bin\r\n"); + else if ( c3_unlink(sop_c) ) { + fprintf(stderr, "disk: failed to delete bhk/south.bin: %s\r\n", + strerror(errno)); } else { - if ( c3n == c3_rmdir(bhk_c) ) { - fprintf(stderr, "disk: failed to delete bhk/\r\n"); + if ( c3_rmdir(bhk_c) ) { + fprintf(stderr, "disk: failed to delete bhk/: %s\r\n", + strerror(errno)); } } // delete old lock.mdb and data.mdb files - if ( 0 != c3_unlink(luk_c) ) { - fprintf(stderr, "disk: failed to unlink lock.mdb\r\n"); + if ( c3_unlink(luk_c) ) { + fprintf(stderr, "disk: failed to unlink lock.mdb: %s\r\n", + strerror(errno)); } - if ( 0 != c3_unlink(dut_c) ) { - fprintf(stderr, "disk: failed to unlink data.mdb\r\n"); + if ( c3_unlink(dut_c) ) { + fprintf(stderr, "disk: failed to unlink data.mdb: %s\r\n", + strerror(errno)); return c3n; // migration succeeds only if we can unlink data.mdb } From b1cf27735d5a94f332902ea596fda48ee2ba1c95 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 4 Oct 2023 00:02:16 -0400 Subject: [PATCH 74/87] vere: fix up lmdb lifecycle, plugging leaks --- pkg/vere/disk.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 424c7a6887..572801fcdc 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1076,12 +1076,17 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) fprintf(stderr, "disk: failed to read metadata\r\n"); goto fail; } + + u3_lmdb_exit(log_u->mdb_u); + log_u->mdb_u = 0; } + // initialize db of new epoch if ( c3y == u3_Host.ops_u.nuu || epo_d > 0 ) { c3_c dat_c[8193]; snprintf(dat_c, sizeof(dat_c), "%s/data.mdb", epo_c); + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); @@ -1226,14 +1231,6 @@ _disk_migrate(u3_disk* log_u, c3_d eve_d) // - not started the migration, or // - crashed before completing the migration - // initialize pre-migrated lmdb - { - if ( 0 == (log_u->mdb_u = u3_lmdb_init(log_u->com_u->pax_c, siz_i)) ) { - fprintf(stderr, "disk: failed to initialize database\r\n"); - return c3n; - } - } - // get first/last event numbers from pre-migrated lmdb c3_d fir_d, las_d; if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { @@ -1461,11 +1458,13 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) && !log_u->dun_d && (c3y == u3_disk_epoc_last(log_u, &nop_d)) ) { - u3_lmdb_exit(log_u->mdb_u); c3_c luk_c[8193]; c3_c dut_c[8193]; snprintf(dut_c, sizeof(dut_c), "%s/data.mdb", log_c); snprintf(luk_c, sizeof(luk_c), "%s/lock.mdb", log_u->com_u->pax_c); + u3_lmdb_exit(log_u->mdb_u); + log_u->mdb_u = 0; + if ( c3_unlink(dut_c) || ( (0 == access(luk_c, R_OK)) && c3_unlink(luk_c) )) From 20f4a34810f53dec34bccf79e27953b496cb753f Mon Sep 17 00:00:00 2001 From: Sigilante <57601680+sigilante@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:11:30 -0500 Subject: [PATCH 75/87] Make dor jet use u3_noun. --- pkg/noun/jets/c/dor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/noun/jets/c/dor.c b/pkg/noun/jets/c/dor.c index dc463f7ae6..0c1e220afc 100644 --- a/pkg/noun/jets/c/dor.c +++ b/pkg/noun/jets/c/dor.c @@ -7,8 +7,8 @@ u3_noun - u3qc_dor(u3_atom a, - u3_atom b) + u3qc_dor(u3_noun a, + u3_noun b) { if ( c3y == u3r_sing(a, b) ) { return c3y; From c42e1497ad8b9291dd418514b87a19f2e412c1e1 Mon Sep 17 00:00:00 2001 From: Sigilante <57601680+sigilante@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:12:02 -0500 Subject: [PATCH 76/87] Update mor.c to take u3_noun --- pkg/noun/jets/c/mor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/noun/jets/c/mor.c b/pkg/noun/jets/c/mor.c index 6967a8a1b6..97ba1410bd 100644 --- a/pkg/noun/jets/c/mor.c +++ b/pkg/noun/jets/c/mor.c @@ -7,8 +7,8 @@ u3_noun - u3qc_mor(u3_atom a, - u3_atom b) + u3qc_mor(u3_noun a, + u3_noun b) { c3_w c_w = u3r_mug(u3r_mug(a)); c3_w d_w = u3r_mug(u3r_mug(b)); From 674c9844e701c5f1a410489452487f090a542536 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 5 Oct 2023 21:36:39 -0400 Subject: [PATCH 77/87] u3: move u3r_cell/trel/&c to inline functions --- pkg/noun/retrieve.c | 134 +++++++++------------------------------ pkg/noun/retrieve.h | 148 ++++++++++++++++++++++++++++---------------- 2 files changed, 122 insertions(+), 160 deletions(-) diff --git a/pkg/noun/retrieve.c b/pkg/noun/retrieve.c index d1790c7320..c5f20d0c27 100644 --- a/pkg/noun/retrieve.c +++ b/pkg/noun/retrieve.c @@ -9,6 +9,35 @@ #include "trace.h" #include "xtract.h" + +// declarations of inline functions +// +c3_o +u3r_cell(u3_noun a, u3_noun* b, u3_noun* c); +c3_o +u3r_trel(u3_noun a, u3_noun* b, u3_noun* c, u3_noun* d); +c3_o +u3r_qual(u3_noun a, + u3_noun* b, + u3_noun* c, + u3_noun* d, + u3_noun* e); +c3_o +u3r_quil(u3_noun a, + u3_noun* b, + u3_noun* c, + u3_noun* d, + u3_noun* e, + u3_noun* f); +c3_o +u3r_hext(u3_noun a, + u3_noun* b, + u3_noun* c, + u3_noun* d, + u3_noun* e, + u3_noun* f, + u3_noun* g); + /* _frag_word(): fast fragment/branch prediction for top word. */ static u3_weak @@ -833,27 +862,6 @@ u3r_bite(u3_noun bite, u3_atom* bloq, u3_atom *step) } } -/* u3r_cell(): -** -** Factor (a) as a cell (b c). -*/ -c3_o -u3r_cell(u3_noun a, - u3_noun* b, - u3_noun* c) -{ - u3_assert(u3_none != a); - - if ( _(u3a_is_atom(a)) ) { - return c3n; - } - else { - if ( b ) *b = u3a_h(a); - if ( c ) *c = u3a_t(a); - return c3y; - } -} - /* u3r_p(): ** ** & [0] if [a] is of the form [b *c]. @@ -937,90 +945,6 @@ u3r_pqrs(u3_noun a, else return c3n; } -/* u3r_trel(): -** -** Factor (a) as a trel (b c d). -*/ -c3_o -u3r_trel(u3_noun a, - u3_noun *b, - u3_noun *c, - u3_noun *d) -{ - u3_noun guf; - - if ( (c3y == u3r_cell(a, b, &guf)) && - (c3y == u3r_cell(guf, c, d)) ) { - return c3y; - } - else { - return c3n; - } -} - -/* u3r_qual(): -** -** Factor (a) as a qual (b c d e). -*/ -c3_o -u3r_qual(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e) -{ - u3_noun guf; - - if ( (c3y == u3r_cell(a, b, &guf)) && - (c3y == u3r_trel(guf, c, d, e)) ) { - return c3y; - } - else return c3n; -} - -/* u3r_quil(): -** -** Factor (a) as a quil (b c d e f). -*/ -c3_o -u3r_quil(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e, - u3_noun* f) -{ - u3_noun guf; - - if ( (c3y == u3r_cell(a, b, &guf)) && - (c3y == u3r_qual(guf, c, d, e, f)) ) { - return c3y; - } - else return c3n; -} - -/* u3r_hext(): -** -** Factor (a) as a hext (b c d e f g) -*/ -c3_o -u3r_hext(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e, - u3_noun* f, - u3_noun* g) -{ - u3_noun guf; - - if ( (c3y == u3r_cell(a, b, &guf)) && - (c3y == u3r_quil(guf, c, d, e, f, g)) ) { - return c3y; - } - else return c3n; -} - /* u3r_met(): ** ** Return the size of (b) in bits, rounded up to diff --git a/pkg/noun/retrieve.h b/pkg/noun/retrieve.h index a98a5e4697..875b54f606 100644 --- a/pkg/noun/retrieve.h +++ b/pkg/noun/retrieve.h @@ -4,11 +4,104 @@ #define U3_RETRIEVE_H #include "c3.h" +#include "allocate.h" +#include "error.h" #include "gmp.h" #include "types.h" /** u3r_*: read without ever crashing. **/ + + /* u3r_cell(): factor (a) as a cell (b c). + */ + inline c3_o + u3r_cell(u3_noun a, u3_noun* b, u3_noun* c) + { + u3_assert(u3_none != a); + + if ( c3y == u3a_is_cell(a) ) { + if ( b ) *b = u3a_h(a); // XX use unchecked + if ( c ) *c = u3a_t(a); + return c3y; + } + else { + return c3n; + } + } + + /* u3r_trel(): factor (a) as a trel (b c d). + */ + inline c3_o + u3r_trel(u3_noun a, u3_noun *b, u3_noun *c, u3_noun *d) + { + u3_noun guf; + + if ( (c3y == u3r_cell(a, b, &guf)) && + (c3y == u3r_cell(guf, c, d)) ) { + return c3y; + } + else { + return c3n; + } + } + + /* u3r_qual(): factor (a) as a qual (b c d e). + */ + inline c3_o + u3r_qual(u3_noun a, + u3_noun* b, + u3_noun* c, + u3_noun* d, + u3_noun* e) + { + u3_noun guf; + + if ( (c3y == u3r_cell(a, b, &guf)) && + (c3y == u3r_trel(guf, c, d, e)) ) { + return c3y; + } + else return c3n; + } + + /* u3r_quil(): factor (a) as a quil (b c d e f). + */ + inline c3_o + u3r_quil(u3_noun a, + u3_noun* b, + u3_noun* c, + u3_noun* d, + u3_noun* e, + u3_noun* f) + { + u3_noun guf; + + if ( (c3y == u3r_cell(a, b, &guf)) && + (c3y == u3r_qual(guf, c, d, e, f)) ) { + return c3y; + } + else return c3n; + } + + /* u3r_hext(): factor (a) as a hext (b c d e f g) + */ + inline c3_o + u3r_hext(u3_noun a, + u3_noun* b, + u3_noun* c, + u3_noun* d, + u3_noun* e, + u3_noun* f, + u3_noun* g) + { + u3_noun guf; + + if ( (c3y == u3r_cell(a, b, &guf)) && + (c3y == u3r_quil(guf, c, d, e, f, g)) ) { + return c3y; + } + else return c3n; + } + /* u3r_at(): fragment `a` of `b`, or u3_none. */ u3_weak @@ -183,61 +276,6 @@ c3_o u3r_bite(u3_noun bite, u3_atom* bloq, u3_atom *step); - /* u3r_cell(): - ** - ** Divide `a` as a cell `[b c]`. - */ - c3_o - u3r_cell(u3_noun a, - u3_noun* b, - u3_noun* c); - - /* u3r_trel(): - ** - ** Divide `a` as a trel `[b c d]`. - */ - c3_o - u3r_trel(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d); - - /* u3r_qual(): - ** - ** Divide (a) as a qual [b c d e]. - */ - c3_o - u3r_qual(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e); - - /* u3r_quil(): - ** - ** Divide (a) as a quil [b c d e f]. - */ - c3_o - u3r_quil(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e, - u3_noun* f); - - /* u3r_hext(): - ** - ** Divide (a) as a hext [b c d e f g]. - */ - c3_o - u3r_hext(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e, - u3_noun* f, - u3_noun* g); - /* u3r_p(): ** ** & [0] if [a] is of the form [b *c]. From 6a6f634a00045f35d217cebbbb72a2f90474d729 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 5 Oct 2023 21:54:29 -0400 Subject: [PATCH 78/87] u3: move u3x_cell/trel/&c to macros --- pkg/noun/xtract.c | 106 +--------------------------------- pkg/noun/xtract.h | 142 +++++++++++++++++++++++----------------------- 2 files changed, 73 insertions(+), 175 deletions(-) diff --git a/pkg/noun/xtract.c b/pkg/noun/xtract.c index fc59f463d8..a869eb9547 100644 --- a/pkg/noun/xtract.c +++ b/pkg/noun/xtract.c @@ -5,21 +5,8 @@ #include "manage.h" #include "retrieve.h" -/* u3x_good(): test for u3_none. -*/ u3_noun -u3x_good(u3_weak som) -{ - return ( u3_none == som ) ? u3m_bail(c3__exit) : som; -} - -/* u3x_at (u3at): fragment. -*/ -u3_noun -u3x_at(u3_noun axe, u3_noun som) -{ - return u3x_good(u3r_at(axe, som)); -} +u3x_good(u3_weak som); /* u3x_mean(): ** @@ -40,94 +27,3 @@ u3x_mean(u3_noun som, ...) u3m_bail(c3__exit); } } - -/* u3x_bite(): xtract/default $bloq and $step from $bite. -*/ -void -u3x_bite(u3_noun bite, u3_atom* bloq, u3_atom *step) -{ - if ( c3n == u3r_bite(bite, bloq, step) ) { - u3m_bail(c3__exit); - } -} - -/* u3x_cell(): -** -** Divide `a` as a cell `[b c]`. -*/ -void -u3x_cell(u3_noun a, - u3_noun* b, - u3_noun* c) -{ - if ( c3n == u3r_cell(a, b, c) ) { - u3m_bail(c3__exit); - } -} - -/* u3x_trel(): -** -** Divide `a` as a trel `[b c d]`, or bail. -*/ -void -u3x_trel(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d) -{ - if ( c3n == u3r_trel(a, b, c, d) ) { - u3m_bail(c3__exit); - } -} - -/* u3x_qual(): -** -** Divide `a` as a quadruple `[b c d e]`. -*/ -void -u3x_qual(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e) -{ - if ( c3n == u3r_qual(a, b, c, d, e) ) { - u3m_bail(c3__exit); - } -} - -/* u3x_quil(): -** -** Divide `a` as a quintuple `[b c d e f]`. -*/ -void -u3x_quil(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e, - u3_noun* f) -{ - if ( c3n == u3r_quil(a, b, c, d, e, f) ) { - u3m_bail(c3__exit); - } -} - -/* u3x_hext(): -** -** Divide `a` as a hextuple `[b c d e f g]`. -*/ -void -u3x_hext(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e, - u3_noun* f, - u3_noun* g) -{ - if ( c3n == u3r_hext(a, b, c, d, e, f, g) ) { - u3m_bail(c3__exit); - } -} - diff --git a/pkg/noun/xtract.h b/pkg/noun/xtract.h index cf39011463..343690a8f2 100644 --- a/pkg/noun/xtract.h +++ b/pkg/noun/xtract.h @@ -5,6 +5,8 @@ #include "c3.h" #include "types.h" +#include "allocate.h" +#include "manage.h" /** Constants. **/ @@ -40,6 +42,21 @@ **/ /* Word axis macros. For 31-bit axes only. */ + + /* u3x_at (u3at): fragment. + */ +# define u3x_at(a, b) u3x_good(u3r_at(a, b)) +# define u3at(a, b) u3x_at(a, b) + + /* u3x_bite(): xtract/default $bloq and $step from $bite. + */ +# define u3x_bite(a, b, c) \ + do { \ + if ( c3n == u3r_bite(a, b, c) ) { \ + u3m_bail(c3__exit); \ + } \ + } while (0) + /* u3x_dep(): number of axis bits. */ # define u3x_dep(a_w) (c3_bits_word(a_w) - 1) @@ -61,25 +78,70 @@ # define u3x_peg(a_w, b_w) \ ( (a_w << u3x_dep(b_w)) | (b_w &~ (1 << u3x_dep(b_w))) ) - /* u3x_atom(): atom or exit. + /* u3x_cell(): divide `a` as a cell `[b c]`. + */ +# define u3x_cell(a, b, c) \ + do { \ + if ( c3n == u3r_cell(a, b, c) ) { \ + u3m_bail(c3__exit); \ + } \ + } while (0) + + /* u3x_trel(): divide `a` as a trel `[b c d]`, or bail. + */ +# define u3x_trel(a, b, c, d) \ + do { \ + if ( c3n == u3r_trel(a, b, c, d) ) { \ + u3m_bail(c3__exit); \ + } \ + } while (0) + + /* u3x_qual(): divide `a` as a quadruple `[b c d e]`. */ -# define u3x_atom(a) \ - ( (c3y == u3a_is_cell(a)) ? u3m_bail(c3__exit) : a ) +# define u3x_qual(a, b, c, d, e) \ + do { \ + if ( c3n == u3r_qual(a, b, c, d, e) ) { \ + u3m_bail(c3__exit); \ + } \ + } while (0) + + /* u3x_quil(): divide `a` as a quintuple `[b c d e f]`. + */ +# define u3x_quil(a, b, c, d, e, f) \ + do { \ + if ( c3n == u3r_quil(a, b, c, d, e, f) ) { \ + u3m_bail(c3__exit); \ + } \ + } while (0) + + /* u3x_hext(): divide `a` as a hextuple `[b c d e f g]`. + */ +# define u3x_hext(a, b, c, d, e, f, g) \ + do { \ + if ( c3n == u3r_hext(a, b, c, d, e, f, g) ) { \ + u3m_bail(c3__exit); \ + } \ + } while (0) /** Functions. **/ /** u3x_*: read, but bail with c3__exit on a crash. **/ - /* u3x_good(): test for u3_none. + /* u3x_atom(): atom or exit. */ - u3_noun - u3x_good(u3_weak som); + inline u3_atom + u3x_atom(u3_noun a) + { + return ( c3y == u3a_is_cell(a) ) ? u3m_bail(c3__exit) : a; + } - /* u3x_at (u3at): fragment. + /* u3x_good(): test for u3_none. */ - u3_noun - u3x_at(u3_noun axe, u3_noun som); -# define u3at(axe, som) u3x_at(axe, som) + inline u3_noun + u3x_good(u3_weak som) + { + return ( u3_none == som ) ? u3m_bail(c3__exit) : som; + } /* u3x_mean(): ** @@ -89,64 +151,4 @@ void u3x_mean(u3_noun a, ...); - /* u3x_bite(): xtract/default $bloq and $step from $bite. - */ - void - u3x_bite(u3_noun bite, u3_atom* bloq, u3_atom *step); - - /* u3x_cell(): - ** - ** Divide `a` as a cell `[b c]`. - */ - void - u3x_cell(u3_noun a, - u3_noun* b, - u3_noun* c); - - /* u3x_trel(): - ** - ** Divide `a` as a trel `[b c d]`, or bail. - */ - void - u3x_trel(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d); - - /* u3x_qual(): - ** - ** Divide `a` as a quadruple `[b c d e]`. - */ - void - u3x_qual(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e); - - /* u3x_quil(): - ** - ** Divide `a` as a quintuple `[b c d e f]`. - */ - void - u3x_quil(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e, - u3_noun* f); - - /* u3x_hext(): - ** - ** Divide `a` as a hextuple `[b c d e f g]`. - */ - void - u3x_hext(u3_noun a, - u3_noun* b, - u3_noun* c, - u3_noun* d, - u3_noun* e, - u3_noun* f, - u3_noun* g); - #endif /* ifndef U3_XTRACT_H */ From b082b4fc231829c934994b564eec322d2acafed4 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 6 Oct 2023 10:33:58 -0400 Subject: [PATCH 79/87] vere: s/desk/disk/g --- pkg/vere/disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 572801fcdc..aceaef5407 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1175,7 +1175,7 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) return ret_o; } -/* _disk_need_migrate: does the desk need to be migrated? +/* _disk_need_migrate: does the disk need to be migrated? */ static c3_o _disk_need_migrate(u3_disk* log_u) From f31afc739ae56450a9aafbe3716b6779ff8849c6 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 6 Oct 2023 14:27:03 -0400 Subject: [PATCH 80/87] u3: updates _ce_image_sync to return status --- pkg/noun/events.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 96fb560623..c3a2c6ee71 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -778,14 +778,16 @@ _ce_patch_sync(u3_ce_patch* pat_u) /* _ce_image_sync(): make sure image is synced to disk. */ -static void +static c3_o _ce_image_sync(u3e_image* img_u) { if ( -1 == c3_sync(img_u->fid_i) ) { fprintf(stderr, "loom: image (%s) sync failed: %s\r\n", img_u->nam_c, strerror(errno)); - u3_assert(!"loom: image sync"); + return c3n; } + + return c3y; } /* _ce_image_resize(): resize image, truncating if it shrunk. @@ -1474,8 +1476,9 @@ u3e_save(u3_post low_p, u3_post hig_p) _ce_patch_apply(pat_u); - _ce_image_sync(&u3P.nor_u); - _ce_image_sync(&u3P.sou_u); + u3_assert( c3y == _ce_image_sync(&u3P.nor_u) ); + u3_assert( c3y == _ce_image_sync(&u3P.sou_u) ); + _ce_patch_free(pat_u); _ce_patch_delete(); @@ -1599,8 +1602,8 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) */ if ( 0 != (pat_u = _ce_patch_open()) ) { _ce_patch_apply(pat_u); - _ce_image_sync(&u3P.nor_u); - _ce_image_sync(&u3P.sou_u); + u3_assert( c3y == _ce_image_sync(&u3P.nor_u) ); + u3_assert( c3y == _ce_image_sync(&u3P.sou_u) ); _ce_patch_free(pat_u); _ce_patch_delete(); } From 55c0e82de0e7a09b7c5b21e5084f959f0356ba63 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 6 Oct 2023 14:28:16 -0400 Subject: [PATCH 81/87] u3: updates u3e_backup to fsync destination images --- pkg/noun/events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/noun/events.c b/pkg/noun/events.c index c3a2c6ee71..d4f6c92ed0 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -1397,7 +1397,9 @@ u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) } if ( (c3n == _ce_image_copy(&nux_u, &nax_u)) - || (c3n == _ce_image_copy(&sux_u, &sax_u)) ) + || (c3n == _ce_image_copy(&sux_u, &sax_u)) + || (c3n == _ce_image_sync(&nax_u)) + || (c3n == _ce_image_sync(&sax_u)) ) { c3_unlink(nax_c); c3_unlink(sax_c); From fc7efea28c8cea6a7f524746918267708ef0b355 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 6 Oct 2023 15:41:34 -0400 Subject: [PATCH 82/87] vere: reorders 3_disk_epoc_init and adds syncs for atomicity --- pkg/vere/disk.c | 60 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index aceaef5407..51ddbd3606 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1036,37 +1036,51 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) // create new epoch directory if it doesn't exist c3_c epo_c[8193]; + c3_i epo_i; snprintf(epo_c, sizeof(epo_c), "%s/0i%" PRIc3_d, log_u->com_u->pax_c, epo_d); c3_d ret_d = c3_mkdir(epo_c, 0700); if ( ( ret_d < 0 ) && ( errno != EEXIST ) ) { - fprintf(stderr, "disk: failed to create epoch directory %" PRIc3_d "\r\n", epo_d); + fprintf(stderr, "disk: create epoch dir %" PRIc3_d " failed: %s\r\n", + epo_d, strerror(errno)); return c3n; } + // copy snapshot files (skip if first epoch) + if ( epo_d > 0 ) { + c3_c chk_c[8193]; + snprintf(chk_c, 8192, "%s/.urb/chk", u3_Host.dir_c); + if ( c3n == u3e_backup(chk_c, epo_c, c3y) ) { + fprintf(stderr, "disk: copy epoch snapshot failed\r\n"); + goto fail1; + } + } + + if ( -1 == (epo_i = c3_open(epo_c, O_RDONLY)) ) { + fprintf(stderr, "disk: open epoch dir %" PRIc3_d " failed: %s\r\n", + epo_d, strerror(errno)); + goto fail1; + } + + if ( -1 == c3_sync(epo_i) ) { // XX fdatasync on linux? + fprintf(stderr, "disk: sync epoch dir %" PRIc3_d " failed: %s\r\n", + epo_d, strerror(errno)); + goto fail2; + } + // create epoch version file, overwriting any existing file c3_c epv_c[8193]; snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); - FILE* epv_f = fopen(epv_c, "w"); + FILE* epv_f = fopen(epv_c, "w"); // XX errors fprintf(epv_f, "%d", U3D_VER1); fclose(epv_f); // create binary version file, overwriting any existing file c3_c biv_c[8193]; snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); - FILE* biv_f = fopen(biv_c, "w"); + FILE* biv_f = fopen(biv_c, "w"); // XX errors fprintf(biv_f, URBIT_VERSION); fclose(biv_f); - // copy snapshot files (skip if first epoch) - if ( epo_d > 0 ) { - c3_c chk_c[8193]; - snprintf(chk_c, 8192, "%s/.urb/chk", u3_Host.dir_c); - if ( c3n == u3e_backup(chk_c, epo_c, c3y) ) { - fprintf(stderr, "disk: failed to copy snapshot to new epoch\r\n"); - goto fail; - } - } - // get metadata from old epoch or unmigrated event log's db c3_d who_d[2]; c3_o fak_o; @@ -1074,14 +1088,13 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) if ( c3y == eps_o ) { // skip if no epochs yet if ( c3y != u3_disk_read_meta(log_u->mdb_u, who_d, &fak_o, &lif_w) ) { fprintf(stderr, "disk: failed to read metadata\r\n"); - goto fail; + goto fail3; } u3_lmdb_exit(log_u->mdb_u); log_u->mdb_u = 0; } - // initialize db of new epoch if ( c3y == u3_Host.ops_u.nuu || epo_d > 0 ) { c3_c dat_c[8193]; @@ -1090,7 +1103,7 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { fprintf(stderr, "disk: failed to initialize database\r\n"); c3_free(log_u); - goto fail; + goto fail3; } } @@ -1098,19 +1111,30 @@ u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d) if ( c3y == eps_o ) { if ( c3n == u3_disk_save_meta(log_u->mdb_u, who_d, fak_o, lif_w) ) { fprintf(stderr, "disk: failed to save metadata\r\n"); - goto fail; + goto fail3; } } + if ( -1 == c3_sync(epo_i) ) { // XX fdatasync on linux? + fprintf(stderr, "disk: sync epoch dir %" PRIc3_d " failed: %s\r\n", + epo_d, strerror(errno)); + goto fail3; + } + + close(epo_i); + // load new epoch directory and set it in log_u log_u->epo_d = epo_d; // success return c3y; -fail: +fail3: c3_unlink(epv_c); c3_unlink(biv_c); +fail2: + close(epo_i); +fail1: c3_rmdir(epo_c); return c3n; } From b9e39ba81161dc0d843ddcac10e2652c9b471d60 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 6 Oct 2023 16:07:40 -0400 Subject: [PATCH 83/87] vere: factors sorted epoc list out of chop subcommand --- pkg/vere/disk.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ pkg/vere/main.c | 51 +++++++------------------------------------------ pkg/vere/vere.h | 17 +++++++++++------ 3 files changed, 64 insertions(+), 50 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 51ddbd3606..7f3d0efadd 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1199,6 +1199,52 @@ u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d) return ret_o; } +/* u3_disk_epoc_list: get descending epoch numbers, "mcut" pattern. +*/ +c3_z +u3_disk_epoc_list(u3_disk* log_u, c3_d* sot_d) +{ + u3_dire* ned_u = u3_foil_folder(log_u->com_u->pax_c); + u3_dent* den_u = ned_u->dil_u; + c3_z len_z = 0; + + while ( den_u ) { // count epochs + len_z++; + den_u = den_u->nex_u; + } + + if ( !sot_d ) { + u3_dire_free(ned_u); + return len_z; + } + + len_z = 0; + den_u = ned_u->dil_u; + + while ( den_u ) { + if ( 1 == sscanf(den_u->nam_c, "0i%" PRIc3_d, (sot_d + len_z)) ) { + len_z++; + } + den_u = den_u->nex_u; + } + + // sort sot_d naively in descending order + // + c3_d tmp_d; + for ( c3_z i_z = 0; i_z < len_z; i_z++ ) { + for ( c3_z j_z = i_z + 1; j_z < len_z; j_z++ ) { + if ( sot_d[i_z] < sot_d[j_z] ) { + tmp_d = sot_d[i_z]; + sot_d[i_z] = sot_d[j_z]; + sot_d[j_z] = tmp_d; + } + } + } + + u3_dire_free(ned_u); + return len_z; +} + /* _disk_need_migrate: does the disk need to be migrated? */ static c3_o diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 0013ca3af7..9a1680347c 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2459,13 +2459,6 @@ _cw_chop(c3_i argc, c3_c* argv[]) u3_disk_kindly(log_u, u3_Host.eve_d); - // get latest epoch number prior to creating a new one - c3_d pre_d; - if ( c3n == u3_disk_epoc_last(log_u, &pre_d) ) { - fprintf(stderr, "chop: failed to find last epoch\r\n"); - exit(1); - } - // create new epoch c3_d fir_d, las_d; if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { @@ -2479,50 +2472,20 @@ _cw_chop(c3_i argc, c3_c* argv[]) exit(1); } - // sort epoch directories in descending order - u3_dire* ned_u = u3_foil_folder(log_u->com_u->pax_c); - u3_dent* den_u = ned_u->dil_u; - c3_z len_z = 0; - while ( den_u ) { // count epochs - len_z++; - den_u = den_u->nex_u; - } - c3_d* sot_d = c3_malloc(len_z * sizeof(c3_d)); - len_z = 0; - den_u = ned_u->dil_u; - while ( den_u ) { - if ( 1 == sscanf(den_u->nam_c, "0i%" PRIc3_d, (sot_d + len_z)) ) { - len_z++; - } - den_u = den_u->nex_u; - } + c3_z len_z = u3_disk_epoc_list(log_u, 0); if ( len_z <= 2 ) { fprintf(stderr, "chop: nothing to do, have a great day\r\n"); exit(0); // enjoy } - // sort sot_d naively in descending order - c3_d tmp_d; - for ( c3_z i_z = 0; i_z < len_z; i_z++ ) { - for ( c3_z j_z = i_z + 1; j_z < len_z; j_z++ ) { - if ( sot_d[i_z] < sot_d[j_z] ) { - tmp_d = sot_d[i_z]; - sot_d[i_z] = sot_d[j_z]; - sot_d[j_z] = tmp_d; - } - } - } - - // get latest epoch number prior to creating a new one - c3_d pos_d; - if ( c3n == u3_disk_epoc_last(log_u, &pos_d) ) { - fprintf(stderr, "chop: failed to find last epoch\r\n"); - exit(1); - } + c3_d* sot_d = c3_malloc(len_z * sizeof(c3_d)); + u3_disk_epoc_list(log_u, sot_d); // delete all but the last two epochs - // XX parameterize the number of epochs to chop + // + // XX parameterize the number of epochs to chop + // for ( c3_z i_z = 2; i_z < len_z; i_z++ ) { fprintf(stderr, "chop: deleting epoch 0i%" PRIc3_d "\r\n", sot_d[i_z]); if ( c3y != u3_disk_epoc_kill(log_u, sot_d[i_z]) ) { @@ -2532,7 +2495,7 @@ _cw_chop(c3_i argc, c3_c* argv[]) } // cleanup - u3_dire_free(ned_u); + c3_free(sot_d); u3_disk_exit(log_u); // success diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index bff229e2f3..b2b78b5e81 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -1009,18 +1009,23 @@ /* u3_disk_epoc_init(): create new epoch. */ - c3_o - u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d); + c3_o + u3_disk_epoc_init(u3_disk* log_u, c3_d epo_d); /* u3_disk_epoc_kill(): delete an epoch. */ - c3_o - u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d); + c3_o + u3_disk_epoc_kill(u3_disk* log_u, c3_d epo_d); /* u3_disk_epoc_last(): get latest epoch number. */ - c3_o - u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d); + c3_o + u3_disk_epoc_last(u3_disk* log_u, c3_d* lat_d); + + /* u3_disk_epoc_list: get descending epoch numbers, "mcut" pattern. + */ + c3_z + u3_disk_epoc_list(u3_disk* log_u, c3_d* sot_d); /* u3_disk_kindly(): do the needful. */ From d7ea9828bcfadb4e833c3f9e05de18494889eeb5 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 6 Oct 2023 16:49:41 -0400 Subject: [PATCH 84/87] vere: refactors epoc loading, adds fallback to previous when bad --- pkg/vere/disk.c | 191 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 137 insertions(+), 54 deletions(-) diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 7f3d0efadd..45a2c21cef 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1423,6 +1423,86 @@ u3_disk_kindly(u3_disk* log_u, c3_d eve_d) } } +typedef enum { + _epoc_good = 0, // load successfully + _epoc_gone = 1, // version missing, total failure + _epoc_fail = 2, // transient failure (?) + _epoc_void = 3, // empty event log (cheaper to recover?) + _epoc_late = 4 // format from the future +} _epoc_kind; + +/* _disk_epoc_load(): load existing epoch, enumerating failures +*/ +static _epoc_kind +_disk_epoc_load(u3_disk* log_u, c3_d lat_d) +{ + // check latest epoc version + // + { + c3_c ver_c[8]; + c3_w ver_w; + if ( c3n == _disk_epoc_meta(log_u, lat_d, "epoc", + sizeof(ver_c) - 1, ver_c) ) + { + fprintf(stderr, "disk: failed to load epoch 0i%" PRIc3_d " version\r\n", + lat_d); + + return _epoc_gone; + } + + if ( 1 != sscanf(ver_c, "%d", &ver_w) ) { + fprintf(stderr, "disk: failed to parse epoch version: '%s'\r\n", ver_c); + return _epoc_fail; + } + + if ( U3D_VER1 != ver_w ) { + fprintf(stderr, "disk: unknown epoch version: '%s', expected '%d'\r\n", + ver_c, U3D_VER1); + return _epoc_late; + } + + log_u->ver_w = ver_w; + } + + // set path to latest epoch + c3_c epo_c[8193]; + snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_u->com_u->pax_c, lat_d); + + // initialize latest epoch's db + if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { + fprintf(stderr, "disk: failed to initialize database at %s\r\n", + epo_c); + return _epoc_fail; + } + + fprintf(stderr, "disk: loaded epoch 0i%" PRIc3_d "\r\n", lat_d); + + // get first/last event numbers from lmdb + c3_d fir_d, las_d; + if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { + fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); + u3_lmdb_exit(log_u->mdb_u); + log_u->mdb_u = 0; + return _epoc_fail; + } + + if ( (c3n == u3_Host.ops_u.nuu ) + && !fir_d + && !las_d + && (c3n == u3_disk_read_meta(log_u->mdb_u, 0, 0, 0)) ) + { + u3_lmdb_exit(log_u->mdb_u); + log_u->mdb_u = 0; + return _epoc_void; + } + + // initialize dun_d/sen_d values + log_u->dun_d = ( 0 != las_d ) ? las_d : lat_d; + log_u->sen_d = log_u->dun_d; + + return _epoc_good; +} + /* u3_disk_init(): load or create pier directories and event log. */ u3_disk* @@ -1561,71 +1641,74 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) return 0; } - // check latest epoc version - // + c3_o try_o = c3n; + +try_init: { - c3_c ver_c[8]; - c3_w ver_w; - if ( c3n == _disk_epoc_meta(log_u, lat_d, "epoc", - sizeof(ver_c) - 1, ver_c) ) - { - fprintf(stderr, "disk: failed to load epoch version\r\n"); - c3_free(log_u); - return 0; - } + _epoc_kind kin_e = _disk_epoc_load(log_u, lat_d); - if ( 1 != sscanf(ver_c, "%d", &ver_w) ) { - fprintf(stderr, "disk: failed to parse epoch version: '%s'\r\n", ver_c); - c3_free(log_u); - return 0; - } + switch ( kin_e ) { + case _epoc_good: { + // mark the latest epoch directory + log_u->epo_d = lat_d; - if ( U3D_VER1 != ver_w ) { - fprintf(stderr, "disk: unknown epoch version: '%s', expected '%d'\r\n", - ver_c, U3D_VER1); - c3_free(log_u); - return 0; - } + // mark the log as live + log_u->liv_o = c3y; - log_u->ver_w = ver_w; - } +#if defined(DISK_TRACE_JAM) || defined(DISK_TRACE_CUE) + u3t_trace_open(pax_c); +#endif - // set path to latest epoch - c3_c epo_c[8193]; - snprintf(epo_c, 8192, "%s/0i%" PRIc3_d, log_c, lat_d); + return log_u; + } break; - // initialize latest epoch's db - if ( 0 == (log_u->mdb_u = u3_lmdb_init(epo_c, siz_i)) ) { - fprintf(stderr, "disk: failed to initialize database at '%s' '%s' '%s'\r\n", pax_c, log_c, epo_c); - c3_free(log_u); - return 0; - } - fprintf(stderr, "disk: loaded epoch 0i%" PRIc3_d "\r\n", lat_d); + case _epoc_void: // XX could handle more efficiently - // get first/last event numbers from lmdb - c3_d fir_d, las_d; - if ( c3n == u3_lmdb_gulf(log_u->mdb_u, &fir_d, &las_d) ) { - fprintf(stderr, "disk: failed to get first/last event numbers\r\n"); - // XX dispose mdb_u - c3_free(log_u); - return 0; - } + case _epoc_gone: { + // XX if there is no version number, the epoc is invalid + // backup and try previous - // initialize dun_d/sen_d values - log_u->dun_d = ( 0 != las_d ) ? las_d : lat_d; - log_u->sen_d = log_u->dun_d; + if ( c3y == try_o ) { + fprintf(stderr, "multiple bad epochs, bailing out\r\n"); + c3_free(log_u); + return 0; + } - // mark the latest epoch directory - log_u->epo_d = lat_d; + c3_z len_z = u3_disk_epoc_list(log_u, 0); - // mark the log as live - log_u->liv_o = c3y; - } + if ( len_z <= 1 ) { + fprintf(stderr, "only epoch is bad, bailing out\r\n"); + c3_free(log_u); + return 0; + } + c3_d* sot_d = c3_malloc(len_z * sizeof(*sot_d)); + u3_disk_epoc_list(log_u, sot_d); -#if defined(DISK_TRACE_JAM) || defined(DISK_TRACE_CUE) - u3t_trace_open(pax_c); -#endif + fprintf(stderr, "disk: latest epoch is 0i%" PRIc3_d " is bogus; " + "falling back to previous at 0i%" PRIc3_d "\r\n", + lat_d, sot_d[1]); + + u3_disk_epoc_kill(log_u, lat_d); + + lat_d = sot_d[1]; + try_o = c3y; + c3_free(sot_d); + goto try_init; + } break; + + case _epoc_fail: { + fprintf(stderr, "failed to load epoch\r\n"); + c3_free(log_u); + return 0; + } break; - return log_u; + case _epoc_late: { + fprintf(stderr, "upgrade runtime version\r\n"); + c3_free(log_u); + return 0; + } + } + } + } } From 7149079ee6c74729f2779878b3691bef8934f1d5 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sun, 8 Oct 2023 01:00:37 -0400 Subject: [PATCH 85/87] u3: use unchecked head/tail access in u3r_cell() --- pkg/noun/retrieve.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/noun/retrieve.h b/pkg/noun/retrieve.h index 875b54f606..0b77708b47 100644 --- a/pkg/noun/retrieve.h +++ b/pkg/noun/retrieve.h @@ -17,11 +17,14 @@ inline c3_o u3r_cell(u3_noun a, u3_noun* b, u3_noun* c) { + u3a_cell* cel_u; + u3_assert(u3_none != a); if ( c3y == u3a_is_cell(a) ) { - if ( b ) *b = u3a_h(a); // XX use unchecked - if ( c ) *c = u3a_t(a); + cel_u = u3a_to_ptr(a); + if ( b ) *b = cel_u->hed; + if ( c ) *c = cel_u->tel; return c3y; } else { From be185b511c22e6755956d579072b3cf6222d9f0a Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 9 Oct 2023 10:36:55 -0400 Subject: [PATCH 86/87] u3: declares %139 jets for +scot and +scow --- pkg/noun/jets/tree.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/noun/jets/tree.c b/pkg/noun/jets/tree.c index c15e29ba8e..b0264327d1 100644 --- a/pkg/noun/jets/tree.c +++ b/pkg/noun/jets/tree.c @@ -2224,11 +2224,8 @@ static u3j_core _139_qua_d[] = { "mole", 7, _140_qua_mole_a, 0, no_hashes }, { "mule", 7, _140_qua_mule_a, 0, no_hashes }, - // XX disabled, implicated in memory corruption - // write tests and re-enable - // - // { "scot", 7, _140_qua_scot_a, 0, no_hashes }, - // { "scow", 7, _140_qua_scow_a, 0, no_hashes }, + { "scot", 7, _140_qua_scot_a, 0, no_hashes }, + { "scow", 7, _140_qua_scow_a, 0, no_hashes }, { "slaw", 7, _140_qua_slaw_a, 0, no_hashes }, {} }; From ce999cd476e1be3d1be12a779d79098ea8d04642 Mon Sep 17 00:00:00 2001 From: pkova Date: Thu, 19 Oct 2023 22:07:50 +0300 Subject: [PATCH 87/87] ames: resolve galaxy ips using ipv4 only --- pkg/vere/io/ames.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 24baa6e042..6df308239b 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1030,17 +1030,9 @@ _ames_czar_cb(uv_getaddrinfo_t* adr_u, struct addrinfo* rai_u = aif_u; time_t now = time(0); - while ( rai_u ) { - if ( (AF_INET == rai_u->ai_family) ) { - _ames_czar_here(pac_u, now, (struct sockaddr_in *)rai_u->ai_addr); - break; - } - else { - rai_u = rai_u->ai_next; - } - } - - if ( !rai_u ) { + if ( sas_i == 0 ) { + _ames_czar_here(pac_u, now, (struct sockaddr_in *)rai_u->ai_addr); + } else { _ames_czar_gone(pac_u, now); } } @@ -1128,9 +1120,13 @@ _ames_czar(u3_pact* pac_u) uv_getaddrinfo_t* adr_u = c3_malloc(sizeof(*adr_u)); adr_u->data = pac_u; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // only IPv4 addresses + if ( 0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _ames_czar_cb, - pac_u->rut_u.dns_c, 0, 0)) ) + pac_u->rut_u.dns_c, 0, &hints)) ) { u3l_log("ames: %s", uv_strerror(sas_i)); _ames_czar_gone(pac_u, now);