diff --git a/VERSION b/VERSION index 8c2691509e..37989bd16b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.9 +2.10 diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 7922c40604..efb506f072 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -446,6 +446,7 @@ _ce_patch_verify(u3_ce_patch* pat_u) c3_w pag_w, mug_w; c3_y buf_y[_ce_page]; c3_zs ret_zs; + c3_o sou_o = c3n; // south seen if ( U3E_VERLAT != pat_u->con_u->ver_w ) { fprintf(stderr, "loom: patch version mismatch: have %"PRIc3_w", need %u\r\n", @@ -454,6 +455,12 @@ _ce_patch_verify(u3_ce_patch* pat_u) return c3n; } + if ( pat_u->con_u->sou_w > 1 ) { + fprintf(stderr, "loom: patch strange south size: %u\r\n", + pat_u->con_u->sou_w); + return c3n; + } + for ( c3_z i_z = 0; i_z < pat_u->con_u->pgs_w; i_z++ ) { pag_w = pat_u->con_u->mem_u[i_z].pag_w; mug_w = pat_u->con_u->mem_u[i_z].mug_w; @@ -485,6 +492,16 @@ _ce_patch_verify(u3_ce_patch* pat_u) } #endif } + + if ( pag_w >= pat_u->con_u->nor_w ) { + if ( c3n == sou_o ) { + sou_o = c3y; + } + else { + fprintf(stderr, "loom: patch multiple south pages\r\n"); + return c3n; + } + } } return c3y; } @@ -755,9 +772,12 @@ _ce_patch_apply(u3_ce_patch* pat_u) fid_i = u3P.nor_u.fid_i; off_z = _ce_len(pag_w); } + // NB: this assumes that there never more than one south page, + // as enforced by _ce_patch_verify() + // else { fid_i = u3P.sou_u.fid_i; - off_z = _ce_len((u3P.pag_w - (pag_w + 1))); + off_z = 0; } if ( _ce_page != (ret_zs = read(pat_u->mem_i, buf_y, _ce_page)) ) { diff --git a/pkg/noun/jets/a/max.c b/pkg/noun/jets/a/max.c new file mode 100644 index 0000000000..929ee501d4 --- /dev/null +++ b/pkg/noun/jets/a/max.c @@ -0,0 +1,61 @@ +/// @file + +#include "jets/k.h" +#include "jets/q.h" +#include "jets/w.h" + +#include "noun.h" + +u3_noun +u3qa_max(u3_atom a, u3_atom b) +{ + if ( _(u3a_is_cat(a)) && _(u3a_is_cat(b)) ) { + return u3k(c3_max(a, b)); + } + else { + c3_w a_w = u3r_met(0, a); + c3_w b_w = u3r_met(0, b); + + if ( a_w != b_w ) { + return u3k((a_w > b_w) ? a : b); + } + else { + mpz_t a_mp, b_mp; + u3_noun max; + + u3r_mp(a_mp, a); + u3r_mp(b_mp, b); + + max = (mpz_cmp(a_mp, b_mp) > 0) ? a : b; + + mpz_clear(a_mp); + mpz_clear(b_mp); + + return u3k(max); + } + } +} + +u3_noun +u3wa_max(u3_noun cor) +{ + u3_noun a, b; + + if ( (c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0)) + || (c3n == u3ud(b) && 0 != a) + || (c3n == u3ud(a) && 0 != b) ) + { + return u3m_bail(c3__exit); + } + else { + return u3qa_max(a, b); + } +} + +u3_noun +u3ka_max(u3_noun a, u3_noun b) +{ + u3_noun c = u3qa_max(a, b); + u3z(a); u3z(b); + return c; +} diff --git a/pkg/noun/jets/a/min.c b/pkg/noun/jets/a/min.c new file mode 100644 index 0000000000..243c50bb6e --- /dev/null +++ b/pkg/noun/jets/a/min.c @@ -0,0 +1,61 @@ +/// @file + +#include "jets/k.h" +#include "jets/q.h" +#include "jets/w.h" + +#include "noun.h" + +u3_noun +u3qa_min(u3_atom a, u3_atom b) +{ + if ( _(u3a_is_cat(a)) && _(u3a_is_cat(b)) ) { + return u3k(c3_min(a, b)); + } + else { + c3_w a_w = u3r_met(0, a); + c3_w b_w = u3r_met(0, b); + + if ( a_w != b_w ) { + return u3k((a_w < b_w) ? a : b); + } + else { + mpz_t a_mp, b_mp; + u3_noun min; + + u3r_mp(a_mp, a); + u3r_mp(b_mp, b); + + min = (mpz_cmp(a_mp, b_mp) < 0) ? a : b; + + mpz_clear(a_mp); + mpz_clear(b_mp); + + return u3k(min); + } + } +} + +u3_noun +u3wa_min(u3_noun cor) +{ + u3_noun a, b; + + if ( (c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0)) + || (c3n == u3ud(b) && 0 != a) + || (c3n == u3ud(a) && 0 != b) ) + { + return u3m_bail(c3__exit); + } + else { + return u3qa_min(a, b); + } +} + +u3_noun +u3ka_min(u3_noun a, u3_noun b) +{ + u3_noun c = u3qa_min(a, b); + u3z(a); u3z(b); + return c; +} diff --git a/pkg/noun/jets/k.h b/pkg/noun/jets/k.h index b18db58b47..f4587bef58 100644 --- a/pkg/noun/jets/k.h +++ b/pkg/noun/jets/k.h @@ -11,6 +11,8 @@ u3_noun u3ka_dec(u3_atom a); u3_noun u3ka_div(u3_noun a, u3_noun b); u3_noun u3ka_sub(u3_noun a, u3_noun b); + u3_noun u3ka_max(u3_noun a, u3_noun b); + u3_noun u3ka_min(u3_noun a, u3_noun b); u3_noun u3ka_mod(u3_noun a, u3_noun b); u3_noun u3ka_mul(u3_noun a, u3_noun b); u3_noun u3ka_gth(u3_noun a, u3_noun b); diff --git a/pkg/noun/jets/q.h b/pkg/noun/jets/q.h index e9c8bfd9b3..33c63ef42b 100644 --- a/pkg/noun/jets/q.h +++ b/pkg/noun/jets/q.h @@ -15,6 +15,8 @@ u3_noun u3qa_inc(u3_atom); u3_noun u3qa_lte(u3_atom, u3_atom); u3_noun u3qa_lth(u3_atom, u3_atom); + u3_noun u3qa_max(u3_atom, u3_atom); + u3_noun u3qa_min(u3_atom, u3_atom); u3_noun u3qa_mod(u3_atom, u3_atom); u3_noun u3qa_mul(u3_atom, u3_atom); u3_noun u3qa_sub(u3_atom, u3_atom); diff --git a/pkg/noun/jets/tree.c b/pkg/noun/jets/tree.c index f6233cd74d..c15e29ba8e 100644 --- a/pkg/noun/jets/tree.c +++ b/pkg/noun/jets/tree.c @@ -2059,6 +2059,16 @@ static c3_c* _140_one_lth_ha[] = { "39260325faffbbf5bd88c4abb3efb09c5a7e1deb81a2126498d6c0f49474955e", 0 }; +static u3j_harm _140_one_max_a[] = {{".2", u3wa_max, c3y}, {}}; +static c3_c* _140_one_max_ha[] = { + "39260325faffbbf5bd88c4abb3efb09c5a7e1deb81a2126498d6c0f49474955e", + 0 +}; +static u3j_harm _140_one_min_a[] = {{".2", u3wa_min, c3y}, {}}; +static c3_c* _140_one_min_ha[] = { + "39260325faffbbf5bd88c4abb3efb09c5a7e1deb81a2126498d6c0f49474955e", + 0 +}; static u3j_harm _140_one_mod_a[] = {{".2", u3wa_mod, c3y}, {}}; static c3_c* _140_one_mod_ha[] = { "374d2f3cd0ece33f680bd7103b99891d7dae03590f9eb9faac03a4a501f17038", @@ -2102,6 +2112,8 @@ static u3j_core _140_one_d[] = { "gth", 7, _140_one_gth_a, 0, _140_one_gth_ha }, { "lte", 7, _140_one_lte_a, 0, _140_one_lte_ha }, { "lth", 7, _140_one_lth_a, 0, _140_one_lth_ha }, + { "max", 7, _140_one_max_a, 0, _140_one_max_ha }, + { "min", 7, _140_one_min_a, 0, _140_one_min_ha }, { "mod", 7, _140_one_mod_a, 0, _140_one_mod_ha }, { "mul", 7, _140_one_mul_a, 0, _140_one_mul_ha }, { "sub", 7, _140_one_sub_a, 0, _140_one_sub_ha }, @@ -2330,6 +2342,8 @@ static u3j_core _139_one_d[] = { "gth", 7, _140_one_gth_a, 0, no_hashes }, { "lte", 7, _140_one_lte_a, 0, no_hashes }, { "lth", 7, _140_one_lth_a, 0, no_hashes }, + { "max", 7, _140_one_max_a, 0, no_hashes }, + { "min", 7, _140_one_min_a, 0, no_hashes }, { "mod", 7, _140_one_mod_a, 0, no_hashes }, { "mul", 7, _140_one_mul_a, 0, no_hashes }, { "sub", 7, _140_one_sub_a, 0, no_hashes }, diff --git a/pkg/noun/jets/w.h b/pkg/noun/jets/w.h index 2898e0b6e6..d838416c03 100644 --- a/pkg/noun/jets/w.h +++ b/pkg/noun/jets/w.h @@ -14,6 +14,8 @@ u3_noun u3wa_gth(u3_noun); u3_noun u3wa_lte(u3_noun); u3_noun u3wa_lth(u3_noun); + u3_noun u3wa_max(u3_noun); + u3_noun u3wa_min(u3_noun); u3_noun u3wa_mod(u3_noun); u3_noun u3wa_mul(u3_noun); u3_noun u3wa_sub(u3_noun); diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 033fba7a5f..722c77992e 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1748,11 +1748,12 @@ _fine_hear_request(u3_pact* req_u, c3_w cur_w) // look up request in scry cache // c3_w fra_w = res_u->pur_u.pep_u.fra_w; - u3_weak cac = _fine_get_cache(sam_u, key, fra_w); + c3_w lop_w = _fine_lop(fra_w); + u3_weak pec = _fine_get_cache(sam_u, key, lop_w); // already pending; drop // - if ( FINE_PEND == cac ) { + if ( FINE_PEND == pec ) { if ( u3C.wag_w & u3o_verbose ) { u3l_log("fine: pend %u %s", res_u->pur_u.pep_u.fra_w, res_u->pur_u.pep_u.pat_c); @@ -1761,42 +1762,45 @@ _fine_hear_request(u3_pact* req_u, c3_w cur_w) } // cache miss or a previous scry blocked; try again // - else if ( (u3_none == cac) || (FINE_DEAD == cac) ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("fine: miss %u %s", res_u->pur_u.pep_u.fra_w, - res_u->pur_u.pep_u.pat_c); - } - - c3_w lop_w = _fine_lop(fra_w); - u3_noun pax = - u3nc(c3__fine, - u3nq(c3__hunk, - u3dc("scot", c3__ud, u3i_word(lop_w)), - u3dc("scot", c3__ud, FINE_PAGE), - u3k(key))); - - // mark as pending in the scry cache - // - _fine_put_cache(res_u->sam_u, key, lop_w, FINE_PEND); - - // scry into arvo for a page of packets - // - u3_pier_peek_last(res_u->sam_u->car_u.pir_u, u3_nul, c3__ax, u3_nul, - pax, res_u, _fine_hunk_scry_cb); - } - // cache hit, fill in response meow and send - // - else if ( c3y == _fine_sift_meow(&res_u->pur_u.mew_u, u3k(cac)) ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("fine: hit %u %s", res_u->pur_u.pep_u.fra_w, - res_u->pur_u.pep_u.pat_c); - } - _fine_etch_response(res_u); - _ames_try_send(res_u, c3n); - } else { - u3l_log("fine: _fine_hear_request meow bad"); - _ames_pact_free(res_u); + u3_weak cac = _fine_get_cache(sam_u, key, fra_w); + + if ( (u3_none == cac) || (FINE_DEAD == cac) ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("fine: miss %u %s", res_u->pur_u.pep_u.fra_w, + res_u->pur_u.pep_u.pat_c); + } + + u3_noun pax = + u3nc(c3__fine, + u3nq(c3__hunk, + u3dc("scot", c3__ud, u3i_word(lop_w)), + u3dc("scot", c3__ud, FINE_PAGE), + u3k(key))); + + // mark as pending in the scry cache + // + _fine_put_cache(res_u->sam_u, key, lop_w, FINE_PEND); + + // scry into arvo for a page of packets + // + u3_pier_peek_last(res_u->sam_u->car_u.pir_u, u3_nul, c3__ax, u3_nul, + pax, res_u, _fine_hunk_scry_cb); + } + // cache hit, fill in response meow and send + // + else if ( c3y == _fine_sift_meow(&res_u->pur_u.mew_u, u3k(cac)) ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("fine: hit %u %s", res_u->pur_u.pep_u.fra_w, + res_u->pur_u.pep_u.pat_c); + } + _fine_etch_response(res_u); + _ames_try_send(res_u, c3n); + } + else { + u3l_log("fine: _fine_hear_request meow bad"); + _ames_pact_free(res_u); + } } u3z(key); diff --git a/pkg/vere/main.c b/pkg/vere/main.c index bb5b514bcc..0f552b0252 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -2002,7 +2002,7 @@ _cw_play(c3_i argc, c3_c* argv[]) { "no-demand", no_argument, NULL, 6 }, { "auto-meld", no_argument, NULL, 7 }, { "soft-mugs", no_argument, NULL, 8 }, - { "full", required_argument, NULL, 'f' }, + { "full", no_argument, NULL, 'f' }, { "replay-to", required_argument, NULL, 'n' }, { "snap-at", required_argument, NULL, 's' }, { NULL, 0, NULL, 0 } @@ -2124,10 +2124,9 @@ _cw_play(c3_i argc, c3_c* argv[]) 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); - u3e_yolo(); + u3m_foul(); u3m_pave(c3y); u3j_boot(c3y); - u3A->eve_d = 0; } else { u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); diff --git a/pkg/vere/mars.c b/pkg/vere/mars.c index b15de5919f..37933bd49e 100644 --- a/pkg/vere/mars.c +++ b/pkg/vere/mars.c @@ -68,6 +68,13 @@ _mars_poke_play(u3_mars* mar_u, const u3_fact* tac_u) return u3_none; } +/* _mars_show_time(): print date, truncated to seconds. +*/ +static u3_noun +_mars_show_time(u3_noun wen) +{ + return u3dc("scot", c3__da, u3kc_lsh(6, 1, u3kc_rsh(6, 1, wen))); +} typedef enum { _play_yes_e, // success @@ -78,15 +85,19 @@ typedef enum { _play_bad_e // total failure } _mars_play_e; -/* _mars_play_batch(): replay a batch of events. +/* _mars_play_batch(): replay a batch of events, return status and batch date. */ static _mars_play_e -_mars_play_batch(u3_mars* mar_u, c3_o mug_o, c3_w bat_w) +_mars_play_batch(u3_mars* mar_u, + c3_o mug_o, + c3_w bat_w, + c3_c** wen_c) { u3_disk* log_u = mar_u->log_u; u3_disk_walk* wok_u = u3_disk_walk_init(log_u, mar_u->dun_d + 1, bat_w); u3_fact tac_u; u3_noun dud; + u3_weak wen = u3_none; while ( c3y == u3_disk_walk_live(wok_u) ) { if ( c3n == u3_disk_walk_step(wok_u, &tac_u) ) { @@ -96,6 +107,10 @@ _mars_play_batch(u3_mars* mar_u, c3_o mug_o, c3_w bat_w) u3_assert( ++mar_u->sen_d == tac_u.eve_d ); + if ( u3_none == wen ) { + wen = _mars_show_time(u3k(u3h(tac_u.job))); + } + if ( u3_none != (dud = _mars_poke_play(mar_u, &tac_u)) ) { c3_m mot_m; @@ -107,25 +122,26 @@ _mars_play_batch(u3_mars* mar_u, c3_o mug_o, c3_w bat_w) switch ( mot_m ) { case c3__meme: { fprintf(stderr, "play (%" PRIu64 "): %%meme\r\n", tac_u.eve_d); - u3z(dud); + u3z(dud); u3z(wen); return _play_mem_e; } case c3__intr: { fprintf(stderr, "play (%" PRIu64 "): %%intr\r\n", tac_u.eve_d); - u3z(dud); + u3z(dud); u3z(wen); return _play_int_e; } case c3__awry: { fprintf(stderr, "play (%" PRIu64 "): %%awry\r\n", tac_u.eve_d); - u3z(dud); + u3z(dud); u3z(wen); return _play_mug_e; } default: { fprintf(stderr, "play (%" PRIu64 "): failed\r\n", tac_u.eve_d); u3_pier_punt_goof("play", dud); + u3z(wen); // XX say something uplifting // return _play_bad_e; @@ -138,6 +154,8 @@ _mars_play_batch(u3_mars* mar_u, c3_o mug_o, c3_w bat_w) u3_disk_walk_done(wok_u); + *wen_c = u3r_string(wen); + u3z(wen); return _play_yes_e; } @@ -239,27 +257,45 @@ u3_mars_play(u3_mars* mar_u, c3_d eve_d, c3_d sap_d) } { - c3_d pas_d = mar_u->dun_d; // last snapshot - c3_d mem_d = 0; // last event to meme - c3_w try_w = 0; // [mem_d] retry count + c3_d pas_d = mar_u->dun_d; // last snapshot + c3_d mem_d = 0; // last event to meme + c3_w try_w = 0; // [mem_d] retry count + c3_c* wen_c; while ( mar_u->dun_d < eve_d ) { _mars_step_trace(mar_u->dir_c); // XX get batch from args // - switch ( _mars_play_batch(mar_u, c3y, 1024) ) { + switch ( _mars_play_batch(mar_u, c3y, 1024, &wen_c) ) { case _play_yes_e: { + c3_c* now_c; + + { + u3_noun now; + struct timeval tim_u; + gettimeofday(&tim_u, 0); + + now = _mars_show_time(u3_time_in_tv(&tim_u)); + now_c = u3r_string(now); + u3z(now); + } + u3m_reclaim(); if ( sap_d && ((mar_u->dun_d - pas_d) >= sap_d) ) { u3m_save(); pas_d = mar_u->dun_d; - u3l_log("play (%" PRIu64 "): save", mar_u->dun_d); + u3l_log("play (%" PRIu64 "): save (%s, now=%s)", + mar_u->dun_d, wen_c, now_c); } else { - u3l_log("play (%" PRIu64 "): done", mar_u->dun_d); + u3l_log("play (%" PRIu64 "): done (%s, now=%s)", + mar_u->dun_d, wen_c, now_c); } + + c3_free(now_c); + c3_free(wen_c); } break; case _play_mem_e: {