Merge remote-tracking branch 'cgyarvin/revere-next'

New event system. Command line options are temporarily out of order;
please use the exact same command to restart an urbit that you did to
start it, including the -c, -A, and -B options.
This commit is contained in:
Raymond Pasco 2017-02-07 12:29:38 -08:00
commit 2be28943fd
34 changed files with 43578 additions and 4397 deletions

View File

@ -66,6 +66,7 @@ CURLLIB=$(shell curl-config --libs)
RM=rm -f
CC=cc
LN=ln -f
CXX=c++
CXXFLAGS=$(CFLAGS)
CLD=c++ $(CFLAGS) -L/usr/local/lib $(OPTLOCALLFLAGS) $(OPENSSLLFLAGS)
@ -349,15 +350,17 @@ V_OFILES=\
vere/behn.o \
vere/cttp.o \
vere/http.o \
vere/loop.o \
vere/raft.o \
vere/newt.o \
vere/reck.o \
vere/sist.o \
vere/term.o \
vere/time.o \
vere/unix.o \
vere/save.o \
vere/walk.o
vere/serf.o \
vere/pier.o \
vere/foil.o \
vere/walk.o \
vere/ivory.o
MAIN_FILE =\
vere/main.o
@ -388,7 +391,7 @@ TAGS=\
GPATH GTAGS GRTAGS \
cscope.in.out cscope.po.out cscope.out
all: urbit
all: urbit links
.MAKEFILE-VERSION: Makefile .make.conf
@echo "Makefile update."
@ -397,6 +400,9 @@ all: urbit
.make.conf:
@echo "# Set custom configuration here, please!" > ".make.conf"
links: urbit
$(LN) $(BIN)/urbit $(BIN)/urbit-worker
urbit: $(BIN)/urbit
$(LIBED25519):

View File

@ -90,3 +90,5 @@
c3_assert(!"memory lost"); \
} \
rut;})
#define c3_free(s) free(s)
#define c3_realloc(s, l) realloc(s, l)

View File

@ -187,5 +187,10 @@
# define c3_rand(rd) (getentropy((void*)rd, 64) == 0 ? \
(void)0 : c3_assert(!"ent"))
# else
# define c3_rand u3_sist_rand
# define c3_rand u3_pier_rand
# endif
# if defined(U3_OS_linux)
# define DEVRANDOM "/dev/urandom"
# else
# define DEVRANDOM "/dev/random"
# endif

View File

@ -73,6 +73,11 @@
c3_o
u3e_live(c3_o nuu_o, c3_c* dir_c);
/* u3e_live_new(): start the persistence system.
*/
c3_o
u3e_live_new(c3_c* dir_c);
/* u3e_dirty(): count dirty pages.
*/
c3_w

View File

@ -10,7 +10,7 @@
*/
u3_noun
u3i_words(c3_w a_w,
const c3_w* b_w);
const c3_w* b_w);
/* u3i_bytes():
**
@ -18,7 +18,7 @@
*/
u3_noun
u3i_bytes(c3_w a_w,
const c3_y* b_y);
const c3_y* b_y);
/* u3i_mp():
**
@ -76,7 +76,7 @@
*/
u3_atom
u3i_chubs(c3_w a_w,
const c3_d* b_d);
const c3_d* b_d);
/* u3i_tape(): from a C string, to a list of bytes.
*/

View File

@ -7,7 +7,18 @@
/* u3m_boot(): start the u3 system.
*/
void
u3m_boot(c3_o nuu_o, c3_o bug_o, c3_c* dir_c, c3_c *pil_c);
u3m_boot(c3_o nuu_o, c3_c* dir_c, c3_c *pil_c);
/* u3m_boot_new(): start the u3 system (new). return next event,
** starting from 1.
*/
c3_d
u3m_boot_new(c3_c* dir_c);
/* u3m_boot_pier(): start without checkpointing.
*/
c3_d
u3m_boot_pier(void);
/* u3m_bail(): bail out. Does not return.
**

View File

@ -409,6 +409,16 @@
c3_w* c_w,
u3_atom d);
/* u3r_chubs():
**
** Copy double-words (a_w) through (a_w + b_w - 1) from (d) to (c).
*/
void
u3r_chubs(c3_w a_w,
c3_w b_w,
c3_d* c_d,
u3_atom d);
/* u3r_string(): `a`, a text atom, as malloced C string.
*/
c3_c*

View File

@ -31,6 +31,7 @@
u3_noun roe; // temporary unsaved events
u3_noun key; // log key, or 0
u3_noun sys; // system pill
u3_noun ken; // kernel formula
u3_noun roc; // kernel core
@ -69,6 +70,11 @@
void
u3v_boot(c3_c* pas_c);
/* u3v_boot_lite(): light bootstrap sequence, just making a kernel.
*/
void
u3v_boot_lite(u3_noun lit);
/* u3v_make(): make a new pier by loading a pill.
*/
void

View File

@ -199,6 +199,78 @@
c3_y hun_y[0]; // data
} u3_apac;
/* u3_poke: poke callback function.
*/
typedef void (*u3_poke)(void*, u3_noun);
/* u3_bail: bailout callback function.
*/
typedef void (*u3_bail)(void*, const c3_c* err_c);
/* u3_done: completion function.
*/
typedef void (*u3_done)(void *);
/* u3_mess: blob message in process.
*/
typedef struct _u3_mess {
c3_d len_d; // blob length in bytes
c3_d has_d; // currently held
struct _u3_meat* meq_u; // exit of message queue
struct _u3_meat* qem_u; // entry of message queue
} u3_mess;
/* u3_meat: blob message block.
*/
typedef struct _u3_meat {
struct _u3_meat* nex_u;
c3_d len_d;
c3_y hun_y[0];
} u3_meat;
/* u3_moat: inbound message stream.
*/
typedef struct _u3_moat {
uv_pipe_t pyp_u; // input stream
void* vod_p; // callback pointer
u3_poke pok_f; // action function
u3_bail bal_f; // error response function
struct _u3_mess* mes_u; // message in progress
c3_d len_d; // length of stray bytes
c3_y* rag_y; // stray bytes
} u3_moat;
/* u3_mojo: outbound message stream.
*/
typedef struct _u3_mojo {
uv_pipe_t pyp_u; // output stream
u3_bail bal_f; // error response function
} u3_mojo;
/* u3_foil: abstract chub-addressed file.
*/
typedef struct _u3_foil {
uv_file fil_u; // libuv file handle
struct _u3_dire* dir_u; // parent directory
c3_c* nam_c; // name within parent
c3_d end_d; // end of file
} u3_foil;
/* u3_dent: directory entry.
*/
typedef struct _u3_dent {
c3_c* nam_c;
struct _u3_dent* nex_u;
} u3_dent;
/* u3_dire: simple directory state.
*/
typedef struct _u3_dire {
c3_c* pax_c; // path of directory
uv_file fil_u; // file, opened read-only to fsync
u3_dent* all_u; // file list
} u3_dire;
/* u3_ames: ames networking.
*/
typedef struct _u3_ames { // packet network state
@ -537,16 +609,17 @@
c3_c* tic_c; // -t, ticket value
c3_c* pil_c; // -B, bootstrap from
c3_c* arv_c; // -A, initial sync from
c3_c* lit_c; // -J, ivory (fastboot) kernel
c3_c* gen_c; // -G, czar generator
c3_w kno_w; // -k, kernel version
c3_w fuz_w; // -f, fuzz testing
c3_s por_s; // -p, ames port
c3_s rop_s; // -l, raft port
c3_o abo; // -a
c3_o abo; // -a, abort aggressively
c3_o bat; // -b, batch create
c3_o gab; // -g
c3_o gab; // -g, test garbage collection
c3_o dem; // -d, daemon
c3_o dry; // -D, dry compute
c3_o dry; // -D, dry compute, no checkpoint
c3_o tex; // -x, exit after loading
c3_o fog; // -X, skip last event
c3_o fak; // -F, fake carrier
@ -555,7 +628,7 @@
c3_o veb; // -v, verbose (inverse of -q)
c3_o nuu; // -c, new pier
c3_o qui; // -q, quiet
c3_o vno; // -V, replay without reboots
c3_o vno; // -V, turn on +verb
c3_o mem; // -M, memory madness
c3_o rep; // -R, report build info
} u3_opts;
@ -571,7 +644,6 @@
u3_cttp ctp_u; // http clients
u3_utel tel_u; // telnet listener
u3_utty* uty_u; // linked terminal list
u3_ames sam_u; // packet interface
u3_save sav_u; // autosave
u3_opts ops_u; // commandline options
u3_unix unx_u; // sync and clay
@ -581,15 +653,101 @@
void* ssl_u; // struct SSL_CTX*
} u3_host; // host == computer == process
/** New pier system.
**/
/* u3_writ: inbound event.
*/
typedef struct _u3_writ {
struct _u3_pier* pir_u; // backpointer to pier
u3_noun job; // (pair date ovum)
c3_d evt_d; // event number
u3_noun now; // event time
c3_l msc_l; // ms to timeout
c3_l mug_l; // hash before executing
u3_foil* fol_u; // precommit file
u3_atom mat; // jammed $work, or 0
u3_noun act; // action list
struct _u3_writ* nex_u; // next in queue, or 0
} u3_writ;
/* u3_lord: working process controller.
*/
typedef struct _u3_lord {
uv_process_t cub_u; // process handle
uv_process_options_t ops_u; // process configuration
uv_stdio_container_t cod_u[3]; // process options
time_t wen_t; // process creation time
u3_mojo inn_u; // client's stdin
u3_moat out_u; // client's stdout
c3_d sen_d; // last event dispatched
c3_d dun_d; // last event completed
c3_d rel_d; // last event released
c3_l mug_l; // mug after last completion
struct _u3_pier* pir_u; // pier backpointer
} u3_lord;
/* u3_disk: manage events on disk.
**
** any event once discovered should be in one of these sets.
** at present, all sets are ordered and can be defined by a
** simple counter. any events <= the counter is in the set.
*/
typedef struct _u3_disk {
u3_dire* dir_u; // main pier directory
u3_dire* urb_u; // urbit system data
u3_dire* com_u; // log directory
u3_dire* pre_u; // precommit directory
u3_foil* fol_u; // logfile
c3_d end_d; // byte end of file
c3_d rep_d; // precommit requested
c3_d pre_d; // precommitted
c3_d moc_d; // commit requested
c3_d com_d; // committed
struct _u3_pier* pir_u; // pier backpointer
} u3_disk;
/* u3_boot: startup controller.
*/
typedef struct _u3_boot {
} u3_boot;
/* u3_pier: ship controller.
*/
typedef struct _u3_pier {
c3_c* pax_c; // pier directory
c3_c* sys_c; // pill directory
c3_d gen_d; // last event discovered
c3_d but_d; // boot barrier
c3_d key_d[4]; // save and passkey
u3_disk* log_u; // event log
u3_lord* god_u; // computer
u3_ames* sam_u; // packet interface
u3_writ* ent_u; // entry of queue
u3_writ* ext_u; // exit of queue
} u3_pier;
/* u3_king: all executing piers.
*/
typedef struct _u3_king {
c3_w len_w; // number of lords used
c3_w all_w; // number of lords allocated
u3_pier** tab_u; // lord table
} u3_king;
static u3_king u3K;
# define u3L u3_Host.lup_u // global event loop
# define u3Z (&(u3_Raft))
# define u3S u3_Host.ssl_u
# define u3K u3_King
/** Global variables.
**/
c3_global u3_host u3_Host;
c3_global u3_raft u3_Raft;
c3_global c3_c* u3_Local;
c3_global u3_king u3_King;
/** Functions.
**/
@ -726,17 +884,82 @@
u3_noun
u3_ve_zeus(u3_noun hap);
/** Output.
/** Filesystem (async)
**/
/* u3_ve_tank(): print a tank at `tab`.
/* u3_foil_folder(): load directory, blockingly. create if nonexistent.
*/
u3_dire*
u3_foil_folder(const c3_c* pax_c); // directory object, or 0
/* u3_foil_create(): create a new, empty file, not syncing.
*/
void
u3_ve_tank(c3_l tab_l, u3_noun tac);
u3_foil_create(void (*fun_f)(void*, // context pointer
u3_foil*),// file object
void* vod_p, // context pointer
u3_dire* dir_u, // directory
const c3_c* nam_c); // name of new file
/* u3_foil_absorb(): absorb logfile, truncating to last good frame; block.
*/
u3_foil*
u3_foil_absorb(u3_dire* dir_u, // directory
c3_c* nam_c); // filename
/* u3_foil_delete(): delete a file; free descriptor.
*/
void
u3_foil_delete(void (*fun_f)(void*), // context pointer
void* vod_p, // context pointer
u3_foil* fol_u); // file to delete
/* u3_foil_append(): write a frame at the end of a file, freeing buffer.
*/
void
u3_foil_append(void (*fun_f)(void*), // context pointer
void* vod_p, // context pointer
u3_foil* fol_u, // file
c3_d* buf_d, // buffer to write from
c3_d len_d); // length in chubs
/* u3_foil_reveal(): read the frame before a position, blocking.
*/
c3_d*
u3_foil_reveal(u3_foil* fol_u, // file from
c3_d* pos_d, // end position/prev end
c3_d* len_d); // length return
/* u3_foil_commit(): reveal from one file, append to another.
*/
void
u3_foil_commit(void (*fun_f)(void*, // context pointer
u3_foil*, // file from
c3_d, // previous from
u3_foil*, // file to
c3_d), // end of to
void* vod_p, // context pointer
u3_foil* del_u, // file from
c3_d del_d, // end of from frame
u3_foil* unt_u, // file to
c3_d unt_d); // end of to frame
/* u3_foil_invent(): make new file with one frame; free buffer, sync.
*/
void
u3_foil_invent(void (*fun_f)(void*, // context pointer
u3_foil*), // new file
void* vod_p, // context pointer
u3_dire* dir_u, // directory
c3_c* nam_c, // filename
c3_d* buf_d, // buffer (to free)
c3_d len_d); // length
/** Output.
**/
/* u3_reck_kick(): handle effect.
*/
void
u3_reck_kick(u3_noun ovo);
u3_reck_kick(u3_pier* pir_u, u3_noun ovo);
/** Main loop, new style.
@ -833,7 +1056,7 @@
/* u3_term_ef_bake(): initial effects for new server.
*/
void
u3_term_ef_bake(u3_noun fav);
u3_term_ef_bake(void);
/* u3_term_ef_blit(): send %blit effect to terminal.
*/
@ -884,33 +1107,39 @@
/* u3_ames_ef_bake(): create ames duct.
*/
void
u3_ames_ef_bake(void);
u3_ames_ef_bake(u3_pier* pir_u);
/* u3_ames_ef_send(): send packet to network.
*/
void
u3_ames_ef_send(u3_noun lan,
u3_ames_ef_send(u3_pier* pir_u,
u3_noun lan,
u3_noun pac);
/* u3_ames_io_init(): initialize ames I/O.
*/
void
u3_ames_io_init(void);
u3_ames_io_init(u3_pier* pir_u);
/* u3_ames_io_talk(): bring up listener.
*/
void
u3_ames_io_talk(void);
u3_ames_io_talk(u3_pier* pir_u);
/* u3_ames_ef_bake(): send initial events.
*/
void
u3_ames_io_bake(u3_pier* pir_u);
/* u3_ames_io_exit(): terminate ames I/O.
*/
void
u3_ames_io_exit(void);
u3_ames_io_exit(u3_pier* pir_u);
/* u3_ames_io_poll(): update ames IO state.
*/
void
u3_ames_io_poll(void);
u3_ames_io_poll(u3_pier* pir_u);
/** Autosave.
**/
@ -941,6 +1170,16 @@
void
u3_unix_ef_hold();
/* u3_unix_ef_boot(): boot actions
*/
void
u3_unix_ef_boot(void);
/* u3_unix_ef_bake(): initial effects for new process.
*/
void
u3_unix_ef_bake(void);
/* u3_unix_ef_move():
*/
void
@ -1068,7 +1307,6 @@
void
u3_raft_work(void);
/** Disk persistence.
**/
/* u3_sist_boot(): restore or create pier from disk.
@ -1139,6 +1377,7 @@
void
u3_sist_rand(c3_w* rad_w);
/** New timer system.
**/
/* u3_behn_io_init(): initialize time timer.
@ -1179,3 +1418,83 @@
*/
void
u3_cttp_io_poll(void);
/** Stream messages.
**/
/* u3_newt_write(): write atom to stream; free atom.
*/
void
u3_newt_write(u3_mojo* moj_u,
u3_atom mat,
void* vod_p);
/* u3_newt_read(): activate reading on input stream.
*/
void
u3_newt_read(u3_moat* mot_u);
/** Main for worker process.
**/
c3_i
u3_serf_main(c3_i arg_i,
c3_c** arg_c);
/** Pier control.
**/
/* u3_pier_create(): create a pier, loading existing.
*/
u3_pier*
u3_pier_create(c3_c* pax_c, c3_c* sys_c);
/* u3_pier_interrupt(): interrupt running process.
*/
void
u3_pier_interrupt(u3_pier* pir_u);
/* u3_pier_discover(): insert task into process controller.
*/
void
u3_pier_discover(u3_pier* pir_u,
c3_l msc_l,
u3_noun job);
/* u3_pier_exit(): trigger a gentle shutdown.
*/
void
u3_pier_exit(void);
/* u3_pier_work(): send event; real pier pointer.
*/
void
u3_pier_work(u3_pier* pir_u, u3_noun pax, u3_noun fav);
/* u3_pier_stub(): get the One Pier for unreconstructed code.
*/
u3_pier*
u3_pier_stub(void);
/* u3_pier_plan(): submit event; fake pier
*/
void
u3_pier_plan(u3_noun pax, u3_noun fav);
/* u3_pier_boot(): start the new pier system.
*/
void
u3_pier_boot(c3_c* pax_c, // pier path
c3_c* sys_c); // path to boot pill
/* u3_pier_tank(): dump single tank.
*/
void
u3_pier_tank(c3_l tab_l, u3_noun tac);
/* u3_pier_punt(): dump tank list.
*/
void
u3_pier_punt(c3_l tab_l, u3_noun tac);
/* u3_pier_sway(): print trace.
*/
void
u3_pier_sway(c3_l tab_l, u3_noun tax);

View File

@ -4,7 +4,7 @@
#include "all.h"
extern void
u3_lo_tank(c3_l tab_l, u3_noun tac);
u3_pier_tank(c3_l tab_l, u3_noun tac);
// duck: create a duck core for mean.
@ -67,7 +67,7 @@
sprintf(ugh_c, "%s: %s: 0x%8x:",
paz_c, pfix_c, u3r_mug(typ));
u3_lo_tank(0, u3n_kick_on(u3qfu_dunq(van, ugh_c, typ)));
u3_pier_tank(0, u3n_kick_on(u3qfu_dunq(van, ugh_c, typ)));
}
// shew: create a show core for mean

View File

@ -165,9 +165,9 @@ u3e_fault(void* adr_v, c3_i ser_i)
/* _ce_image_open(): open or create image.
*/
static c3_o
_ce_image_open(u3e_image* img_u, c3_o nuu_o)
_ce_image_open(u3e_image* img_u)
{
c3_i mod_i = _(nuu_o) ? (O_RDWR | O_CREAT) : O_RDWR;
c3_i mod_i = O_RDWR | O_CREAT;
c3_c ful_c[8193];
snprintf(ful_c, 8192, "%s", u3P.dir_c);
@ -197,11 +197,7 @@ _ce_image_open(u3e_image* img_u, c3_o nuu_o)
c3_d pgs_d = (siz_d + (c3_d)((1 << (u3a_page + 2)) - 1)) >>
(c3_d)(u3a_page + 2);
if ( c3y == nuu_o ) {
if ( siz_d ) {
c3_assert(0);
return c3n;
}
if ( !siz_d ) {
return c3y;
}
else {
@ -275,12 +271,12 @@ _ce_patch_create(u3_ce_patch* pat_u)
mkdir(ful_c, 0700);
snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
if ( -1 == (pat_u->ctl_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0666)) ) {
if ( -1 == (pat_u->ctl_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) {
c3_assert(0);
}
snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
if ( -1 == (pat_u->mem_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0666)) ) {
if ( -1 == (pat_u->mem_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) {
c3_assert(0);
}
}
@ -815,7 +811,7 @@ u3e_save(void)
_ce_patch_free(pat_u);
}
/* u3e_live(): start the persistence system.
/* u3e_live(): start the checkpointing system.
*/
c3_o
u3e_live(c3_o nuu_o, c3_c* dir_c)
@ -830,29 +826,15 @@ u3e_live(c3_o nuu_o, c3_c* dir_c)
} else
#endif
{
/* Open and apply any patches.
*/
if ( _(nuu_o) ) {
if ( (c3n == _ce_image_open(&u3P.nor_u, c3y)) ||
(c3n == _ce_image_open(&u3P.sou_u, c3y)) )
{
printf("boot: image failed\r\n");
exit(1);
}
if ( (c3n == _ce_image_open(&u3P.nor_u)) ||
(c3n == _ce_image_open(&u3P.sou_u)) )
{
printf("boot: image failed\r\n");
exit(1);
}
else {
u3_ce_patch* pat_u;
/* Open image files.
*/
{
if ( (c3n == _ce_image_open(&u3P.nor_u, c3n)) ||
(c3n == _ce_image_open(&u3P.sou_u, c3n)) )
{
fprintf(stderr, "boot: no image\r\n");
return u3e_live(c3y, dir_c);
}
}
/* Load any patch files; apply them to images.
*/
if ( 0 != (pat_u = _ce_patch_open()) ) {
@ -901,4 +883,3 @@ u3e_live(c3_o nuu_o, c3_c* dir_c)
}
return nuu_o;
}

View File

@ -344,7 +344,7 @@ u3j_boot(void)
memset(u3D.ray_u, 0, (u3D.all_l * sizeof(u3j_core)));
jax_l = _cj_install(u3D.ray_u, 1, u3D.dev_u);
fprintf(stderr, "boot: installed %d jets\n", jax_l);
fprintf(stderr, "boot: installed %d jets\r\n", jax_l);
}
/* _cj_soft(): kick softly by arm axis.

View File

@ -482,7 +482,7 @@ u3m_mark(void)
/* _cm_pave(): instantiate or activate image.
*/
static void
_cm_pave(c3_o nuu_o, c3_o bug_o)
_cm_pave(c3_o nuu_o)
{
if ( c3y == nuu_o ) {
u3H = (void *)_pave_north(u3_Loom + 1,
@ -1497,6 +1497,50 @@ _cm_init(c3_o chk_o)
}
}
/* _cm_init_new(): start the environment.
*/
void
_cm_init_new(void)
{
_cm_limits();
_cm_signals();
/* Make sure GMP uses our malloc.
*/
mp_set_memory_functions(u3a_malloc, u3a_realloc2, u3a_free2);
/* Map at fixed address.
*/
{
c3_w len_w = u3a_bytes;
void* map_v;
map_v = mmap((void *)u3_Loom,
len_w,
(PROT_READ | PROT_WRITE),
(MAP_ANON | MAP_FIXED | MAP_PRIVATE),
-1, 0);
if ( -1 == (c3_ps)map_v ) {
void* dyn_v = mmap((void *)0,
len_w,
PROT_READ,
MAP_ANON | MAP_PRIVATE,
-1, 0);
fprintf(stderr, "boot: mapping %dMB failed\r\n", (len_w / (1024 * 1024)));
fprintf(stderr, "see urbit.org/docs/using/install to add swap space\r\n");
if ( -1 != (c3_ps)map_v ) {
fprintf(stderr,
"if porting to a new platform, try U3_OS_LoomBase %p\r\n",
dyn_v);
}
exit(1);
}
printf("loom: mapped %dMB\r\n", len_w >> 20);
}
}
/* _boot_home(): create ship directory.
*/
static void
@ -1549,10 +1593,10 @@ _boot_home(c3_c *dir_c, c3_c *pil_c)
}
}
/* u3m_boot(): start the u3 system.
/* u3m_boot(): start the u3 system (old).
*/
void
u3m_boot(c3_o nuu_o, c3_o bug_o, c3_c* dir_c, c3_c *pil_c)
u3m_boot(c3_o nuu_o, c3_c* dir_c, c3_c *pil_c)
{
/* Activate the loom.
*/
@ -1568,7 +1612,7 @@ u3m_boot(c3_o nuu_o, c3_o bug_o, c3_c* dir_c, c3_c *pil_c)
/* Construct or activate the allocator.
*/
_cm_pave(nuu_o, bug_o);
_cm_pave(nuu_o);
/* Initialize the jet system.
*/
@ -1587,10 +1631,82 @@ u3m_boot(c3_o nuu_o, c3_o bug_o, c3_c* dir_c, c3_c *pil_c)
printf("boot: loading %s\r\n", ful_c);
u3v_boot(ful_c);
}
}
else {
u3v_hose();
u3j_ream();
}
}
/* u3m_boot_new(): start the u3 system (new). return next event,
** starting from 1.
*/
c3_d
u3m_boot_new(c3_c* dir_c)
{
c3_o nuu_o;
/* Activate the loom.
*/
_cm_init_new();
/* Activate the storage system.
*/
nuu_o = u3e_live(c3n, dir_c);
/* Activate tracing.
*/
u3t_init();
/* Construct or activate the allocator.
*/
_cm_pave(nuu_o);
/* Initialize the jet system.
*/
u3j_boot();
/* Reactivate jets on old kernel.
*/
if ( !_(nuu_o) ) {
u3v_hose();
u3j_ream();
return u3A->ent_d;
}
else {
/* Basic initialization.
*/
memset(u3A, 0, sizeof(*u3A));
return 0;
}
}
/* u3m_boot_pier(): start without checkpointing.
*/
c3_d
u3m_boot_pier(void)
{
/* Activate the loom.
*/
_cm_init_new();
/* Activate tracing.
*/
u3t_init();
/* Construct or activate the allocator.
*/
_cm_pave(c3y);
/* Initialize the jet system.
*/
u3j_boot();
/* Basic initialization.
*/
memset(u3A, 0, sizeof(*u3A));
return 0;
}

View File

@ -1535,9 +1535,9 @@ u3r_chub(c3_w a_w,
*/
void
u3r_words(c3_w a_w,
c3_w b_w,
c3_w* c_w,
u3_atom d)
c3_w b_w,
c3_w* c_w,
u3_atom d)
{
c3_assert(u3_none != d);
c3_assert(_(u3a_is_atom(d)));
@ -1570,6 +1570,21 @@ u3r_words(c3_w a_w,
}
}
/* u3r_chubs():
**
** Copy double-words (a_w) through (a_w + b_w - 1) from (d) to (c).
*/
void
u3r_chubs(c3_w a_w,
c3_w b_w,
c3_d* c_d,
u3_atom d)
{
/* XX: assumes little-endian
*/
u3r_words(a_w * 2, b_w * 2, (c3_w *)c_d, d);
}
/* u3r_chop():
**
** Into the bloq space of `met`, from position `fum` for a

View File

@ -36,7 +36,7 @@ u3t_drop(void)
}
extern void
u3_lo_tank(c3_l tab_l, u3_noun tac);
u3_pier_tank(c3_l tab_l, u3_noun tac);
#ifdef GHETTO
/* _t_ghetto(): ghetto timelapse.
@ -55,11 +55,11 @@ _t_ghetto(void)
ms_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000);
if (ms_w > 1) {
#if 0
printf("%6d.%02dms: %9d ",
fprintf(stderr, "%6d.%02dms: %9d ",
ms_w, (int) (d0.tv_usec % 1000) / 10,
((int) (u3R->pro.nox_d - b4_d)));
#else
printf("%6d.%02dms ",
fprintf(stderr, "%6d.%02dms ",
ms_w, (int) (d0.tv_usec % 1000) / 10);
#endif
gettimeofday(&b4, 0);
@ -90,11 +90,11 @@ u3t_slog(u3_noun hod)
u3_noun pri = u3h(hod);
switch ( pri ) {
case 3: printf(">>> "); break;
case 2: printf(">> "); break;
case 1: printf("> "); break;
case 3: fprintf(stderr, ">>> "); break;
case 2: fprintf(stderr, ">> "); break;
case 1: fprintf(stderr, "> "); break;
}
u3_lo_tank(0, u3k(u3t(hod)));
u3_pier_tank(0, u3k(u3t(hod)));
}
u3z(hod);
}
@ -112,7 +112,7 @@ u3t_shiv(u3_noun hod)
}
else {
c3_c *str_c = u3r_string(hod);
printf("%s\r\n", str_c);
fprintf(stderr, "%s\r\n", str_c);
free(str_c);
}
}

View File

@ -46,8 +46,30 @@ u3_noun
u3v_load(u3_noun pil)
{
u3_noun sys = u3ke_cue(pil);
u3_noun cor = u3v_fire(sys);
u3_noun pro;
fprintf(stderr, "load: mug: %x\r\n", u3r_mug(sys));
{
u3_noun cor = u3v_fire(sys);
u3_noun pro;
pro = u3k(u3r_at(7, cor));
u3z(cor);
return pro;
}
}
/* u3v_lite(): load lightweight, core-only pill.
*/
u3_noun
u3v_lite(u3_noun pil)
{
u3_noun arv = u3ke_cue(pil);
u3_noun cor, pro;
fprintf(stderr, "lite: arvo formula %x\r\n", u3r_mug(arv));
cor = u3n_nock_on(0, arv);
fprintf(stderr, "lite: core %x\r\n", u3r_mug(cor));
pro = u3k(u3r_at(7, cor));
@ -60,16 +82,41 @@ u3v_load(u3_noun pil)
void
u3v_boot(c3_c* pas_c)
{
u3_noun pil = u3m_file(pas_c);
u3_noun pru = u3m_soft(0, u3v_load, pil);
u3_noun pru;
if ( !u3A->sys ) {
u3A->sys = u3m_file(pas_c);
}
pru = u3m_soft(0, u3v_load, u3k(u3A->sys));
if ( u3h(pru) != 0 ) {
fprintf(stderr, "boot failed\r\n");
exit(1);
}
fprintf(stderr, "final state %x\r\n", u3r_mug(u3t(pru)));
fprintf(stderr, "boot: final state %x\r\n", u3r_mug(u3t(pru)));
u3A->ken = 0;
u3A->roc = u3k(u3t(pru));
u3z(pru);
}
/* u3v_boot_lite(): light bootstrap sequence, just making a kernel.
*/
void
u3v_boot_lite(u3_atom lit)
{
u3_noun pru = u3m_soft(0, u3v_lite, lit);
if ( u3h(pru) != 0 ) {
fprintf(stderr, "boot failed\r\n");
exit(1);
}
fprintf(stderr, "lite: final state %x\r\n", u3r_mug(u3t(pru)));
u3A->ken = 0;
u3A->roc = u3k(u3t(pru));
@ -260,7 +307,7 @@ _cv_nock_poke(u3_noun ovo)
u3_noun tox = u3do("spat", u3k(u3h(ovo)));
c3_c* tox_c = u3r_string(tox);
printf("poke: %%%s (%x) on %s\r\n", ovi_c, u3r_mug(ovo), tox_c);
fprintf(stderr, "poke: %%%s (%x) on %s\r\n", ovi_c, u3r_mug(ovo), tox_c);
free(tox_c); free(ovi_c); u3z(tox);
}
#endif
@ -273,8 +320,11 @@ _cv_nock_poke(u3_noun ovo)
{
c3_c* ovi_c = u3r_string(u3h(u3t(ovo)));
printf("poked: %s\r\n", ovi_c);
if ( u3_nul == u3h(pro) ) {
fprintf(stderr, " blank: %s\r\n", ovi_c);
} else {
fprintf(stderr, " happy: %s: %d\r\n", ovi_c, u3kb_lent(u3k(u3h(pro))));
}
free(ovi_c);
}
#endif

View File

@ -46,9 +46,9 @@ _ames_free(void* ptr_v)
/* _ames_czar(): quasi-static route to emperor.
*/
static c3_w
_ames_czar(c3_y imp_y, c3_s* por_s)
_ames_czar(u3_pier* pir_u, c3_y imp_y, c3_s* por_s)
{
u3_ames* sam_u = &u3_Host.sam_u;
u3_ames* sam_u = pir_u->sam_u;
if ( c3y == u3_Host.ops_u.loh ) {
*por_s = 31337 + imp_y;
@ -183,19 +183,23 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i)
}
void
u3_ames_ef_bake(void)
u3_ames_ef_bake(u3_pier* pir_u)
{
u3_noun pax = u3nq(u3_blip, c3__newt, u3k(u3A->sen), u3_nul);
u3v_plan(pax, u3nc(c3__barn, u3_nul));
u3_pier_work(pir_u, pax, u3nc(c3__barn, u3_nul));
u3_pier_work(pir_u,
u3nt(u3_blip, c3__ames, u3_nul),
u3nc(c3__kick, u3k(u3A->now)));
}
/* u3_ames_ef_send(): send packet to network (v4).
*/
void
u3_ames_ef_send(u3_noun lan, u3_noun pac)
u3_ames_ef_send(u3_pier* pir_u, u3_noun lan, u3_noun pac)
{
u3_ames* sam_u = &u3_Host.sam_u;
u3_ames* sam_u = pir_u->sam_u;
c3_s por_s;
c3_w pip_w;
@ -212,7 +216,7 @@ u3_ames_ef_send(u3_noun lan, u3_noun pac)
if ( 0 == pip_w ) {
pip_w = 0x7f000001;
por_s = u3_Host.sam_u.por_s;
por_s = pir_u->sam_u->por_s;
}
{
struct sockaddr_in add_u;
@ -220,7 +224,7 @@ u3_ames_ef_send(u3_noun lan, u3_noun pac)
if ( (0 == (pip_w >> 16)) && (1 == (pip_w >> 8)) ) {
c3_y imp_y = (pip_w & 0xff);
pip_w = _ames_czar(imp_y, &por_s);
pip_w = _ames_czar(pir_u, imp_y, &por_s);
}
if ( 0 != pip_w ) {
@ -238,7 +242,7 @@ u3_ames_ef_send(u3_noun lan, u3_noun pac)
if ( 0 != (ret = uv_udp_send(&ruq_u->snd_u,
&sam_u->wax_u,
&buf_u, 1,
(const struct sockaddr*) & add_u, // IS THIS RIGHT ?!?!?
(const struct sockaddr*) &add_u,
_ames_send_cb)) ) {
uL(fprintf(uH, "ames: send: %s\n", uv_strerror(ret)));
}
@ -252,18 +256,18 @@ u3_ames_ef_send(u3_noun lan, u3_noun pac)
/* _ames_time_cb(): timer callback.
*/
static void
_ames_time_cb(uv_timer_t* tim_uo)
_ames_time_cb(uv_timer_t* tim_u)
{
u3_ames* sam_u = &u3_Host.sam_u;
u3_lo_open();
u3_pier* pir_u = tim_u->data;
u3_ames* sam_u = pir_u->sam_u;
sam_u->law_w = time(0);
{
u3v_plan
(u3nt(u3_blip, c3__ames, u3_nul),
u3_pier_work
(pir_u,
u3nt(u3_blip, c3__ames, u3_nul),
u3nc(c3__wake, u3_nul));
}
u3_lo_shut(c3n);
}
/* _ames_recv_cb(): receive callback.
@ -275,13 +279,14 @@ _ames_recv_cb(uv_udp_t* wax_u,
const struct sockaddr* adr_u,
unsigned flg_i)
{
u3_pier* pir_u = wax_u->data;
// uL(fprintf(uH, "ames: rx %p\r\n", buf_u.base));
if ( 0 == nrd_i ) {
_ames_free(buf_u->base);
}
else {
u3_lo_open();
{
u3_noun msg = u3i_bytes((c3_w)nrd_i, (c3_y*)buf_u->base);
@ -293,25 +298,25 @@ _ames_recv_cb(uv_udp_t* wax_u,
c3_s por_s = ntohs(add_u->sin_port);
c3_w pip_w = ntohl(add_u->sin_addr.s_addr);
u3v_plan
(u3nt(u3_blip, c3__ames, u3_nul),
u3_pier_work
(pir_u,
u3nt(u3_blip, c3__ames, u3_nul),
u3nt(c3__hear,
u3nq(c3__if, u3k(u3A->now), por_s, u3i_words(1, &pip_w)),
msg));
#endif
}
_ames_free(buf_u->base);
u3_lo_shut(c3y);
}
}
/* u3_ames_io_init(): initialize ames I/O.
*/
void
u3_ames_io_init()
u3_ames_io_init(u3_pier* pir_u)
{
u3_ames* sam_u = &u3_Host.sam_u;
c3_s por_s;
u3_ames* sam_u = pir_u->sam_u;
c3_s por_s;
por_s = u3_Host.ops_u.por_s;
if ( 0 != u3_Host.ops_u.imp_c ) {
@ -325,16 +330,17 @@ u3_ames_io_init()
}
num_y = u3r_byte(0, u3t(num));
_ames_czar(num_y, &por_s);
_ames_czar(pir_u, num_y, &por_s);
uL(fprintf(uH, "ames: czar: %s on %d\n", u3_Host.ops_u.imp_c, por_s));
u3z(num);
}
int ret;
if ( 0 != (ret = uv_udp_init(u3L, &u3_Host.sam_u.wax_u)) ) {
if ( 0 != (ret = uv_udp_init(u3L, &(pir_u->sam_u->wax_u))) ) {
uL(fprintf(uH, "ames: init: %s\n", uv_strerror(ret)));
c3_assert(0);
}
sam_u->wax_u.data = pir_u;
// Bind and stuff.
{
@ -366,26 +372,35 @@ u3_ames_io_init()
// Timer too.
{
uv_timer_init(u3L, &sam_u->tim_u);
sam_u->tim_u.data = pir_u;
}
}
/* u3_ames_io_talk(): start receiving ames traffic.
*/
void
u3_ames_io_talk()
u3_ames_io_talk(u3_pier* pir_u)
{
u3_ames* sam_u = &u3_Host.sam_u;
u3_ames* sam_u = pir_u->sam_u;
uL(fprintf(uH, "ames: on localhost, UDP %d.\n", sam_u->por_s));
uv_udp_recv_start(&sam_u->wax_u, _ames_alloc, _ames_recv_cb);
}
/* u3_ames_io_bake(): send initial events.
*/
void
u3_ames_io_bake(u3_pier* pir_u)
{
}
/* u3_ames_io_exit(): terminate ames I/O.
*/
void
u3_ames_io_exit()
u3_ames_io_exit(u3_pier* pir_u)
{
u3_ames* sam_u = &u3_Host.sam_u;
u3_ames* sam_u = pir_u->sam_u;
uv_close(&sam_u->had_u, 0);
}
@ -393,9 +408,9 @@ u3_ames_io_exit()
/* u3_ames_io_poll(): update ames IO state.
*/
void
u3_ames_io_poll()
u3_ames_io_poll(u3_pier* pir_u)
{
u3_ames* sam_u = &u3_Host.sam_u;
u3_ames* sam_u = pir_u->sam_u;
u3_noun wen = u3v_keep(u3nt(u3_blip, c3__ames, u3_nul));
if ( (u3_nul != wen) &&

View File

@ -51,7 +51,7 @@ _batz_time_cb(uv_timer_t* tim_u)
u3_lo_open();
{
u3v_plan
u3_pier_plan
(u3nt(u3_blip, c3__batz, u3_nul),
u3nc(c3__wake, u3_nul));
}

View File

@ -49,13 +49,11 @@ _behn_time_cb(uv_timer_t* tim_u)
teh_u->run_w++;
}
u3_lo_open();
{
u3v_plan
u3_pier_plan
(u3nt(u3_blip, c3__behn, u3_nul),
u3nc(c3__wake, u3_nul));
}
u3_lo_shut(c3n);
}
/* u3_behn_io_poll(): update behn IO state.

View File

@ -445,7 +445,7 @@ _cttp_httr(c3_l num_l, c3_w sas_w, u3_noun mes, u3_noun uct)
u3_noun htr = u3nt(sas_w, mes, uct);
u3_noun pox = u3nt(u3_blip, c3__http, u3_nul);
u3v_plan(pox, u3nt(c3__they, num_l, htr));
u3_pier_plan(pox, u3nt(c3__they, num_l, htr));
}
/* _cttp_httr_cres(): deliver valid response.
@ -953,7 +953,6 @@ _cttp_ccon_kick_connect(u3_ccon* coc_u)
static void
_cttp_ccon_kick_write_cb(uv_write_t* wri_u, c3_i sas_i)
{
u3_lo_open();
{
_u3_write_t* ruq_u = (void *)wri_u;
@ -963,7 +962,6 @@ _cttp_ccon_kick_write_cb(uv_write_t* wri_u, c3_i sas_i)
free(ruq_u->buf_y);
free(ruq_u);
}
u3_lo_shut(c3n);
}
/* _cttp_ccon_kick_write_cryp()
@ -1192,7 +1190,6 @@ _cttp_ccon_kick_read_cryp_cb(uv_stream_t* tcp_u,
{
u3_ccon *coc_u = _cttp_ccon_wax((uv_tcp_t*)tcp_u);
u3_lo_open();
{
if ( siz_w == UV_EOF ) {
// _cttp_ccon_fail(coc_u, c3n); // replaced with uv_close() 2016-06-07
@ -1217,7 +1214,6 @@ _cttp_ccon_kick_read_cryp_cb(uv_stream_t* tcp_u,
free(buf_u->base);
}
}
u3_lo_shut(c3y);
}
/* _cttp_ccon_read_clyr_cb()
@ -1240,7 +1236,6 @@ _cttp_ccon_kick_read_clyr_cb(uv_stream_t* tcp_u,
{
u3_ccon *coc_u = _cttp_ccon_wax((uv_tcp_t*)tcp_u);
u3_lo_open();
{
if ( siz_w == UV_EOF ) {
// _cttp_ccon_fail(coc_u, c3n); // replaced with uv_close() 2016-06-07
@ -1256,7 +1251,6 @@ _cttp_ccon_kick_read_clyr_cb(uv_stream_t* tcp_u,
free(buf_u->base);
}
}
u3_lo_shut(c3y);
}
/* _cttp_ccon_kick_read_clyr(): start reading on insecure socket.
@ -1638,6 +1632,7 @@ u3_cttp_io_init()
SSL_load_error_strings();
u3_Host.ssl_u = SSL_CTX_new(TLSv1_client_method());
SSL_CTX_set_options(u3S, SSL_OP_NO_SSLv2);
SSL_CTX_set_verify(u3S, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_default_verify_paths(u3S);
@ -1676,5 +1671,5 @@ u3_cttp_io_poll(void)
void
u3_cttp_io_exit(void)
{
SSL_CTX_free(u3S);
SSL_CTX_free(u3S);
}

629
vere/foil.c Normal file
View File

@ -0,0 +1,629 @@
/* vere/foil.c
**
** This file is in the public domain.
*/
#include "all.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <setjmp.h>
#include <gmp.h>
#include <dirent.h>
#include <stdint.h>
#include <uv.h>
#include <termios.h>
#include <term.h>
#include <errno.h>
#include <libgen.h>
#include <ftw.h>
#include "vere/vere.h"
/* assumptions:
** all measurements are in chubs (double-words, c3_d, uint64_t).
** little-endian addressing is ASSUMED.
**
** framing:
** the last two chubs of a frame:
**
** {
** 64-bit frame length
** {
** (high 32 bits) mug of frame
** (low 32 bits) mug of current address
** }
** }
**
** we can scan for one of these frames with very low probability
** of a false positive. we always write to and read from the end
** of a file. a frame position points to its end.
**
** protocol:
** once the callback is called, all results are fully fsynced.
** all callbacks are optional and can be passed 0.
*/
/* _foil_fail(): fail with error.
*/
static void
_foil_fail(const c3_c* why_c, c3_i err_i)
{
if ( err_i ) {
fprintf(stderr, "%s: error: %s\r\n", why_c, uv_strerror(err_i));
c3_assert(0);
} else {
fprintf(stderr, "%s: file error\r\n", why_c);
}
exit(1);
}
/* _foil_close(): close file, blockingly.
*/
static void
_foil_close(uv_file fil_f)
{
c3_i err_i;
uv_fs_t ruq_u;
if ( 0 != (err_i = uv_fs_close(u3L, &ruq_u, fil_f, 0)) ) {
_foil_fail("uv_fs_close", err_i);
}
}
/* _foil_path(): allocate path.
*/
static c3_c*
_foil_path(u3_dire* dir_u,
const c3_c* nam_c)
{
c3_w len_w = strlen(dir_u->pax_c);
c3_c* pax_c;
pax_c = c3_malloc(1 + len_w + 1 + strlen(nam_c));
strcpy(pax_c, dir_u->pax_c);
pax_c[len_w] = '/';
strcpy(pax_c + len_w + 1, nam_c);
return pax_c;
}
/* u3_foil_folder(): load directory, blockingly. null if nonexistent.
*/
u3_dire*
u3_foil_folder(const c3_c* pax_c)
{
u3_dire* dir_u;
uv_fs_t ruq_u;
uv_dirent_t den_u;
c3_i err_i;
/* open directory, synchronously
*/
{
err_i = uv_fs_scandir(u3L, &ruq_u, pax_c, 0, 0);
if ( err_i < 0 ) {
if ( UV_ENOENT != err_i ) {
_foil_fail(pax_c, err_i);
return 0;
}
else {
if ( 0 != (err_i = uv_fs_mkdir(u3L, &ruq_u, pax_c, 0700, 0)) ) {
_foil_fail(pax_c, err_i);
return 0;
}
else {
uv_fs_req_cleanup(&ruq_u);
return u3_foil_folder(pax_c);
}
}
}
dir_u = c3_malloc(sizeof *dir_u);
dir_u->all_u = 0;
dir_u->pax_c = c3_malloc(1 + strlen(pax_c));
strcpy(dir_u->pax_c, pax_c);
}
/* create entries for all files
*/
while ( UV_EOF != uv_fs_scandir_next(&ruq_u, &den_u) ) {
if ( UV_DIRENT_FILE == den_u.type ) {
u3_dent* det_u = c3_malloc(sizeof(*det_u));
det_u->nam_c = c3_malloc(1 + strlen(den_u.name));
strcpy(det_u->nam_c, den_u.name);
det_u->nex_u = dir_u->all_u;
dir_u->all_u = det_u;
}
}
/* clean up request
*/
{
uv_fs_req_cleanup(&ruq_u);
}
/* open directory file for reading, to fsync
*/
{
if ( 0 > (err_i = uv_fs_open(u3L,
&ruq_u,
pax_c,
O_RDONLY,
0600,
0)) )
{
_foil_fail("open directory", err_i);
return 0;
}
dir_u->fil_u = ruq_u.result;
uv_fs_req_cleanup(&ruq_u);
}
return dir_u;
}
/* u3_foil_create(): create a new, empty, open file, not syncing.
*/
struct _foil_create_request {
uv_fs_t ruq_u;
void (*fun_f)(void*, u3_foil*);
void* vod_p;
u3_dire* dir_u;
c3_c* nam_c;
c3_c* pax_c;
};
static void
_foil_create_cb(uv_fs_t* ruq_u)
{
struct _foil_create_request* req_u = (void *)ruq_u;
u3_foil* fol_u;
fol_u = c3_malloc(sizeof(*fol_u));
fol_u->fil_u = ruq_u->result;
fol_u->dir_u = req_u->dir_u;
fol_u->nam_c = req_u->nam_c;
fol_u->end_d = 0;
req_u->fun_f(req_u->vod_p, fol_u);
c3_free(req_u->pax_c);
uv_fs_req_cleanup(ruq_u);
c3_free(req_u);
}
void
u3_foil_create(void (*fun_f)(void*, // context pointer
u3_foil*),// file object
void* vod_p, // context pointer
u3_dire* dir_u, // directory
const c3_c* nam_c) // name of new file
{
c3_c* pax_c;
c3_i err_i;
/* construct full path
*/
pax_c = _foil_path(dir_u, nam_c);
/* perform create
*/
{
struct _foil_create_request* req_u;
req_u = c3_malloc(sizeof(*req_u));
req_u->fun_f = fun_f;
req_u->vod_p = vod_p;
req_u->dir_u = dir_u;
req_u->nam_c = c3_malloc(1 + strlen(nam_c));
strcpy(req_u->nam_c, nam_c);
req_u->pax_c = pax_c;
if ( 0 != (err_i = uv_fs_open(u3L,
&req_u->ruq_u,
pax_c,
O_CREAT | O_WRONLY,
0600,
_foil_create_cb)) )
{
_foil_fail("uv_fs_open", err_i);
}
}
}
/* u3_foil_absorb(): open logfile, truncating to last good frame; blocking.
*/
u3_foil*
u3_foil_absorb(u3_dire* dir_u, // directory
c3_c* nam_c) // filename
{
u3_foil* fol_u;
uv_fs_t ruq_u;
c3_i err_i;
/* open file and create wrapper
*/
{
c3_c* pax_c = _foil_path(dir_u, nam_c);
if ( 0 > (err_i = uv_fs_open(u3L,
&ruq_u,
pax_c,
O_RDWR | O_CREAT,
0600,
0)) )
{
_foil_fail(pax_c, err_i);
c3_free(pax_c);
return 0;
}
c3_free(pax_c);
fol_u = c3_malloc(sizeof(*fol_u));
fol_u->dir_u = dir_u;
fol_u->fil_u = ruq_u.result;
fol_u->nam_c = c3_malloc(1 + strlen(nam_c));
strcpy(fol_u->nam_c, nam_c);
uv_fs_req_cleanup(&ruq_u);
}
/* measure file
*/
{
if ( 0 != (err_i = uv_fs_fstat(u3L, &ruq_u, fol_u->fil_u, 0)) ) {
_foil_fail("uv_fs_fstat", err_i);
return 0;
}
if ( 0 != (7 & ruq_u.statbuf.st_size) ) {
_foil_fail("logfile size corrupt", 0);
return 0;
}
fol_u->end_d = (ruq_u.statbuf.st_size >> 3ULL);
}
/* XX: scan for good frame.
*/
return fol_u;
}
/* u3_foil_delete(): delete a file; free descriptor.
*/
struct _foil_delete_request {
uv_fs_t ruq_u;
void (*fun_f)(void*);
void* vod_p;
u3_foil* fol_u;
c3_c* pax_c;
};
static void
_foil_delete_cb(uv_fs_t* ruq_u)
{
struct _foil_delete_request* req_u = (void *)ruq_u;
if ( req_u->fun_f ) {
req_u->fun_f(req_u->vod_p);
}
c3_free(req_u->pax_c);
c3_free(req_u->fol_u->nam_c);
c3_free(req_u->fol_u);
uv_fs_req_cleanup(ruq_u);
c3_free(req_u);
}
void
u3_foil_delete(void (*fun_f)(void*), // context pointer
void* vod_p, // context pointer
u3_foil* fol_u) // file to delete
{
c3_i err_i;
c3_c* pax_c;
/* construct full path
*/
pax_c = _foil_path(fol_u->dir_u, fol_u->nam_c);
/* perform delete
*/
{
struct _foil_delete_request* req_u;
req_u = c3_malloc(sizeof(*req_u));
req_u->fun_f = fun_f;
req_u->vod_p = vod_p;
req_u->fol_u = fol_u;
req_u->pax_c = pax_c;
if ( 0 != (err_i = uv_fs_unlink(u3L,
&req_u->ruq_u,
pax_c,
_foil_delete_cb)) )
{
_foil_fail("uv_fs_unlink", err_i);
}
}
}
/* u3_foil_append(): write a frame at the end of a file, freeing the buffer.
*/
struct _foil_append_request {
uv_fs_t ruq_u;
void (*fun_f)(void*);
void* vod_p;
u3_foil* fol_u;
c3_d* fam_d;
c3_d* buf_d;
};
static void
_foil_append_cb_2(uv_fs_t* ruq_u)
{
struct _foil_append_request* req_u = (void*) ruq_u;
req_u->fun_f(req_u->vod_p);
uv_fs_req_cleanup(ruq_u);
c3_free(req_u);
}
static void
_foil_append_cb_1(uv_fs_t* ruq_u)
{
struct _foil_append_request* req_u = (void*) ruq_u;
uv_fs_req_cleanup(ruq_u);
c3_free(req_u->buf_d);
uv_fs_fsync(u3L, &req_u->ruq_u,
req_u->fol_u->fil_u,
_foil_append_cb_2);
}
void
u3_foil_append(void (*fun_f)(void*), // context pointer
void* vod_p, // context pointer
u3_foil* fol_u, // file
c3_d* buf_d, // buffer to write from
c3_d len_d) // length in chubs
{
c3_d pos_d = fol_u->end_d;
struct _foil_append_request* req_u;
c3_i err_i;
/* set up request
*/
{
req_u = c3_malloc(sizeof(*req_u));
req_u->fun_f = fun_f;
req_u->vod_p = vod_p;
req_u->fol_u = fol_u;
req_u->buf_d = buf_d;
req_u->fam_d = c3_malloc(16);
}
/* framing
*/
{
c3_w top_w, bot_w;
fol_u->end_d = pos_d + len_d + 2;
/* XX: assumes "little-endian won", 32-bit frame length.
*/
top_w = u3r_mug_words((c3_w *)(void *) buf_d, (2 * len_d));
bot_w = (req_u->fol_u->end_d & 0xffffffff);
bot_w = u3r_mug_words(&bot_w, 1);
req_u->fam_d[0] = len_d;
req_u->fam_d[1] = ((c3_d)top_w) << 32ULL | ((c3_d) bot_w);
}
/* do it
*/
{
uv_buf_t buf_u[2];
buf_u[0] = uv_buf_init((void *)buf_d, (len_d * 8));
buf_u[1] = uv_buf_init((void *)req_u->fam_d, 16);
if ( 0 != (err_i = uv_fs_write(u3L,
&req_u->ruq_u,
fol_u->fil_u,
buf_u,
2,
(8ULL * pos_d),
_foil_append_cb_1)) )
{
_foil_fail("uv_fs_write", err_i);
}
}
}
/* u3_foil_reveal(): read the frame before a position, blocking.
*/
c3_d*
u3_foil_reveal(u3_foil* fol_u, // file from
c3_d* sop_d, // end position/prev end
c3_d* len_d) // length return
{
c3_d pos_d = *sop_d;
c3_d fam_d[2];
c3_l mug_l;
uv_fs_t ruq_u;
c3_i err_i;
c3_assert(pos_d >= 2);
c3_assert(pos_d <= fol_u->end_d);
/* read frame data
*/
{
uv_buf_t buf_u = uv_buf_init((void *)fam_d, 16);
fam_d[0] = fam_d[1] = 0;
if ( 0 > (err_i = uv_fs_read(u3L,
&ruq_u,
fol_u->fil_u,
&buf_u, 1,
(8ULL * (pos_d - 2ULL)),
0)) )
{
_foil_fail("uv_fs_read", err_i);
return 0;
}
uv_fs_req_cleanup(&ruq_u);
}
/* validate frame
*/
{
c3_w top_w, bot_w;
c3_l chk_l;
*len_d = fam_d[0];
if ( *len_d > (pos_d - 2ULL) ) {
_foil_fail("corrupt frame a", 0);
return 0;
}
top_w = fam_d[1] >> 32ULL;
mug_l = top_w;
bot_w = fam_d[1] & 0xffffffff;
chk_l = (pos_d & 0xffffffff);
chk_l = u3r_mug_words(&chk_l, 1);
if ( bot_w != chk_l ) {
_foil_fail("corrupt frame b", 0);
}
}
/* read frame
*/
{
c3_d* buf_d = c3_malloc(8 * *len_d);
uv_buf_t buf_u = uv_buf_init((void *)buf_d, 8 * *len_d);
c3_l gum_l;
if ( 0 > (err_i = uv_fs_read(u3L,
&ruq_u,
fol_u->fil_u,
&buf_u, 1,
(8ULL * (pos_d - (*len_d + 2ULL))),
0) ) )
{
_foil_fail("uv_fs_read", err_i);
return 0;
}
uv_fs_req_cleanup(&ruq_u);
gum_l = u3r_mug_words((c3_w *)(void *) buf_d, (2 * *len_d));
if ( mug_l != gum_l ) {
_foil_fail("corrupt frame c", 0);
return 0;
}
*sop_d = (pos_d - (*len_d + 2ULL));
return buf_d;
}
}
/* u3_foil_invent(): create a new file with one frame, freeing buffer; sync.
*/
struct _foil_invent_request {
uv_fs_t ruq_u;
void (*fun_f)(void*, u3_foil*);
u3_foil* fol_u;
void* vod_p;
c3_d* buf_d;
c3_d len_d;
c3_d num_d;
#if 0
struct timeval bef_u;
#endif
};
static void
_foil_invent_cb_2a(void* req_p)
{
struct _foil_invent_request* req_u = req_p;
if ( 1 == req_u->num_d ) {
#if 0
{
struct timeval aft_u, gap_u;
c3_w mls_w;
gettimeofday(&aft_u, 0);
timersub(&aft_u, &req_u->bef_u, &gap_u);
mls_w = (gap_u.tv_sec * 1000) + (gap_u.tv_usec / 1000);
fprintf(stderr, "invent ms: %d\r\n", mls_w);
}
#endif
req_u->fun_f(req_u->vod_p, req_u->fol_u);
_foil_close(req_u->fol_u->fil_u);
c3_free(req_u);
}
else {
req_u->num_d++;
}
}
static void
_foil_invent_cb_2b(uv_fs_t* ruq_u)
{
struct _foil_invent_request* req_u = (void *)ruq_u;
uv_fs_req_cleanup(ruq_u);
_foil_invent_cb_2a(req_u);
}
static void
_foil_invent_cb_1(void* req_p,
u3_foil* fol_u)
{
struct _foil_invent_request* req_u = req_p;
req_u->fol_u = fol_u;
/* fsync the parent directory, since we just created a file.
*/
uv_fs_fsync(u3L, &req_u->ruq_u,
req_u->fol_u->dir_u->fil_u,
_foil_invent_cb_2b);
u3_foil_append(_foil_invent_cb_2a,
req_u,
fol_u,
req_u->buf_d,
req_u->len_d);
}
void
u3_foil_invent(void (*fun_f)(void*, // context pointer
u3_foil*), // new file
void* vod_p, // context pointer
u3_dire* dir_u, // directory
c3_c* nam_c, // filename
c3_d* buf_d, // buffer (to free)
c3_d len_d) // length
{
struct _foil_invent_request* req_u;
req_u = malloc(sizeof(*req_u));
req_u->fun_f = fun_f;
req_u->fol_u = 0;
req_u->vod_p = vod_p;
req_u->buf_d = buf_d;
req_u->len_d = len_d;
req_u->num_d = 0;
#if 0
gettimeofday(&req_u->bef_u, 0);
#endif
u3_foil_create(_foil_invent_cb_1, req_u, dir_u, nam_c);
}

694
vere/fuse.c Normal file
View File

@ -0,0 +1,694 @@
/* v/fuse.c
**
** This file is in the public domain.
*/
#include "all.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <setjmp.h>
#include <gmp.h>
#include <dirent.h>
#include <stdint.h>
#include <uv.h>
#include <termios.h>
#include <term.h>
#include <errno.h>
#include <libgen.h>
#include <ftw.h>
#include "vere/vere.h"
/* helper routines adapted from FUSE example code
*/
struct _fusedr_buf {
c3_c* buf_c;
c3_z siz_z;
};
static void
_fusedr_buf_add(fuse_req_t req_u,
struct _fusedr_buf* buf_u,
const c3_c* nam_c,
fuse_ino_t ino_i)
{
struct stat sat_u;
c3_z old_z = buf_u->siz_z;
buf_u->siz_z += fuse_add_direntry(req_u, NULL, 0, nam_c, NULL, 0);
buf_u->buf_c = (c3_c*) realloc(buf_u->buf_c, buf_u->siz_z);
memset(&sat_u, 0, sizeof(sat_u));
sat_u.st_ino = ino_i;
fuse_add_direntry(req_u,
buf_u->buf_c + old_z,
buf_u->siz_z - old_z,
nam_c,
&sat_u,
buf_u->siz_z);
}
static void
_fuse_buf_reply(fuse_req_t req_u,
c3_c* buf_c,
c3_z siz_z,
c3_f off_f,
c3_z max_z)
{
if ( off_f < siz_z ) {
fuse_reply_buf(req_u,
buf_c + off_f,
c3_min(siz_z - off_f, max_z));
} else {
fuse_reply_buf(req_u, NULL, 0);
}
}
static void
_inode_init(void)
{
u3_fuse* fus_u = &u3_Host.fus_u;
memset(fus_u, 0, sizeof(u3_fuse));
{
fus_u->rot_u.ino_i = FUSE_ROOT_ID;
fus_u->rot_u.val_u = 0;
fus_u->rot_u.nam_c = strdup("/");
fus_u->rot_u.pax_c = 0;
fus_u->rot_u.val_u = 0;
fus_u->rot_u.ref_w = 0x1fffffff;
fus_u->rot_u.par_u = 0;
fus_u->rot_u.kid_u = 0;
fus_u->rot_u.nex_u = 0;
}
{
fus_u->ion_u.ino_i = FUSE_ROOT_ID + 1;
fus_u->ion_u.len_w = 64;
fus_u->ion_u.nod_u = calloc(64, sizeof(struct fnod *));
fus_u->ion_u.nod_u[FUSE_ROOT_ID] = &fus_u->rot_u;
}
}
/* _inode_get(): look up an inode.
*/
static u3_fnod*
_inode_get(fuse_ino_t ino_i)
{
u3_fuse* fus_u = &u3_Host.fus_u;
c3_assert(ino_i < fus_u->ion_u.ino_i);
return fus_u->ion_u.nod_u[ino_i];
}
/* _inode_new(): create an inode.
*/
static u3_fnod*
_inode_new(void)
{
u3_fuse* fus_u = &u3_Host.fus_u;
u3_fnod* nod_u = calloc(1, sizeof(u3_fnod));
nod_u->ino_i = fus_u->ion_u.ino_i;
fus_u->ion_u.nod_u[nod_u->ino_i] = nod_u;
fus_u->ion_u.ino_i++;
if ( fus_u->ion_u.len_w == fus_u->ion_u.ino_i ) {
fus_u->ion_u.len_w *= 2;
fus_u->ion_u.nod_u = realloc(fus_u->ion_u.nod_u,
(fus_u->ion_u.len_w *
sizeof(struct fnod *)));
}
return nod_u;
}
/* _inode_make(): set up an inode.
*/
static u3_fnod*
_inode_make(u3_fnod* par_u, c3_c* nam_c)
{
u3_fnod* nod_u = _inode_new();
nod_u->nam_c = nam_c;
nod_u->par_u = par_u;
nod_u->nex_u = par_u->kid_u;
par_u->kid_u = nod_u;
return nod_u;
}
/* _inode_stat(): fill stat buffer from inode; return c3y if available
*/
static c3_o
_inode_stat(u3_fnod* nod_u, struct stat* buf_u)
{
memset(buf_u, 0, sizeof(struct stat));
switch ( nod_u->typ_e ) {
case u3_fuse_type_unknown: return c3n;
case u3_fuse_type_file: {
if ( 0 == nod_u->val_u ) {
return c3n;
}
else {
buf_u->st_mode = S_IFREG | 0444;
buf_u->st_nlink = 1;
buf_u->st_size = nod_u->val_u->siz_z;
return c3y;
}
}
case u3_fuse_type_directory: {
buf_u->st_mode = S_IFDIR | 0555;
buf_u->st_nlink = 2;
return c3y;
}
}
}
/* _inode_path(): map inode path to noun.
*/
static u3_noun
_inode_path(u3_fnod* nod_u, u3_noun end)
{
if ( nod_u->par_u == 0 ) {
return end;
}
else {
end = u3nc(u3i_string(nod_u->nam_c), end);
return _inode_path(nod_u->par_u, end);
}
}
/* _inode_load_arch(): load urbit's own "inode".
*/
static u3_weak
_inode_load_arch(u3_noun hap)
{
if ( u3_nul == u3A->own ) {
return u3_none;
}
else {
u3_noun our = u3dc("scot", 'p', u3k(u3h(u3A->own)));
u3_noun pax = u3nc(c3__cy, u3nq(our, c3__home, u3k(u3A->wen), hap));
u3_noun val = u3v_peek(pax);
if ( u3_nul == val ) {
return u3_none;
} else {
u3_noun ret = u3k(u3t(val));
u3z(val);
return ret;
}
}
}
/* _inode_load_data(): load urbit file contents.
*/
static u3_weak
_inode_load_data(u3_noun hap)
{
if ( u3_nul == u3A->own ) {
return u3_none;
}
else {
u3_noun our = u3dc("scot", 'p', u3k(u3h(u3A->own)));
u3_noun pax = u3nc(c3__cx, u3nq(our, c3__home, u3k(u3A->wen), hap));
u3_noun val = u3v_peek(pax);
if ( u3_nul == val ) {
return u3_none;
} else {
u3_noun ret = u3k(u3t(val));
u3z(val);
if ( c3n == u3ud(ret) ) {
uL(fprintf(uH, "inode_load_data: not an atom\n"));
u3z(ret);
ret = 0;
}
return ret;
}
}
}
/* _inode_fill_directory(): fill directory inode.
*/
static u3_fdir*
_inode_fill_directory(u3_fnod* par_u, u3_noun kiz)
{
u3_fdir* dir_u;
dir_u = malloc(sizeof(u3_fdir));
dir_u->num_w = 0;
{
u3_noun zik = kiz;
while ( u3_nul != zik ) {
u3_noun ph_zik = u3h(u3h(zik));
c3_c* nam_c = u3r_string(ph_zik);
u3_fent* fen_u = calloc(1, sizeof(u3_fent));
fen_u->nod_u = _inode_make(par_u, nam_c);
fen_u->nex_u = dir_u->fen_u;
dir_u->fen_u = fen_u;
dir_u->num_w += 1;
zik = u3t(zik);
}
u3z(kiz);
}
return dir_u;
}
/* _inode_fill_file(): fill file inode.
*/
static u3_fval*
_inode_fill_file(u3_atom dat)
{
u3_fval* val_u = calloc(1, sizeof(u3_fval));
val_u->siz_z = u3r_met(3, dat);
val_u->buf_y = malloc(val_u->siz_z);
u3r_bytes(0, val_u->siz_z, val_u->buf_y, dat);
u3z(dat);
return val_u;
}
/* _inode_load(): load inode value.
*/
static c3_o
_inode_load(u3_fnod* nod_u)
{
if ( u3_nul == u3A->own ) {
return c3n;
}
else {
if ( nod_u->typ_e != u3_fuse_type_unknown ) {
return c3y;
}
else {
u3_noun hap = _inode_path(nod_u, u3_nul);
u3_weak ark = _inode_load_arch(u3k(hap));
c3_o ret;
if ( u3_none == ark ) {
ret = c3n;
}
else {
if ( u3_nul == u3h(ark) ) {
nod_u->typ_e = u3_fuse_type_directory;
nod_u->dir_u = _inode_fill_directory
(nod_u, u3qdb_tap(u3t(ark), u3_nul));
}
else {
u3_noun dat;
nod_u->typ_e = u3_fuse_type_file;
dat = _inode_load_data(u3k(hap));
nod_u->val_u = _inode_fill_file(dat);
}
ret = c3y;
u3z(ark);
}
u3z(hap);
return ret;
}
}
}
/**
* Initialize filesystem
*
* Called before any other filesystem method
*
* There's no reply to this function
*
* @param userdata the user data passed to fuse_lowlevel_new()
*/
static void
_fuse_ll_init(void* usr_v,
struct fuse_conn_info* con_u)
{
uL(fprintf(uH, "ll_init\n"));
{
_inode_init();
}
}
/**
* Look up a directory entry by name and get its attributes.
*
* Valid replies:
* fuse_reply_entry
* fuse_reply_err
*
* @param req request handle
* @param parent inode number of the parent directory
* @param name the name to look up
*/
static void
_fuse_ll_lookup(fuse_req_t req_u,
fuse_ino_t pno_i,
const c3_c* nam_c)
{
uL(fprintf(uH, "ll_lookup %ld %s\n", pno_i, nam_c));
{
u3_fnod* par_u = _inode_get(pno_i);
u3_fnod* nod_u;
// Find, then make.
{
for ( nod_u = par_u->kid_u; nod_u; nod_u = nod_u->nex_u ) {
if ( !strcmp(nam_c, nod_u->nam_c) ) {
break;
}
}
if ( !nod_u ) {
nod_u = _inode_make(par_u, strdup(nam_c));
}
}
if ( c3n == _inode_load(nod_u) ) {
fuse_reply_err(req_u, ENOENT);
}
else {
struct fuse_entry_param ent_u;
memset(&ent_u, 0, sizeof(ent_u));
if ( c3n == _inode_stat(nod_u, &ent_u.attr) ) {
fuse_reply_err(req_u, ENOENT);
}
ent_u.ino = nod_u->ino_i;
ent_u.generation = 1;
ent_u.attr_timeout = 1.0;
ent_u.entry_timeout = 1.0;
fuse_reply_entry(req_u, &ent_u);
}
}
}
/**
* Get file attributes
*
* Valid replies:
* fuse_reply_attr
* fuse_reply_err
*
* @param req request handle
* @param ino the inode number
* @param fi for future use, currently always NULL
*/
static void
_fuse_ll_getattr(fuse_req_t req_u,
fuse_ino_t ino_i,
struct fuse_file_info* ffi_u)
{
uL(fprintf(uH, "ll_getattr %ld\n", ino_i));
{
u3_fnod* nod_u = _inode_get(ino_i);
if ( c3n == _inode_load(nod_u) ) {
fuse_reply_err(req_u, ENOENT);
}
else {
struct stat buf_u;
if ( c3n == _inode_stat(nod_u, &buf_u) ) {
fuse_reply_err(req_u, ENOENT);
}
else {
fuse_reply_attr(req_u, &buf_u, 1.0);
}
}
}
}
/**
* Read directory
*
* Send a buffer filled using fuse_add_direntry(), with size not
* exceeding the requested size. Send an empty buffer on end of
* stream.
*
* fi->fh will contain the value set by the opendir method, or
* will be undefined if the opendir method didn't set any value.
*
* Valid replies:
* fuse_reply_buf
* fuse_reply_err
*
* @param req request handle
* @param ino the inode number
* @param size maximum number of bytes to send
* @param off offset to continue reading the directory stream
* @param fi file information
*/
static void
_fuse_ll_readdir(fuse_req_t req_u,
fuse_ino_t ino_i,
c3_z max_z,
c3_f off_f,
struct fuse_file_info* ffi_u)
{
uL(fprintf(uH, "ll_readdir %ld %ld %lld\n", ino_i, max_z, off_f));
{
u3_fnod* nod_u = _inode_get(ino_i);
if ( c3n == _inode_load(nod_u) ) {
fuse_reply_err(req_u, ENOENT);
}
else if ( u3_fuse_type_directory != nod_u->typ_e ) {
fuse_reply_err(req_u, ENOTDIR);
}
else {
struct _fusedr_buf buf_u;
memset(&buf_u, 0, sizeof(buf_u));
_fusedr_buf_add(req_u, &buf_u, ".", ino_i);
_fusedr_buf_add(req_u, &buf_u, "..", nod_u->par_u
? nod_u->par_u->ino_i
: ino_i);
{
u3_fent* fen_u;
for ( fen_u = nod_u->dir_u->fen_u; fen_u; fen_u = fen_u->nex_u ) {
_fusedr_buf_add(req_u,
&buf_u,
fen_u->nod_u->nam_c,
fen_u->nod_u->ino_i);
}
}
_fuse_buf_reply(req_u, buf_u.buf_c, buf_u.siz_z, off_f, max_z);
}
}
}
/**
* Open a file
*
* Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and
* O_TRUNC) are available in fi->flags.
*
* Filesystem may store an arbitrary file handle (pointer, index,
* etc) in fi->fh, and use this in other all other file operations
* (read, write, flush, release, fsync).
*
* Filesystem may also implement stateless file I/O and not store
* anything in fi->fh.
*
* There are also some flags (direct_io, keep_cache) which the
* filesystem may set in fi, to change the way the file is opened.
* See fuse_file_info structure in <fuse_common.h> for more details.
*
* Valid replies:
* fuse_reply_open
* fuse_reply_err
*
* @param req request handle
* @param ino the inode number
* @param fi file information
*/
static void
_fuse_ll_open(fuse_req_t req_u,
fuse_ino_t ino_i,
struct fuse_file_info* ffi_u)
{
uL(fprintf(uH, "ll_open %ld\n", ino_i));
{
u3_fnod* nod_u = _inode_get(ino_i);
if ( c3n == _inode_load(nod_u) ) {
fuse_reply_err(req_u, ENOENT);
}
else if ( u3_fuse_type_file != nod_u->typ_e ) {
fuse_reply_err(req_u, ENOTDIR);
}
else if ( (ffi_u->flags & 3) != O_RDONLY ) {
fuse_reply_err(req_u, EACCES);
}
else {
fuse_reply_open(req_u, ffi_u);
}
}
}
/**
* Read data
*
* Read should send exactly the number of bytes requested except
* on EOF or error, otherwise the rest of the data will be
* substituted with zeroes. An exception to this is when the file
* has been opened in 'direct_io' mode, in which case the return
* value of the read system call will reflect the return value of
* this operation.
*
* fi->fh will contain the value set by the open method, or will
* be undefined if the open method didn't set any value.
*
* Valid replies:
* fuse_reply_buf
* fuse_reply_err
*
* @param req request handle
* @param ino the inode number
* @param size number of bytes to read
* @param off offset to read from
* @param fi file information
*/
static void
_fuse_ll_read(fuse_req_t req_u,
fuse_ino_t ino_i,
c3_z max_z,
c3_f off_f,
struct fuse_file_info* ffi_u)
{
uL(fprintf(uH, "ll_read %ld %ld %lld\n", ino_i, max_z, off_f));
{
u3_fnod* nod_u = _inode_get(ino_i);
if ( c3n == _inode_load(nod_u) ) {
fuse_reply_err(req_u, ENOENT);
} else {
_fuse_buf_reply(req_u,
(c3_c*)(nod_u->val_u->buf_y),
nod_u->val_u->siz_z,
off_f,
max_z);
}
}
}
static struct fuse_lowlevel_ops fuse_api = {
.init = _fuse_ll_init,
.lookup = _fuse_ll_lookup,
.getattr = _fuse_ll_getattr,
.readdir = _fuse_ll_readdir,
.open = _fuse_ll_open,
.read = _fuse_ll_read,
};
/* _fuse_poll_cb():
*/
static void
_fuse_poll_cb(uv_poll_t* wax_u,
c3_i sas_i,
c3_i evt_i)
{
u3_fuse* fus_u = &u3_Host.fus_u;
uL(fprintf(uH, "fuse_poll_cb\n"));
{
c3_z buf_z = fuse_chan_bufsize(fus_u->cha_u);
c3_y* buf_y = malloc(buf_z + 1);
c3_i res_i = fuse_chan_recv(&fus_u->cha_u, (c3_c *)buf_y, buf_z);
if ( res_i < 0 ) {
if ( (res_i != -EINTR) && (res_i != -EAGAIN) ) {
uL(fprintf(uH, "fuse_poll_cb: error: %s\n", strerror(res_i)));
c3_assert(0);
}
}
else {
uL(fprintf(uH, "fuse_session_process\n"));
fuse_session_process(fus_u->sez_u,
(c3_c *)buf_y,
buf_z,
fus_u->cha_u);
uv_poll_start(&fus_u->wax_u, UV_READABLE, _fuse_poll_cb);
}
}
}
/* u3_fuse_io_init(): initialize FUSE.
*/
void
u3_fuse_io_init(void)
{
u3_fuse* fus_u = &u3_Host.fus_u;
#if 0
fus_u->mnt_c = malloc(strlen(u3_Host.dir_c) + 16);
strcpy(fus_u->mnt_c, u3_Host.dir_c);
strncat(fus_u->mnt_c, "/.urb/fun", 14);
#else
fus_u->mnt_c = strdup("/Users/cyarvin/urbit");
#endif
mkdir(fus_u->mnt_c, 0755);
uL(fprintf(uH, "fuse: mounting: %s\n", fus_u->mnt_c));
if ( !(fus_u->cha_u = fuse_mount(fus_u->mnt_c, 0)) ) {
uL(fprintf(uH, "fuse: could not mount %s\n", fus_u->mnt_c));
}
if ( !(fus_u->sez_u=fuse_lowlevel_new(0, &fuse_api, sizeof(fuse_api), 0)) ) {
uL(fprintf(uH, "fuse: could not create session\n"));
}
fuse_session_add_chan(fus_u->sez_u, fus_u->cha_u);
{
c3_i fid_i = fuse_chan_fd(fus_u->cha_u);
c3_i err_i;
uL(fprintf(uH, "fuse: fd: %d (loop %p)\n", fid_i, u3L));
if ( (err_i = uv_poll_init(u3L, &fus_u->wax_u, fid_i)) < 0 ) {
uL(fprintf(uH, "fuse: poll_init failed: %s\n", uv_strerror(err_i)));
}
uv_poll_start(&fus_u->wax_u, UV_READABLE, _fuse_poll_cb);
}
}
/* u3_fuse_io_exit(): shut down FUSE.
*/
void
u3_fuse_io_exit(void)
{
u3_fuse* fus_u = &u3_Host.fus_u;
uv_poll_stop(&fus_u->wax_u);
fuse_session_remove_chan(fus_u->cha_u);
fuse_session_destroy(fus_u->sez_u);
fuse_unmount(fus_u->mnt_c, fus_u->cha_u);
uL(fprintf(uH, "fuse: unmounted: %s\n", fus_u->mnt_c));
}

View File

@ -584,7 +584,6 @@ _http_conn_read_cb(uv_stream_t* tcp_u,
{
u3_hcon* hon_u = (u3_hcon*)(void*) tcp_u;
u3_lo_open();
{
if ( siz_w == UV_EOF ) {
_http_conn_dead(hon_u);
@ -606,7 +605,6 @@ _http_conn_read_cb(uv_stream_t* tcp_u,
free(buf_u->base);
}
}
u3_lo_shut(c3y);
}
/* _http_conn_new(): create http connection.
@ -893,7 +891,7 @@ _http_request(u3_hreq* req_u)
c3__chis :
c3__this;
u3v_plan(pox,
u3_pier_plan(pox,
u3nq(typ,
req_u->hon_u->htp_u->sec,
u3nc(c3y, u3i_words(1, &req_u->ipf_w)),
@ -910,7 +908,7 @@ _http_request_dead(u3_hreq* req_u)
req_u->hon_u->coq_l,
req_u->seq_l);
u3v_plan(pox, u3nc(c3__thud, u3_nul));
u3_pier_plan(pox, u3nc(c3__thud, u3_nul));
}
/* _http_flush(): transmit any ready data.
@ -1001,7 +999,7 @@ u3_http_ef_bake(void)
{
u3_noun pax = u3nq(u3_blip, c3__http, u3k(u3A->sen), u3_nul);
u3v_plan(pax, u3nc(c3__born, u3_nul));
u3_pier_plan(pax, u3nc(c3__born, u3_nul));
}
/* u3_http_ef_thou(): send %thou effect (incoming response) to http.

38920
vere/ivory.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,845 +0,0 @@
/* v/loop.c
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <setjmp.h>
#include <gmp.h>
#include <sigsegv.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <uv.h>
#include <errno.h>
#include <curses.h>
#include <termios.h>
#include <term.h>
#include "all.h"
#include "vere/vere.h"
#if 0
static jmp_buf Signal_buf;
#ifndef SIGSTKSZ
# define SIGSTKSZ 16384
#endif
static uint8_t Sigstk[SIGSTKSZ];
uint8_t u3_Critical;
typedef enum {
sig_none,
sig_overflow,
sig_interrupt,
sig_terminate,
sig_memory,
sig_assert,
sig_timer
} u3_kill;
volatile u3_kill Sigcause; // reasons for exception
static void _lo_cont(void *arg1, void *arg2, void *arg3)
{
(void)(arg1);
(void)(arg2);
(void)(arg3);
siglongjmp(Signal_buf, 1);
}
static void
_lo_signal_handle_over(int emergency, stackoverflow_context_t scp)
{
if ( u3_Critical ) {
// Careful not to grow the stack during critical sections.
//
write(2, "stack disaster\n", strlen("stack disaster" + 2));
abort();
}
#if 0
if ( 1 == emergency ) {
write(2, "stack emergency\n", strlen("stack emergency" + 2));
abort();
} else
#endif
{
Sigcause = sig_overflow;
sigsegv_leave_handler(_lo_cont, NULL, NULL, NULL);
}
}
static void
_lo_signal_handle_term(int x)
{
if ( !u3_Critical ) {
Sigcause = sig_terminate;
u3_Host.liv = c3n;
longjmp(Signal_buf, 1);
}
}
static void
_lo_signal_handle_intr(int x)
{
if ( !u3_Critical ) {
Sigcause = sig_interrupt;
longjmp(Signal_buf, 1);
}
}
static void
_lo_signal_handle_alrm(int x)
{
if ( !u3_Critical ) {
Sigcause = sig_timer;
longjmp(Signal_buf, 1);
}
}
/* _lo_signal_done():
*/
static void
_lo_signal_done()
{
// signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGVTALRM, SIG_IGN);
stackoverflow_deinstall_handler();
{
struct itimerval itm_u;
timerclear(&itm_u.it_interval);
timerclear(&itm_u.it_value);
setitimer(ITIMER_VIRTUAL, &itm_u, 0);
}
u3_unix_ef_move();
}
/* _lo_signal_deep(): start deep processing; set timer for sec_w or 0.
*/
static void
_lo_signal_deep(c3_w sec_w)
{
u3_unix_ef_hold();
stackoverflow_install_handler(_lo_signal_handle_over, Sigstk, SIGSTKSZ);
signal(SIGINT, _lo_signal_handle_intr);
signal(SIGTERM, _lo_signal_handle_term);
{
struct itimerval itm_u;
timerclear(&itm_u.it_interval);
itm_u.it_value.tv_sec = sec_w;
itm_u.it_value.tv_usec = 0;
setitimer(ITIMER_VIRTUAL, &itm_u, 0);
}
signal(SIGVTALRM, _lo_signal_handle_alrm);
}
#endif
/* u3_loop_signal_memory(): end computation for out-of-memory.
*/
void
u3_loop_signal_memory()
{
fprintf(stderr, "\r\nout of memory\r\n");
c3_assert(0);
#if 0
Sigcause = sig_memory;
longjmp(Signal_buf, 1);
#endif
}
/* _lo_init(): initialize I/O across the process.
*/
static void
_lo_init()
{
c3_l cod_l;
cod_l = u3a_lush(c3__unix);
u3_unix_io_init();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__ames);
u3_ames_io_init();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__term);
u3_term_io_init();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__http);
u3_http_io_init();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__cttp);
u3_cttp_io_init();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__save);
u3_save_io_init();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__behn);
u3_behn_io_init();
u3a_lop(cod_l);
}
/* _lo_talk(): bring up listeners across the process.
*/
static void
_lo_talk()
{
c3_l cod_l;
cod_l = u3a_lush(c3__unix);
u3_unix_io_talk();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__ames);
u3_ames_io_talk();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__http);
u3_http_io_talk();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__term);
u3_term_io_talk();
u3a_lop(cod_l);
}
/* u3_lo_exit(): terminate I/O across the process.
*/
void
u3_lo_exit(void)
{
c3_l cod_l;
cod_l = u3a_lush(c3__unix);
u3_unix_io_exit();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__ames);
u3_ames_io_exit();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__term);
u3_term_io_exit();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__http);
u3_http_io_exit();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__cttp);
u3_cttp_io_exit();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__save);
u3_save_io_exit();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__behn);
u3_behn_io_exit();
u3a_lop(cod_l);
}
/* _lo_poll(): reset event flags across the process.
*/
static void
_lo_poll(void)
{
c3_l cod_l;
cod_l = u3a_lush(c3__ames);
u3_ames_io_poll();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__http);
u3_http_io_poll();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__term);
u3_term_io_poll();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__save);
u3_save_io_poll();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__unix);
u3_unix_io_poll();
u3a_lop(cod_l);
cod_l = u3a_lush(c3__behn);
u3_behn_io_poll();
u3a_lop(cod_l);
}
#if 0
/* _lo_how(): print how.
*/
static const c3_c*
_lo_how(u3_noun how)
{
switch ( how ) {
default: c3_assert(0); break;
case c3__ames: return "ames";
case c3__behn: return "behn";
case c3__term: return "cons";
case c3__htcn: return "http-conn";
case c3__htls: return "http-lisn";
case c3__save: return "save";
case c3__unix: return "unix";
}
}
#endif
/* u3_lo_bail(): clean up all event state.
*/
void
u3_lo_bail(void)
{
fflush(stdout);
u3_lo_exit();
exit(1);
}
/* _lo_tape(): dump a tape, old style. Don't do this.
*/
static void
_lo_tape(FILE* fil_u, u3_noun tep)
{
u3_noun tap = tep;
while ( c3y == u3du(tap) ) {
c3_c car_c;
if ( u3h(tap) >= 127 ) {
car_c = '?';
} else car_c = u3h(tap);
putc(car_c, fil_u);
tap = u3t(tap);
}
u3z(tep);
}
/* _lo_wall(): dump a wall, old style. Don't do this.
*/
static void
_lo_wall(u3_noun wol)
{
FILE* fil_u = u3_term_io_hija();
u3_noun wal = wol;
while ( u3_nul != wal ) {
_lo_tape(fil_u, u3k(u3h(wal)));
putc(13, fil_u);
putc(10, fil_u);
wal = u3t(wal);
}
u3_term_io_loja(0);
u3z(wol);
}
/* u3_lo_tank(): dump single tank.
*/
void
u3_lo_tank(c3_l tab_l, u3_noun tac)
{
u3_lo_punt(tab_l, u3nc(tac, u3_nul));
}
/* u3_lo_punt(): dump tank list.
*/
void
u3_lo_punt(c3_l tab_l, u3_noun tac)
{
u3_noun blu = u3_term_get_blew(0);
c3_l col_l = u3h(blu);
u3_noun cat = tac;
// We are calling nock here, but hopefully need no protection.
//
while ( c3y == u3r_du(cat) ) {
if ( 0 == u3A->roc ) {
u3_noun act = u3h(cat);
if ( c3__leaf == u3h(act) ) {
FILE* fil_u = u3_term_io_hija();
_lo_tape(fil_u, u3k(u3t(act)));
putc(13, fil_u);
putc(10, fil_u);
u3_term_io_loja(0);
}
}
else {
u3_noun wol = u3dc("wash", u3nc(tab_l, col_l), u3k(u3h(cat)));
_lo_wall(wol);
}
cat = u3t(cat);
}
u3z(tac);
u3z(blu);
}
/* u3_lo_sway(): print trace.
*/
void
u3_lo_sway(c3_l tab_l, u3_noun tax)
{
u3_noun mok = u3dc("mook", 2, tax);
u3_lo_punt(tab_l, u3k(u3t(mok)));
u3z(mok);
}
/* _lo_time(): set time.
*/
static void
_lo_time(void)
{
struct timeval tim_tv;
gettimeofday(&tim_tv, 0);
u3v_time(u3_time_in_tv(&tim_tv));
}
/* u3_lo_open(): begin callback processing.
*/
void
u3_lo_open(void)
{
if ( u3C.wag_w & (u3o_debug_ram | u3o_check_corrupt) ) {
//
// Assumption: there are no noun roots outside u3A.
//
u3m_grab(u3_none);
}
#if 0
if ( u3C.wag_w & u3o_debug_cpu ) {
struct itimerval itm_u;
getitimer(ITIMER_VIRTUAL, &itm_u);
fprintf(stderr, "tv_sec %d, tv_usec %d, value %d/%d\r\n",
itm_u.it_interval.tv_sec,
itm_u.it_interval.tv_usec,
itm_u.it_value.tv_sec,
itm_u.it_interval.tv_usec);
}
#endif
_lo_time();
}
/* u3_lo_shut(): end callback processing.
*/
void
u3_lo_shut(c3_o inn)
{
// u3m_grab(u3_none);
// process actions
//
u3_raft_work();
// u3_lo_grab("lo_shut b", u3_none);
// update time
//
_lo_time();
// u3_lo_grab("lo_shut c", u3_none);
// for input operations, poll fs (XX not permanent)
// XX remove raty_lead guard
//
if ( c3y == inn ) {
u3_unix_ef_look(c3n);
u3_raft_work();
_lo_time();
}
// u3_lo_grab("lo_shut d", u3_none);
// clean shutdown
//
if ( c3n == u3_Host.liv ) {
// direct save and die
//
// u3_lo_grab("lo_exit", u3_none);
// u3_loom_save(u3A->ent_d);
// u3_loom_exit();
u3t_damp();
u3_lo_exit();
// save a checkpoint before exiting
u3e_save();
exit(u3_Host.xit_i);
}
else {
// poll arvo to generate any event binding changes
//
_lo_poll();
}
}
#if 0
// _lo_bench_noop(): benchmark no-op events.
//
static void
_lo_bench_noop(c3_w num_w)
{
c3_w i_w;
for ( i_w = 0; i_w < num_w; i_w++ ) {
u3_reck_plan(u3A, u3nq(u3_blip, c3__term, 1, u3_nul),
u3nc(c3__noop, u3_nul));
}
u3_raft_work(u3A);
}
// _lo_bench_scot_p(): benchmark prettyprint.
//
static void
_lo_bench_scot_p(c3_w num_w)
{
c3_w i_w;
for ( i_w = 0; i_w < num_w; i_w++ ) {
u3_noun soc = u3dc("scot", 'p', u3k(u3A->now));
u3z(soc);
}
}
// _lo_bench_slay_p(): benchmark prettyprint.
//
static void
_lo_bench_slay_p(c3_w num_w)
{
c3_w i_w;
for ( i_w = 0; i_w < num_w; i_w++ ) {
u3_noun soc = u3dc("scot", 'p', u3k(u3A->now));
u3_noun dub = u3do("slay", soc);
u3z(dub);
}
}
// _lo_bench_scot_da(): benchmark prettyprint.
//
static void
_lo_bench_scot_da(c3_w num_w)
{
c3_w i_w;
for ( i_w = 0; i_w < num_w; i_w++ ) {
u3_noun soc = u3dc("scot", c3__da, u3k(u3A->now));
u3z(soc);
}
}
// _lo_bench_dec(): benchmark decrement.
//
static void
_lo_bench_dec(c3_w num_w)
{
c3_w i_w;
for ( i_w = 0; i_w < num_w; i_w++ ) {
u3_noun soc = u3do("dec", u3k(u3A->now));
u3z(soc);
}
}
// _lo_bench_scot_ud(): benchmark prettyprint.
//
static void
_lo_bench_scot_ud(c3_w num_w)
{
c3_w i_w;
for ( i_w = 0; i_w < num_w; i_w++ ) {
u3_noun soc = u3dc("scot", c3__ud, u3k(u3A->now));
u3z(soc);
}
}
// _lo_bench(): lo-tech profiling.
//
static void
_lo_bench(const c3_c* lab_c, void (*fun)(c3_w), c3_w num_w)
{
u3_noun old, new;
uL(fprintf(uH, "bench: %s: start...\n", lab_c));
u3_reck_time(u3A);
old = u3k(u3A->now);
fun(num_w);
u3_reck_time(u3A);
new = u3k(u3A->now);
{
c3_w tms_w = (c3_w)u3_time_gap_ms(old, new);
if ( tms_w > (10 * num_w) ) {
uL(fprintf(uH, "bench: %s*%d: %d ms, %d ms each.\n",
lab_c, num_w, tms_w, (tms_w / num_w)));
}
else {
uL(fprintf(uH, "bench: %s*%d: %d ms, %d us each.\n",
lab_c, num_w, tms_w, ((tms_w * 1000) / num_w)));
}
}
}
#endif
/* u3_lo_show(): generic noun print.
*/
void
u3_lo_show(c3_c* cap_c, u3_noun nun)
{
u3_noun pav = u3dc("pave", c3__noun, nun);
c3_c* txt_c = (c3_c*)u3r_tape(pav);
fprintf(stderr, "%s: %s\r\n", cap_c, txt_c);
u3z(pav);
free(txt_c);
}
static void
_lo_slow()
{
#if 0
_lo_bench("scot %p", _lo_bench_scot_p, 256);
_lo_bench("scot %da", _lo_bench_scot_da, 256);
_lo_bench("scot %ud", _lo_bench_scot_ud, 256);
_lo_bench("slay %p", _lo_bench_slay_p, 256);
_lo_bench("noop", _lo_bench_noop, 256);
#endif
}
/* u3_lo_loop(): begin main event loop.
*/
void
u3_lo_loop()
{
uv_loop_t* lup_u = uv_default_loop();
u3_Host.lup_u = lup_u;
signal(SIGPIPE, SIG_IGN); // pipe, schmipe
// signal(SIGIO, SIG_IGN); // linux is wont to produce for some reason
_lo_init();
u3_raft_init();
if ( _(u3_Host.ops_u.tex) ) {
u3t_boff();
u3t_damp();
u3_lo_exit();
fprintf(stderr, "dry run: exit\r\n");
exit(0);
}
else {
if ( c3n == u3_Host.ops_u.bat ) {
uv_run(u3L, UV_RUN_DEFAULT);
}
}
}
/* u3_lo_lead(): actions on promotion to leader.
*/
void
u3_lo_lead(void)
{
// Further server configuration.
//
{
u3_http_ef_bake();
}
_lo_talk();
{
u3_unix_ef_look(c3n);
u3v_plan(u3nt(u3_blip, c3__ames, u3_nul),
u3nc(c3__kick, u3k(u3A->now)));
}
_lo_poll();
#if 0
u3_loom_save(u3A->ent_d);
u3_Host.sav_u.ent_d = rec_u->ent_d;
#endif
if ( c3y == u3_Host.ops_u.nuu ) {
if ( u3_Host.ops_u.who_c ) {
u3_term_ef_ticket(u3_Host.ops_u.who_c, u3_Host.ops_u.tic_c);
}
u3_term_ef_boil(1);
}
if ( c3y == u3_Host.ops_u.veb ) {
u3_term_ef_verb();
}
#if 1
_lo_slow();
#endif
}
#if 0
/* _lo_mark_reck(): mark a reck.
*/
static c3_w
_lo_mark_reck(u3_reck* rec_u)
{
c3_w siz_w = 0;
c3_w egg_w;
siz_w += u3m_mark_noun(rec_u->ken);
siz_w += u3m_mark_noun(rec_u->roc);
siz_w += u3m_mark_noun(rec_u->yot);
siz_w += u3m_mark_noun(rec_u->now);
siz_w += u3m_mark_noun(rec_u->wen);
siz_w += u3m_mark_noun(rec_u->sen);
siz_w += u3m_mark_noun(rec_u->own);
siz_w += u3m_mark_noun(rec_u->roe);
siz_w += u3m_mark_noun(rec_u->key);
{
u3_cart* egg_u;
egg_w = 0;
for ( egg_u = rec_u->ova.egg_u; egg_u; egg_u = egg_u->nex_u ) {
egg_w += u3m_mark_noun(egg_u->vir);
}
siz_w += egg_w;
}
#if 0
fprintf(stderr, "ken %d, roc %d, yot %d, roe %d, egg %d\r\n",
ken_w, roc_w, yot_w, roe_w, egg_w);
#endif
return siz_w;
}
/* _lo_mark(): mark the whole vere system.
*/
static c3_w
_lo_mark()
{
c3_w siz_w;
siz_w = u3m_mark_internal();
siz_w += _lo_mark_reck(u3_Host.arv_u);
return siz_w;
}
#endif
#if 0
/* _lo_word(): print a word to the passed stream.
*/
static void
_lo_word(FILE* fil_u, c3_w wod_w)
{
u3_noun top = c3y;
if ( wod_w / (1000 * 1000 * 1000) ) {
fprintf(fil_u, "%u.", wod_w / (1000 * 1000 * 1000));
wod_w %= (1000 * 1000 * 1000);
top = c3n;
}
if ( wod_w / (1000 * 1000) ) {
fprintf(fil_u, ((top == c3y) ? "%u." : "%03u."),
wod_w / (1000 * 1000));
wod_w %= (1000 * 1000);
top = c3n;
}
if ( wod_w / 1000 ) {
fprintf(fil_u, ((top == c3y) ? "%u." : "%03u."), wod_w / 1000);
wod_w %= 1000;
top = c3n;
}
fprintf(fil_u, ((top == c3y) ? "%u" : "%03u"), wod_w);
}
/* u3_lo_grab(): garbage-collect the world, plus roots.
*/
void
u3_lo_grab(c3_c* cap_c, u3_noun som, ...)
{
c3_w siz_w, lec_w;
siz_w = _lo_mark();
{
va_list vap;
u3_noun tur;
va_start(vap, som);
if ( som != u3_none ) {
siz_w += u3m_mark_noun(som);
while ( u3_none != (tur = va_arg(vap, u3_noun)) ) {
siz_w += u3m_mark_noun(tur);
}
}
va_end(vap);
}
lec_w = u3m_sweep(siz_w);
// if ( lec_w || (c3y == u3_Flag_Verbose) )
if ( lec_w || !strcmp("init", cap_c) ) {
FILE* fil_u = uH;
fprintf(fil_u, "%s: gc: ", cap_c);
if ( lec_w ) {
_lo_word(fil_u, 4 * lec_w);
fprintf(fil_u, " bytes shed; ");
}
_lo_word(fil_u, 4 * siz_w);
uL(fprintf(fil_u, " bytes live\n"));
#if 0
if ( lec_w ) {
uL(fprintf(uH, "zero garbage tolerance!\n"));
u3_lo_exit();
c3_assert(0);
exit(1);
}
#endif
}
u3_wire_lan(u3_Wire) = c3y;
}
#endif

View File

@ -1,5 +1,4 @@
/* v/main.c
**
*/
#include <stdio.h>
#include <stdlib.h>
@ -395,7 +394,7 @@ overflow_handler(int emergency, stackoverflow_context_t scp)
//
u3_lo_sway(0, u3k(u3_wire_tax(u3_Wire)));
u3_lo_bail(u3A);
u3_pier_exit(u3A);
exit(1);
}
@ -434,13 +433,27 @@ void
_stop_exit(c3_i int_i)
{
fprintf(stderr, "\r\n[received keyboard stop signal, exiting]\r\n");
u3_lo_bail();
u3_pier_exit();
}
c3_i
main(c3_i argc,
c3_c** argv)
{
// Detect executable purpose.
//
{
c3_c* nam_c = strrchr(argv[0], '/');
if ( !nam_c )
nam_c = argv[0];
else nam_c++;
if ( !strcmp("urbit-worker", nam_c) ) {
return u3_serf_main(argc, argv);
}
}
// Parse options.
//
if ( c3n == _main_getopt(argc, argv) ) {
@ -453,21 +466,6 @@ main(c3_i argc,
return 0;
}
if ( c3y == u3_Host.ops_u.nuu ) {
struct stat s;
if ( !stat(u3_Host.dir_c, &s) ) {
fprintf(stderr, "tried to create, but %s already exists\n", u3_Host.dir_c);
fprintf(stderr, "normal usage: %s %s\n", argv[0], u3_Host.dir_c);
exit(1);
}
} else {
struct stat s;
if ( -1 == stat(u3_Host.dir_c, &s) ) {
fprintf(stderr, "%s: urbit not found\n", u3_Host.dir_c);
u3_ve_usage(argc, argv);
}
}
#if 0
if ( 0 == getuid() ) {
chroot(u3_Host.dir_c);
@ -546,38 +544,8 @@ main(c3_i argc,
u3C.wag_w |= u3o_dryrun;
}
}
u3m_boot(u3_Host.ops_u.nuu,
u3_Host.ops_u.gab,
u3_Host.dir_c,
u3_Host.ops_u.pil_c);
/* Start Arvo.
*/
#if 1
{
struct timeval tim_tv;
u3_noun now;
gettimeofday(&tim_tv, 0);
now = u3_time_in_tv(&tim_tv);
u3v_start(now);
}
#endif
#if 0
/* Initial checkpoint.
*/
if ( _(u3_Host.ops_u.nuu) ) {
printf("about to save.\r\n");
u3e_save();
printf("saved.\r\n");
}
#endif
u3_pier_boot(u3_Host.dir_c, u3_Host.ops_u.pil_c);
}
// u3e_grab("main", u3_none);
//
u3_lo_loop();
return 0;
}

335
vere/newt.c Normal file
View File

@ -0,0 +1,335 @@
/* vere/newt.c
**
** implements noun blob messages with trivial framing.
**
** a message is a 64-bit little-endian byte count, followed
** by the indicated number of bytes. the bytes are the
** the ++cue of of a noun.
**
** the implementation is relatively inefficient and could
** lose a few copies, mallocs, etc.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <setjmp.h>
#include <gmp.h>
#include <sigsegv.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <uv.h>
#include <errno.h>
#include <curses.h>
#include <termios.h>
#include <term.h>
#include "all.h"
#include "vere/vere.h"
/* _newt_consume(): advance buffer processing.
*/
static void
_newt_consume(u3_moat* mot_u)
{
/* process stray bytes, trying to create a new message
** or add a block to an existing one.
*/
while ( 1 ) {
if ( mot_u->rag_y ) {
/* if there is a live message, add a block to the queue.
*/
if ( mot_u->mes_u ) {
u3_meat* met_u;
/* create block
*/
met_u = c3_malloc(mot_u->len_d + (c3_d) sizeof(u3_meat));
met_u->nex_u = 0;
met_u->len_d = mot_u->len_d;
memcpy(met_u->hun_y, mot_u->rag_y, mot_u->len_d);
#if 0
fprintf(stderr,
"newt: %d: create: msg %p, new block %p, len %lld, has %lld, needs %lld\r\n",
getpid(),
mot_u->mes_u,
met_u,
met_u->len_d,
mot_u->mes_u->has_d,
mot_u->mes_u->len_d);
#endif
/* enqueue block
*/
if ( !mot_u->mes_u->meq_u ) {
mot_u->mes_u->meq_u = mot_u->mes_u->qem_u = met_u;
}
else {
mot_u->mes_u->qem_u->nex_u = met_u;
mot_u->mes_u->qem_u = met_u;
}
mot_u->mes_u->has_d += met_u->len_d;
/* free consumed stray bytes
*/
c3_free(mot_u->rag_y);
mot_u->len_d = 0;
mot_u->rag_y = 0;
}
else {
/* no message, but enough stray bytes to fill in
** a length; collect them and create a message.
*/
if ( mot_u->len_d >= 8ULL ) {
c3_d nel_d = 0;
nel_d |= ((c3_d) mot_u->rag_y[0]) << 0ULL;
nel_d |= ((c3_d) mot_u->rag_y[1]) << 8ULL;
nel_d |= ((c3_d) mot_u->rag_y[2]) << 16ULL;
nel_d |= ((c3_d) mot_u->rag_y[3]) << 24ULL;
nel_d |= ((c3_d) mot_u->rag_y[4]) << 32ULL;
nel_d |= ((c3_d) mot_u->rag_y[5]) << 40ULL;
nel_d |= ((c3_d) mot_u->rag_y[6]) << 48ULL;
nel_d |= ((c3_d) mot_u->rag_y[7]) << 56ULL;
#if 0
fprintf(stderr, "newt: %d: parsed length %lld\r\n",
getpid(),
nel_d);
#endif
mot_u->len_d -= 8ULL;
mot_u->mes_u = c3_malloc(sizeof(u3_mess));
mot_u->mes_u->len_d = nel_d;
mot_u->mes_u->has_d = 0;
mot_u->mes_u->meq_u = mot_u->mes_u->qem_u = 0;
if ( !mot_u->len_d ) {
c3_free(mot_u->rag_y);
mot_u->rag_y = 0;
}
else {
/* remove consumed length from stray bytes
*/
c3_y* buf_y = c3_malloc(mot_u->len_d);
memcpy(buf_y, mot_u->rag_y + 8, mot_u->len_d);
c3_free(mot_u->rag_y);
mot_u->rag_y = buf_y;
/* remaining bytes will be installed as message meat
*/
continue;
}
}
}
}
/* check for message completions
*/
if ( mot_u->mes_u && (mot_u->mes_u->has_d >= mot_u->mes_u->len_d) ) {
c3_d len_d = mot_u->mes_u->len_d;
c3_y* buf_y = c3_malloc(len_d);
c3_d pat_d = 0;
u3_meat* met_u;
/* we should have just cleared this
*/
c3_assert(!mot_u->rag_y);
c3_assert(!mot_u->len_d);
/* collect queue blocks, cleaning them up; return any spare meat
** to the rag.
*/
{
met_u = mot_u->mes_u->meq_u;
while ( met_u && (pat_d < len_d) ) {
u3_meat* nex_u = met_u->nex_u;
c3_d end_d = (pat_d + met_u->len_d);
c3_d eat_d;
c3_d rem_d;
eat_d = c3_min(len_d, end_d) - pat_d;
memcpy(buf_y + pat_d, met_u->hun_y, eat_d);
pat_d += eat_d;
rem_d = (met_u->len_d - eat_d);
if ( rem_d ) {
mot_u->rag_y = c3_malloc(rem_d);
memcpy(mot_u->rag_y, met_u->hun_y + eat_d, rem_d);
mot_u->len_d = rem_d;
/* one: unless we got a bad length, this has to be the last
** block in the message.
**
** two: bad data on a newt channel can cause us to assert.
** that's actually the right thing for a private channel.
*/
c3_assert(0 == nex_u);
}
c3_free(met_u);
met_u = nex_u;
}
c3_assert(pat_d == len_d);
/* clear the message
*/
c3_free(mot_u->mes_u);
mot_u->mes_u = 0;
}
/* build and send the object
*/
{
u3_noun mat = u3i_bytes((c3_w) len_d, buf_y);
mot_u->pok_f(mot_u->vod_p, mat);
}
/* continue; spare meat may need processing
*/
continue;
}
/* nothing happening, await next event
*/
break;
}
}
/* _raft_alloc(): libuv-style allocator for raft.
*/
static void
_newt_alloc(uv_handle_t* had_u,
size_t len_i,
uv_buf_t* buf_u)
{
void* ptr_v = c3_malloc(len_i);
*buf_u = uv_buf_init(ptr_v, len_i);
}
/* _newt_read_cb(): stream input callback.
*/
void
_newt_read_cb(uv_stream_t* str_u,
ssize_t len_i,
const uv_buf_t* buf_u)
{
c3_d len_d = (c3_d) len_i;
u3_moat* mot_u = (void *)str_u;
if ( UV_EOF == len_i ) {
// fprintf(stderr, "newt: %d: stream closed\r\n", getpid());
uv_read_stop(str_u);
mot_u->bal_f(mot_u->vod_p, "stream closed");
}
else {
#if 0
fprintf(stderr, "newt: %d: read %ld\r\n", getpid(), len_i);
#endif
if ( mot_u->rag_y ) {
mot_u->rag_y = c3_realloc(mot_u->rag_y, mot_u->len_d + len_d);
memcpy(mot_u->rag_y + mot_u->len_d, buf_u->base, len_d);
c3_free(buf_u->base);
}
else {
mot_u->rag_y = (c3_y *)buf_u->base;
mot_u->len_d = len_d;
}
_newt_consume(mot_u);
}
}
/* u3_newt_read(): start stream reading.
*/
void
u3_newt_read(u3_moat* mot_u)
{
c3_i err_i;
mot_u->mes_u = 0;
mot_u->len_d = 0;
mot_u->rag_y = 0;
err_i = uv_read_start((uv_stream_t*) &mot_u->pyp_u,
_newt_alloc,
_newt_read_cb);
if ( err_i != 0 ) {
mot_u->bal_f(mot_u, uv_strerror(err_i));
}
}
/* write request for newt
*/
struct _u3_write_t {
uv_write_t wri_u;
u3_mojo* moj_u;
void* vod_p;
c3_y* buf_y;
};
/* _newt_write_cb(): generic write callback.
*/
static void
_newt_write_cb(uv_write_t* wri_u, c3_i sas_i)
{
struct _u3_write_t* req_u = (struct _u3_write_t*)wri_u;
void* vod_p = req_u->vod_p;
u3_mojo* moj_u = req_u->moj_u;
free(req_u->buf_y);
free(req_u);
if ( 0 != sas_i ) {
fprintf(stderr, "newt: bad write %d\r\n", sas_i);
moj_u->bal_f(vod_p, uv_strerror(sas_i));
}
}
/* u3_newt_write(): write atom to stream; free atom.
*/
void
u3_newt_write(u3_mojo* moj_u,
u3_atom mat,
void* vod_p)
{
c3_w len_w = u3r_met(3, mat);
c3_y* buf_y = c3_malloc(len_w + 8);
struct _u3_write_t* req_u = c3_malloc(sizeof(*req_u));
uv_buf_t buf_u;
c3_i err_i;
/* write header; c3_d is futureproofing
*/
buf_y[0] = ((len_w >> 0) & 0xff);
buf_y[1] = ((len_w >> 8) & 0xff);
buf_y[2] = ((len_w >> 16) & 0xff);
buf_y[3] = ((len_w >> 24) & 0xff);
buf_y[4] = buf_y[5] = buf_y[6] = buf_y[7] = 0;
u3r_bytes(0, len_w, buf_y + 8, mat);
u3z(mat);
req_u->moj_u = moj_u;
req_u->buf_y = buf_y;
buf_u.base = (c3_c*) buf_y;
buf_u.len = len_w + 8;
#if 0
fprintf(stderr, "newt: %d: write %d\n", getpid(), len_w + 8);
#endif
if ( 0 != (err_i = uv_write((uv_write_t*)req_u,
(uv_stream_t*)&moj_u->pyp_u,
&buf_u,
1,
_newt_write_cb)) )
{
moj_u->bal_f(moj_u, uv_strerror(err_i));
}
}

1858
vere/pier.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -69,7 +69,7 @@ _reck_lily(u3_noun fot, u3_noun txt, c3_l* tid_l)
/* _reck_kick_term(): apply terminal outputs.
*/
static u3_noun
_reck_kick_term(u3_noun pox, c3_l tid_l, u3_noun fav)
_reck_kick_term(u3_pier* pir_u, u3_noun pox, c3_l tid_l, u3_noun fav)
{
u3_noun p_fav;
@ -92,7 +92,7 @@ _reck_kick_term(u3_noun pox, c3_l tid_l, u3_noun fav)
case c3__logo:
{
u3_Host.liv = c3n;
u3_pier_exit();
u3_Host.xit_i = u3t(fav);
u3z(pox); u3z(fav); return c3y;
@ -122,7 +122,8 @@ _reck_kick_term(u3_noun pox, c3_l tid_l, u3_noun fav)
/* _reck_kick_http(): apply http effects.
*/
static u3_noun
_reck_kick_http(u3_noun pox,
_reck_kick_http(u3_pier* pir_u,
u3_noun pox,
c3_l sev_l,
c3_l coq_l,
c3_l seq_l,
@ -157,7 +158,7 @@ _reck_kick_http(u3_noun pox,
/* _reck_kick_sync(): apply sync outputs.
*/
static u3_noun
_reck_kick_sync(u3_noun pox, u3_noun fav)
_reck_kick_sync(u3_pier* pir_u, u3_noun pox, u3_noun fav)
{
switch ( u3h(fav) ) {
default: break;
@ -184,7 +185,7 @@ _reck_kick_sync(u3_noun pox, u3_noun fav)
}
static u3_noun
_reck_kick_newt(u3_noun pox, u3_noun fav)
_reck_kick_newt(u3_pier* pir_u, u3_noun pox, u3_noun fav)
{
switch ( u3h(fav) ) {
default: break;
@ -192,7 +193,7 @@ _reck_kick_newt(u3_noun pox, u3_noun fav)
u3_noun lan = u3k(u3h(u3t(fav)));
u3_noun pac = u3k(u3t(u3t(fav)));
u3_ames_ef_send(lan, pac);
u3_ames_ef_send(pir_u, lan, pac);
u3z(pox); u3z(fav); return c3y;
} break;
}
@ -202,7 +203,7 @@ _reck_kick_newt(u3_noun pox, u3_noun fav)
/* _reck_kick_ames(): apply packet network outputs.
*/
static u3_noun
_reck_kick_ames(u3_noun pox, u3_noun fav)
_reck_kick_ames(u3_pier* pir_u, u3_noun pox, u3_noun fav)
{
u3_noun p_fav;
@ -222,7 +223,7 @@ _reck_kick_ames(u3_noun pox, u3_noun fav)
/* _reck_kick_spec(): apply an effect, by path.
*/
static u3_noun
_reck_kick_spec(u3_noun pox, u3_noun fav)
_reck_kick_spec(u3_pier* pir_u, u3_noun pox, u3_noun fav)
{
u3_noun i_pox, t_pox;
u3_noun p_fav;
@ -275,17 +276,17 @@ _reck_kick_spec(u3_noun pox, u3_noun fav)
}
}
}
return _reck_kick_http(pox, sev_l, coq_l, seq_l, fav);
return _reck_kick_http(pir_u, pox, sev_l, coq_l, seq_l, fav);
} break;
case c3__clay:
case c3__boat:
case c3__sync: {
return _reck_kick_sync(pox, fav);
return _reck_kick_sync(pir_u, pox, fav);
} break;
case c3__newt: {
return _reck_kick_newt(pox, fav);
return _reck_kick_newt(pir_u, pox, fav);
} break;
case c3__ames: {
@ -293,7 +294,7 @@ _reck_kick_spec(u3_noun pox, u3_noun fav)
u3z(pox); u3z(fav); return c3n;
}
else {
return _reck_kick_ames(pox, fav);
return _reck_kick_ames(pir_u, pox, fav);
}
} break;
@ -317,7 +318,7 @@ _reck_kick_spec(u3_noun pox, u3_noun fav)
uL(fprintf(uH, "term: bad tire\n"));
u3z(pox); u3z(fav); return c3n;
} else {
return _reck_kick_term(pox, tid_l, fav);
return _reck_kick_term(pir_u, pox, tid_l, fav);
}
} break;
}
@ -329,7 +330,7 @@ _reck_kick_spec(u3_noun pox, u3_noun fav)
/* _reck_kick_norm(): non path-specific effect handling.
*/
static u3_noun
_reck_kick_norm(u3_noun pox, u3_noun fav)
_reck_kick_norm(u3_pier* pir_u, u3_noun pox, u3_noun fav)
{
if ( c3n == u3du(fav) ) {
u3z(pox); u3z(fav); return c3n;
@ -349,7 +350,7 @@ _reck_kick_norm(u3_noun pox, u3_noun fav)
case c3__exit:
{
uL(fprintf(uH, "<<<goodbye>>>\n"));
u3_lo_bail();
u3_pier_exit();
u3z(pox); u3z(fav); return c3y;
} break;
@ -361,10 +362,10 @@ _reck_kick_norm(u3_noun pox, u3_noun fav)
/* u3_reck_kick(): handle effect.
*/
void
u3_reck_kick(u3_noun ovo)
u3_reck_kick(u3_pier* pir_u, u3_noun ovo)
{
if ( (c3n == _reck_kick_spec(u3k(u3h(ovo)), u3k(u3t(ovo)))) &&
(c3n == _reck_kick_norm(u3k(u3h(ovo)), u3k(u3t(ovo)))) )
if ( (c3n == _reck_kick_spec(pir_u, u3k(u3h(ovo)), u3k(u3t(ovo)))) &&
(c3n == _reck_kick_norm(pir_u, u3k(u3h(ovo)), u3k(u3t(ovo)))) )
{
#if 0
if ( (c3__warn != u3h(u3t(ovo))) &&
@ -379,8 +380,9 @@ u3_reck_kick(u3_noun ovo)
(c3__init == u3h(u3t(ovo))) )
#endif
{
u3v_plan(u3nt(u3_blip, c3__term, u3_nul),
u3nc(c3__flog, u3k(u3t(ovo))));
u3_pier_work(pir_u,
u3nt(u3_blip, c3__term, u3_nul),
u3nc(c3__flog, u3k(u3t(ovo))));
}
else {
u3_noun tox = u3do("spat", u3k(u3h(ovo)));

405
vere/serf.c Normal file
View File

@ -0,0 +1,405 @@
/* vere/serf.c
**
** the main loop of a worker process.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <setjmp.h>
#include <gmp.h>
#include <sigsegv.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <uv.h>
#include <errno.h>
#include <curses.h>
#include <termios.h>
#include <term.h>
#include "all.h"
#include <vere/vere.h>
typedef struct _u3_serf {
c3_d evt_d; // last event processed
c3_l mug_l; // hash of state
c3_d key_d[4]; // disk key
u3_moat inn_u; // message input
u3_mojo out_u; // message output
} u3_serf;
static u3_serf u3V;
/* serf-lord protocol:
**
** ++ plea :: from serf to lord
** $% $: $play :: send events
** p/@ :: first number expected
** q/@ :: mug of state (or 0 to boot)
** == ::
** $: $done :: event executed unchanged
** p/@ :: number of this event
** q/@ :: mug of state (or 0)
** r/(list ovum) :: actions
** == ::
** $: $work :: replace and retry
** p/@ :: event number
** q/@ :: mug of state (or 0)
** r/(pair date ovum) :: event
** == == ::
**
** ++ writ :: from lord to serf
** $% $: $exit :: snapshot, then exit
** p/@ :: exit code
** == ::
** $: $save :: save snapshot to disk
** p/@ :: number of old snaps to save
** == ::
** $: $work :: execute event
** p/@ :: event number
** q/@ :: mug of state (or 0)
** r/(pair date ovum) :: event
** == == ::
*/
/* _serf_fail(): failure stub.
*/
static void
_serf_fail(void* vod_p, const c3_c* wut_c)
{
// fprintf(stderr, "serf: fail: %s\r\n", wut_c);
exit(1);
}
/* _serf_send(): send result back to lord.
*/
static void
_serf_send(u3_noun job)
{
u3_newt_write(&u3V.out_u, u3ke_jam(job), 0);
}
/* _serf_send_replace(): send replacement job back to lord.
*/
static void
_serf_send_replace(u3_noun ovo)
{
_serf_send(u3nq(c3__work,
u3i_chubs(1, &u3V.evt_d),
u3V.mug_l,
u3nc(u3k(u3A->now), ovo)));
}
/* _serf_send_complete(): report completion.
*/
static void
_serf_send_complete(u3_noun vir)
{
_serf_send(u3nq(c3__done,
u3i_chubs(1, &u3V.evt_d),
u3r_mug(u3A->roc),
vir));
}
/* _serf_lame(): event failed, replace with error event.
*/
static void
_serf_lame(u3_noun ovo, u3_noun why, u3_noun tan)
{
/* XX: the next crud will contain the original event.
*/
u3z(ovo);
_serf_send_replace(u3nt(c3__crud, why, tan));
}
/* _serf_sure(): event succeeded, report completion.
*/
static void
_serf_sure(u3_noun ovo, u3_noun vir, u3_noun cor)
{
u3z(ovo);
u3z(u3A->roc);
u3A->roc = cor;
_serf_send_complete(vir);
}
/* _serf_poke_live(): apply event.
*/
static void
_serf_poke_live(c3_d evt_d, // event number
c3_l mug_l, // mug of state
u3_noun job) // event date
{
u3_noun now = u3k(u3h(job));
u3_noun ovo = u3k(u3t(job));
// fprintf(stderr, "serf: (%lld)| live\r\n", evt_d);
c3_assert(evt_d == u3V.evt_d + 1ULL);
u3V.evt_d = evt_d;
u3z(job);
{
u3_noun gon;
if ( mug_l ) {
c3_assert(u3r_mug(u3A->roc) == mug_l);
}
u3z(u3A->now);
u3A->now = now;
u3A->ent_d = evt_d;
#ifdef GHETTO
struct timeval b4, f2, d0;
gettimeofday(&b4, 0);
#endif
gon = u3m_soft(0, u3v_poke, u3k(ovo));
#ifdef GHETTO
c3_w ms_w;
c3_w clr_w;
gettimeofday(&f2, 0);
timersub(&f2, &b4, &d0);
ms_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000);
clr_w = ms_w > 1000 ? 1 : ms_w < 100 ? 2 : 3; // red, green, yellow
if (c3__belt != u3h(u3t(ovo)) || clr_w != 2) {
uL(fprintf(uH, "\x1b[3%dm%%%s %4d.%02dms\x1b[0m\n",
clr_w, txt_c, ms_w, (int) (d0.tv_usec % 1000) / 10));
}
free(txt_c);
#endif
if ( u3_blip != u3h(gon) ) {
u3_noun why = u3k(u3h(gon));
u3_noun tan = u3k(u3t(gon));
u3z(gon);
_serf_lame(ovo, why, tan);
}
else {
u3_noun vir = u3k(u3h(u3t(gon)));
u3_noun cor = u3k(u3t(u3t(gon)));
_serf_sure(ovo, vir, cor);
}
}
}
/* _serf_boot_fire(): execute boot sequence.
*/
static u3_noun
_serf_boot_fire(u3_noun eve)
{
u3_noun cor = u3n_nock_on(eve, u3nt(2, u3nc(0, 3), u3nc(0, 2)));
u3_noun pro;
pro = u3k(u3r_at(7, cor));
u3z(cor);
return pro;
}
/* _serf_poke_boot(): apply initial-stage event.
*/
static void
_serf_poke_boot(c3_d evt_d,
c3_l mug_l,
u3_noun job)
{
u3A->roe = u3nc(job, u3A->roe);
c3_assert(evt_d == u3V.evt_d + 1ULL);
u3V.evt_d = evt_d;
fprintf(stderr, "serf: (%lld)| boot\r\n", evt_d);
if ( evt_d == 5 ) {
u3_noun eve = u3kb_flop(u3A->roe);
u3_noun pru;
u3A->roe = 0;
fprintf(stderr, "serf: (5)| pill: %x\r\n", u3r_mug(eve));
pru = u3m_soft(0, _serf_boot_fire, eve);
if ( u3h(pru) != 0 ) {
fprintf(stderr, "boot failed\r\n");
exit(1);
}
fprintf(stderr, "serf: (5)| core: %x\r\n", u3r_mug(u3t(pru)));
u3A->ken = 0;
u3A->roc = u3k(u3t(pru));
u3z(pru);
}
_serf_send(u3nq(c3__done,
u3i_chubs(1, &evt_d),
0,
u3_nul));
}
/* _serf_poke_work(): apply event.
*/
static void
_serf_poke_work(c3_d evt_d, // event number
c3_l mug_l, // mug of state
u3_noun job) // full event
{
if ( evt_d < 6 ) {
_serf_poke_boot(evt_d, mug_l, job);
}
else {
_serf_poke_live(evt_d, mug_l, job);
}
}
/* _serf_poke_exit(): exit on command.
*/
static void
_serf_poke_exit(c3_w cod_w) // exit code
{
exit(cod_w);
}
/* _serf_poke():
*/
void
_serf_poke(void* vod_p, u3_noun mat)
{
u3_noun jar = u3ke_cue(mat);
if ( c3y != u3du(jar) ) {
goto error;
}
else {
u3_noun p_jar, q_jar, r_jar;
switch ( u3h(jar) ) {
case c3__work: {
if ( (c3n == u3r_qual(jar, 0, &p_jar, &q_jar, &r_jar)) ||
(c3n == u3ud(p_jar)) ||
(u3r_met(6, p_jar) != 1) ||
(c3n == u3ud(q_jar)) ||
(u3r_met(5, q_jar) > 1) )
{
goto error;
}
_serf_poke_work(u3r_chub(0, p_jar),
u3r_word(0, q_jar),
u3k(r_jar));
break;
}
case c3__exit: {
if ( (c3n == u3r_cell(jar, 0, &p_jar)) ||
(c3n == u3ud(p_jar)) ||
(u3r_met(3, p_jar) > 1) )
{
goto error;
}
_serf_poke_exit(u3k(p_jar));
break;
}
case c3__save: {
if ( (c3n == u3r_cell(jar, 0, &p_jar)) ||
(c3n == u3ud(p_jar)) ) {
goto error;
}
fprintf(stderr, "serf: save\r\n");
u3e_save();
break;
}
default: {
goto error;
}
}
return;
}
error: {
_serf_fail(0, "bad jar");
}
u3z(jar);
}
/* u3_serf_boot(): send startup message to manager.
*/
void
u3_serf_boot(void)
{
c3_d nex_d = u3A->ent_d + 1ULL;
fprintf(stderr, "serf: play %lld\r\n", nex_d);
_serf_send(u3nt(c3__play, u3i_chubs(1, &nex_d), 0));
}
/* u3_serf_main(): main() when run as urbit-client
*/
c3_i
u3_serf_main(c3_i argc, c3_c* argv[])
{
uv_loop_t* lup_u = uv_default_loop();
c3_c* dir_c = argv[1];
c3_c* key_c = argv[2];
c3_assert(3 == argc);
/* load passkey
*/
{
sscanf(key_c, "%llx:%llx:%llx:%llx", &u3V.key_d[0],
&u3V.key_d[1],
&u3V.key_d[2],
&u3V.key_d[3]);
}
/* boot image
*/
{
u3V.evt_d = u3m_boot_new(dir_c);
}
/* configure pipe to lord process
*/
{
c3_i err_i;
err_i = uv_pipe_init(lup_u, &u3V.inn_u.pyp_u, 0);
c3_assert(!err_i);
uv_pipe_open(&u3V.inn_u.pyp_u, 0);
err_i = uv_pipe_init(lup_u, &u3V.out_u.pyp_u, 0);
c3_assert(!err_i);
uv_pipe_open(&u3V.out_u.pyp_u, 1);
}
/* set up writing
*/
u3V.out_u.bal_f = _serf_fail;
/* start reading
*/
u3V.inn_u.vod_p = &u3V;
u3V.inn_u.pok_f = _serf_poke;
u3V.inn_u.bal_f = _serf_fail;
u3_newt_read(&u3V.inn_u);
/* send start request
*/
u3_serf_boot();
/* enter loop
*/
uv_run(lup_u, UV_RUN_DEFAULT);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -85,7 +85,7 @@ _term_close_cb(uv_handle_t* han_t)
{
u3_noun tid = u3dc("scot", c3__ud, tty_u->tid_l);
u3_noun pax = u3nq(u3_blip, c3__term, tid, u3_nul);
u3v_plan(u3k(pax), u3nc(c3__hook, u3_nul));
u3_pier_plan(u3k(pax), u3nc(c3__hook, u3_nul));
u3z(pax);
}
free(tty_u);
@ -338,9 +338,9 @@ _term_listen_cb(uv_stream_t *wax_u, int sas_i)
{
u3_noun tid = u3dc("scot", c3__ud, tty_u->tid_l);
u3_noun pax = u3nq(u3_blip, c3__term, tid, u3_nul);
// u3v_plan(u3k(pax), u3nq(c3__flow, c3__seat, c3__dojo, u3_nul));
u3v_plan(u3k(pax), u3nc(c3__blew, u3nc(80, 25)));
u3v_plan(u3k(pax), u3nc(c3__hail, u3_nul));
// u3_pier_plan(u3k(pax), u3nq(c3__flow, c3__seat, c3__dojo, u3_nul));
u3_pier_plan(u3k(pax), u3nc(c3__blew, u3nc(80, 25)));
u3_pier_plan(u3k(pax), u3nc(c3__hail, u3_nul));
u3z(pax);
}
@ -721,7 +721,7 @@ _term_io_belt(u3_utty* uty_u, u3_noun blb)
u3_noun tid = u3dc("scot", c3__ud, uty_u->tid_l);
u3_noun pax = u3nq(u3_blip, c3__term, tid, u3_nul);
u3v_plan(pax, u3nc(c3__belt, blb));
u3_pier_plan(pax, u3nc(c3__belt, blb));
}
/* _tel_event(): telnet sucker
@ -793,7 +793,7 @@ _tel_opt(_te_nvt* nvt, telnet_byte opt, _to_evt* evt)
tid = u3dc("scot", c3__ud, tel_u->uty_t.tid_l);
pax = u3nq(u3_blip, c3__term, tid, u3_nul);
blu = u3nc(col_s, row_s);
u3v_plan(pax, u3nc(c3__blew, blu));
u3_pier_plan(pax, u3nc(c3__blew, blu));
break;
}
}
@ -904,7 +904,6 @@ _term_read_tn_cb(uv_stream_t* tcp_u,
{
u3_utel* pty_u = (u3_utel*)(void*) tcp_u;
u3_lo_open();
{
if ( siz_i == UV_EOF ) {
// nothing
@ -920,7 +919,6 @@ _term_read_tn_cb(uv_stream_t* tcp_u,
err:
free(buf_u->base);
}
u3_lo_shut(c3y);
}
/* _term_suck(): process a chunk of input
@ -941,7 +939,6 @@ _term_read_tn_cb(uv_stream_t* tcp_u,
static inline void
_term_suck(u3_utty* uty_u, const c3_y* buf, ssize_t siz_i)
{
u3_lo_open();
{
if ( siz_i == UV_EOF ) {
// nothing
@ -956,7 +953,6 @@ _term_suck(u3_utty* uty_u, const c3_y* buf, ssize_t siz_i)
}
}
}
u3_lo_shut(c3y);
}
/* _term_read_cb(): server read callback.
@ -1218,7 +1214,7 @@ u3_term_ef_winc(void)
{
u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
u3v_plan(pax, u3nc(c3__blew, u3_term_get_blew(1)));
u3_pier_plan(pax, u3nc(c3__blew, u3_term_get_blew(1)));
}
/* u3_term_ef_ctlc(): send ^C on console.
@ -1228,24 +1224,7 @@ u3_term_ef_ctlc(void)
{
u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
u3v_plan(pax, u3nt(c3__belt, c3__ctl, 'c'));
}
/* u3_term_ef_boil(): initial effects for loaded servers.
*/
void
u3_term_ef_boil(void)
{
{
u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
// u3v_plan(u3k(pax), u3nc(c3__init, u3k(u3h(u3A->own))));
u3v_plan(u3k(pax), u3nc(c3__harm, u3_nul));
u3v_plan(u3k(pax), u3nc(c3__blew, u3_term_get_blew(1)));
u3v_plan(u3k(pax), u3nc(c3__hail, u3_nul));
u3z(pax);
}
u3_pier_plan(pax, u3nt(c3__belt, c3__ctl, 'c'));
}
/* u3_term_ef_verb(): initial effects for verbose events
@ -1255,7 +1234,7 @@ u3_term_ef_verb(void)
{
u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
u3v_plan(pax, u3nc(c3__verb, u3_nul));
u3_pier_plan(pax, u3nc(c3__verb, u3_nul));
}
/* u3_term_ef_ticket(): initial effects for new ticket.
@ -1281,20 +1260,19 @@ u3_term_ef_ticket(c3_c* who_c, c3_c* tic_c)
}
else { tic = u3k(u3t(tuc)); u3z(tuc); }
u3v_plan(pax, u3nt(c3__tick, who, tic));
u3_pier_plan(pax, u3nt(c3__tick, who, tic));
}
/* u3_term_ef_bake(): initial effects for new terminal.
*/
void
u3_term_ef_bake(u3_noun fav)
u3_term_ef_bake(void)
{
u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
u3v_plan(u3k(pax), u3nc(c3__boot, fav));
// u3v_plan(u3k(pax), u3nq(c3__flow, c3__seat, c3__dojo, u3_nul));
u3v_plan(u3k(pax), u3nc(c3__blew, u3_term_get_blew(1)));
u3v_plan(u3k(pax), u3nc(c3__hail, u3_nul));
// u3_pier_plan(u3k(pax), u3nq(c3__flow, c3__seat, c3__dojo, u3_nul));
u3_pier_plan(u3k(pax), u3nc(c3__blew, u3_term_get_blew(1)));
u3_pier_plan(u3k(pax), u3nc(c3__hail, u3_nul));
u3z(pax);
}

View File

@ -534,12 +534,10 @@ _delete_mount_point_out:
static void
_unix_time_cb(uv_timer_t* tim_u)
{
u3_lo_open();
{
u3_Host.unx_u.alm = c3n;
u3_Host.unx_u.dyr = c3y;
}
u3_lo_shut(c3y);
}
/* _unix_fs_event_cb(): filesystem event callback.
@ -962,7 +960,7 @@ _unix_update_mount(u3_umon* mon_u, u3_noun all)
can = u3kb_weld(_unix_update_node(nod_u), can);
}
u3v_plan(u3nq(u3_blip, c3__sync, u3k(u3A->sen), u3_nul),
u3_pier_plan(u3nq(u3_blip, c3__sync, u3k(u3A->sen), u3_nul),
u3nq(c3__into, u3i_string(mon_u->nam_c), all, can));
}
}
@ -1088,7 +1086,6 @@ _unix_initial_update_dir(c3_c* pax_c)
static void
_unix_sign_cb(uv_signal_t* sil_u, c3_i num_i)
{
u3_lo_open();
{
switch ( num_i ) {
default: fprintf(stderr, "\r\nmysterious signal %d\r\n", num_i); break;
@ -1103,7 +1100,6 @@ _unix_sign_cb(uv_signal_t* sil_u, c3_i num_i)
case SIGWINCH: u3_term_ef_winc(); break;
}
}
u3_lo_shut(c3y);
}
/* _unix_ef_sync(): check for files to sync.
@ -1111,8 +1107,6 @@ _unix_sign_cb(uv_signal_t* sil_u, c3_i num_i)
static void
_unix_ef_sync(uv_check_t* han_u)
{
u3_lo_open();
u3_lo_shut(c3y);
}
/* _unix_sync_file(): sync file to unix
@ -1335,11 +1329,6 @@ u3_unix_io_init(void)
uv_timer_init(u3L, &unx_u->tim_u);
unx_u->alm = c3n;
unx_u->dyr = c3n;
if ( c3n == u3_Host.ops_u.nuu ) {
u3v_plan(u3nt(u3_blip, c3__boat, u3_nul),
u3nc(c3__boat, u3_nul));
}
}
/* u3_unix_acquire(): acquire a lockfile, killing anything that holds it.
@ -1432,6 +1421,16 @@ u3_unix_ef_hold(void)
}
}
/* u3_unix_ef_bake(): initial effects for new process.
*/
void
u3_unix_ef_bake(void)
{
u3_pier_plan(u3nt(u3_blip, c3__boat, u3_nul),
u3nc(c3__boat, u3_nul));
}
/* u3_unix_ef_move()
*/
void
@ -1445,15 +1444,19 @@ u3_unix_ef_move(void)
}
}
/* u3_unix_ef_boot(): boot actions
*/
void
u3_unix_ef_initial_into()
u3_unix_ef_boot(void)
{
u3_noun can = _unix_initial_update_dir(u3_Host.ops_u.arv_c);
if ( u3_Host.ops_u.imp_c ) {
u3_noun can = _unix_initial_update_dir(u3_Host.ops_u.arv_c);
u3v_plan(u3nq(u3_blip, c3__sync, u3k(u3A->sen), u3_nul),
u3nq(c3__into, u3_nul, c3y, can));
u3_pier_plan(u3nq(u3_blip, c3__sync, u3k(u3A->sen), u3_nul),
u3nq(c3__into, u3_nul, c3y, can));
}
}
/* u3_unix_ef_look(): update the root.
*/
void