diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index 676502461..15320ea06 100644 --- a/pkg/urbit/include/c/motes.h +++ b/pkg/urbit/include/c/motes.h @@ -1226,6 +1226,7 @@ # define c3__weak c3_s4('w','e','a','k') # define c3__web c3_s3('w','e','b') # define c3__wet c3_s3('w','e','t') +# define c3__wend c3_s4('w','e','n','d') # define c3__werp c3_s4('w','e','r','p') # define c3__west c3_s4('w','e','s','t') # define c3__what c3_s4('w','h','a','t') diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index de62a3fdd..68374e590 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -542,8 +542,9 @@ u3_psat_init = 0, // initialized u3_psat_boot = 1, // bootstrap u3_psat_play = 2, // replaying - u3_psat_work = 3, // working - u3_psat_done = 4 // shutting down + u3_psat_wyrd = 3, // versioning + u3_psat_work = 4, // working + u3_psat_done = 5 // shutting down } u3_psat; /* u3_boot: bootstrap event sequence diff --git a/pkg/urbit/vere/io/hind.c b/pkg/urbit/vere/io/hind.c index 37d090399..b8b1577ee 100644 --- a/pkg/urbit/vere/io/hind.c +++ b/pkg/urbit/vere/io/hind.c @@ -53,6 +53,14 @@ _hind_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) ret_o = c3y; u3l_log("<<>>\n"); } break; + + // NB: startup explicitly handled in pier.c + // + // XX review arvo upgrade scenaria + // + case c3__wend: { + ret_o = c3y; + } break; } } diff --git a/pkg/urbit/vere/lord.c b/pkg/urbit/vere/lord.c index f148f1c69..394cb6c5e 100644 --- a/pkg/urbit/vere/lord.c +++ b/pkg/urbit/vere/lord.c @@ -1090,6 +1090,7 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) { u3_lord* god_u = c3_calloc(sizeof *god_u); god_u->liv_o = c3n; + god_u->pin_o = c3n; god_u->wag_w = wag_w; god_u->bin_c = u3_Host.wrk_c; // XX strcopy god_u->pax_c = pax_c; // XX strcopy diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index 41b48fc09..2130a540b 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -285,7 +285,8 @@ _pier_on_lord_work_spin(void* ptr_v, u3_atom pin, c3_o del_o) { u3_pier* pir_u = ptr_v; - c3_assert( (u3_psat_work == pir_u->sat_e) + c3_assert( (u3_psat_wyrd == pir_u->sat_e) + || (u3_psat_work == pir_u->sat_e) || (u3_psat_done == pir_u->sat_e) ); u3_term_start_spinner(pin, del_o); @@ -298,7 +299,8 @@ _pier_on_lord_work_spun(void* ptr_v) { u3_pier* pir_u = ptr_v; - c3_assert( (u3_psat_work == pir_u->sat_e) + c3_assert( (u3_psat_wyrd == pir_u->sat_e) + || (u3_psat_work == pir_u->sat_e) || (u3_psat_done == pir_u->sat_e) ); u3_term_stop_spinner(); @@ -402,13 +404,14 @@ u3_pier_spin(u3_pier* pir_u) { // XX return c3n instead? // - c3_assert( (u3_psat_work == pir_u->sat_e) - || (u3_psat_done == pir_u->sat_e) ); + if ( u3_psat_work == pir_u->sat_e + || u3_psat_done == pir_u->sat_e ) + { + u3_work* wok_u = pir_u->wok_u; - u3_work* wok_u = pir_u->wok_u; - - if ( !uv_is_active((uv_handle_t*)&wok_u->idl_u) ) { - uv_idle_start(&wok_u->idl_u, _pier_work_idle_cb); + if ( !uv_is_active((uv_handle_t*)&wok_u->idl_u) ) { + uv_idle_start(&wok_u->idl_u, _pier_work_idle_cb); + } } } @@ -488,8 +491,7 @@ _pier_work_init(u3_pier* pir_u) { u3_work* wok_u; - c3_assert( (u3_psat_init == pir_u->sat_e) - || (u3_psat_play == pir_u->sat_e) ); + c3_assert( u3_psat_wyrd == pir_u->sat_e ); pir_u->sat_e = u3_psat_work; pir_u->wok_u = wok_u = c3_calloc(sizeof(*wok_u)); @@ -552,6 +554,206 @@ _pier_work_init(u3_pier* pir_u) _pier_work(wok_u); } +/* _pier_wyrd_good(): %wyrd version negotation succeeded. +*/ +static void +_pier_wyrd_good(u3_pier* pir_u, u3_ovum* egg_u, u3_gift* gif_u) +{ + // restore event callbacks + // + { + u3_lord* god_u = pir_u->god_u; + god_u->cb_u.work_done_f = _pier_on_lord_work_done; + god_u->cb_u.work_bail_f = _pier_on_lord_work_bail; + } + + // initialize i/o drivers + // + _pier_work_init(pir_u); + + // plan %wyrd effects + // + _pier_gift_plan(pir_u->wok_u, gif_u); + + // free %wyrd driver and ovum + // + { + u3_auto* car_u = egg_u->car_u; + u3_auto_done(egg_u); + c3_free(car_u); + } +} + +/* _pier_wyrd_fail(): %wyrd version negotation failed. +*/ +static void +_pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) +{ + // XX version negotiation failed, print upgrade message + // + u3l_log("pier: version negotation failed\n\n"); + + // XX only print trace with -v ? + // + u3_auto_bail_slog(egg_u, lud); + + // free %wyrd driver and ovum + // + { + u3_auto* car_u = egg_u->car_u; + u3_auto_done(egg_u); + c3_free(car_u); + } + + u3_pier_bail(pir_u); +} + +// XX organizing version constants +// +#define VERE_NAME "vere" +#define VERE_MAJOR 0 +#define VERE_MINOR 10 +#define VERE_PATCH 9 +#define VERE_ZUSE 309 + +/* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN +*/ +static c3_o +_pier_wyrd_aver(u3_noun act) +{ + u3_noun fec, kel, ver; + + // XX review, %wend re: %wyrd optional? + // + while ( u3_nul != act ) { + u3x_cell(act, &fec, &act); + + if ( c3__wend == u3h(fec) ) { + kel = u3t(fec); + + // traverse $wynn, check for downgrades + // + while ( u3_nul != kel ) { + u3x_cell(kel, &ver, &kel); + + // check for %zuse downgrade + // + if ( (c3__zuse == u3h(ver)) + && (VERE_ZUSE != u3t(ver)) ) + { + return c3n; + } + + // XX in the future, send %wend to serf + // to also negotiate downgrade of nock/hoon/&c? + // (we don't want to have to filter effects) + // + } + } + } + + return c3y; +} + +/* _pier_on_lord_wyrd_done(): callback for successful %wyrd event. +*/ +static void +_pier_on_lord_wyrd_done(void* ptr_v, + u3_ovum* egg_u, + u3_fact* tac_u, + u3_gift* gif_u) +{ + u3_pier* pir_u = ptr_v; + + c3_assert( u3_psat_wyrd == pir_u->sat_e ); + + // arvo's side of version negotiation succeeded + // traverse [gif_y] and validate + // + if ( c3n == _pier_wyrd_aver(gif_u->act) ) { + u3_fact_free(tac_u); + u3_gift_free(gif_u); + + // XX messageing + // + u3l_log("pier: version negotiation failed; downgrade\n"); + _pier_wyrd_fail(pir_u, egg_u, u3_nul); + } + else { + // enqueue %wyrd event-log commit + // + u3_disk_plan(pir_u->log_u, tac_u); + + // finalize %wyrd success + // + _pier_wyrd_good(pir_u, egg_u, gif_u); + } +} + +/* _pier_on_lord_wyrd_bail(): callback for failed %wyrd event. +*/ +static void +_pier_on_lord_wyrd_bail(void* ptr_v, u3_ovum* egg_u, u3_noun lud) +{ + u3_pier* pir_u = ptr_v; + + c3_assert( u3_psat_wyrd == pir_u->sat_e ); + + // print %wyrd failure and exit + // + // XX check bail mote, retry on %intr, %meme, &c + // + _pier_wyrd_fail(pir_u, egg_u, lud); +} + +/* _pier_wyrd_init(): send %wyrd. +*/ +static void +_pier_wyrd_init(u3_pier* pir_u) +{ + u3_lord* god_u = pir_u->god_u; + + pir_u->sat_e = u3_psat_wyrd; + + u3l_log("vere: checking version compatiblity\n"); + + _pier_work_time(pir_u); + u3v_numb(); + + { + u3_noun ver = u3nq(u3i_string(VERE_NAME), VERE_MAJOR, VERE_MINOR, VERE_PATCH); + u3_noun kel = u3nl(u3nc(c3__zuse, VERE_ZUSE), // XX god_u->zus_w + // u3nc(c3__lull, PIER_LULL), // XX define + // u3nc(c3__arvo, god_u->arv_y), // XX from both king and serf? + u3nc(c3__hoon, god_u->hon_y), + u3nc(c3__nock, god_u->noc_y), + u3_none); + u3_noun wir = u3nc(c3__arvo, u3_nul); + u3_noun cad = u3nt(c3__wyrd, u3nc(u3k(u3A->sen), ver), kel); + + { + u3_auto* car_u = c3_calloc(sizeof(*car_u)); + u3_ovum* egg_u = u3_ovum_init(0, u3_blip, wir, cad); + u3_noun ovo; + + car_u->pir_u = pir_u; + car_u->nam_m = c3__wyrd; + + u3_auto_plan(car_u, egg_u); + + // instead of subscribing with u3_auto_peer(), + // we swizzle the [god_u] callbacks for full control + // + god_u->cb_u.work_done_f = _pier_on_lord_wyrd_done; + god_u->cb_u.work_bail_f = _pier_on_lord_wyrd_bail; + + c3_assert( u3_auto_next(car_u, &ovo) == egg_u ); + + u3_lord_work(god_u, egg_u, ovo); + } + } +} + /* _pier_play_plan(): enqueue events for replay. */ static void @@ -730,7 +932,7 @@ _pier_play(u3_play* pay_u) } else if ( pay_u->eve_d == log_u->dun_d ) { u3_lord_save(pir_u->god_u); - _pier_work_init(pir_u); + _pier_wyrd_init(pir_u); } } else { @@ -1188,7 +1390,7 @@ _pier_on_lord_live(void* ptr_v) _pier_play_init(pir_u, eve_d); } else { - _pier_work_init(pir_u); + _pier_wyrd_init(pir_u); } } }