mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-09 22:54:53 +03:00
New event system; activate with -j.
This commit is contained in:
parent
4126bd39b1
commit
f30fc4b218
13
Makefile
13
Makefile
@ -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)
|
||||
@ -355,6 +356,7 @@ V_OFILES=\
|
||||
vere/cttp.o \
|
||||
vere/http.o \
|
||||
vere/loop.o \
|
||||
vere/newt.o \
|
||||
vere/raft.o \
|
||||
vere/reck.o \
|
||||
vere/sist.o \
|
||||
@ -362,7 +364,11 @@ V_OFILES=\
|
||||
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
|
||||
@ -412,7 +418,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."
|
||||
@ -421,6 +427,9 @@ all: urbit
|
||||
.make.conf:
|
||||
@echo "# Set custom configuration here, please!" > ".make.conf"
|
||||
|
||||
links: urbit
|
||||
$(LN) $(BIN)/urbit $(BIN)/urbit-worker
|
||||
|
||||
urbit: $(BIN)/urbit
|
||||
|
||||
$(LIBUV_MAKEFILE) $(LIBUV_MAKEFILE2):
|
||||
|
@ -90,3 +90,5 @@
|
||||
c3_assert(!"memory lost"); \
|
||||
} \
|
||||
rut;})
|
||||
#define c3_free(s) free(s)
|
||||
#define c3_realloc(s, l) realloc(s, l)
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
**
|
||||
|
@ -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*
|
||||
|
@ -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
|
||||
|
@ -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,17 +609,19 @@
|
||||
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 mad; // -j, run manager
|
||||
c3_o fog; // -X, skip last event
|
||||
c3_o fak; // -F, fake carrier
|
||||
c3_o loh; // -L, local-only networking
|
||||
@ -555,7 +629,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;
|
||||
@ -581,15 +655,100 @@
|
||||
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_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,6 +885,76 @@
|
||||
u3_noun
|
||||
u3_ve_zeus(u3_noun hap);
|
||||
|
||||
/** Filesystem (async)
|
||||
**/
|
||||
/* 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_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_ve_tank(): print a tank at `tab`.
|
||||
@ -1068,7 +1297,6 @@
|
||||
void
|
||||
u3_raft_work(void);
|
||||
|
||||
|
||||
/** Disk persistence.
|
||||
**/
|
||||
/* u3_sist_boot(): restore or create pier from disk.
|
||||
@ -1139,6 +1367,7 @@
|
||||
void
|
||||
u3_sist_rand(c3_w* rad_w);
|
||||
|
||||
|
||||
/** New timer system.
|
||||
**/
|
||||
/* u3_behn_io_init(): initialize time timer.
|
||||
@ -1179,3 +1408,59 @@
|
||||
*/
|
||||
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_plan(): submit event.
|
||||
*/
|
||||
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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
126
noun/manage.c
126
noun/manage.c
@ -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
|
||||
@ -1573,10 +1617,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.
|
||||
*/
|
||||
@ -1592,7 +1636,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.
|
||||
*/
|
||||
@ -1611,10 +1655,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;
|
||||
}
|
||||
|
@ -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
|
||||
|
12
noun/trace.c
12
noun/trace.c
@ -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,9 +90,9 @@ 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)));
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -187,7 +187,7 @@ u3_ames_ef_bake(void)
|
||||
{
|
||||
u3_noun pax = u3nq(u3_blip, c3__newt, u3k(u3A->sen), u3_nul);
|
||||
|
||||
u3v_plan(pax, u3nc(c3__barn, u3_nul));
|
||||
u3_pier_plan(pax, u3nc(c3__barn, u3_nul));
|
||||
}
|
||||
|
||||
/* u3_ames_ef_send(): send packet to network (v4).
|
||||
@ -259,7 +259,7 @@ _ames_time_cb(uv_timer_t* tim_uo)
|
||||
|
||||
sam_u->law_w = time(0);
|
||||
{
|
||||
u3v_plan
|
||||
u3_pier_plan
|
||||
(u3nt(u3_blip, c3__ames, u3_nul),
|
||||
u3nc(c3__wake, u3_nul));
|
||||
}
|
||||
@ -293,7 +293,7 @@ _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
|
||||
u3_pier_plan
|
||||
(u3nt(u3_blip, c3__ames, u3_nul),
|
||||
u3nt(c3__hear,
|
||||
u3nq(c3__if, u3k(u3A->now), por_s, u3i_words(1, &pip_w)),
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ _behn_time_cb(uv_timer_t* tim_u)
|
||||
|
||||
u3_lo_open();
|
||||
{
|
||||
u3v_plan
|
||||
u3_pier_plan
|
||||
(u3nt(u3_blip, c3__behn, u3_nul),
|
||||
u3nc(c3__wake, u3_nul));
|
||||
}
|
||||
|
@ -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.
|
||||
@ -1638,6 +1638,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 +1677,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
629
vere/foil.c
Normal 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
694
vere/fuse.c
Normal 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));
|
||||
|
||||
}
|
@ -892,7 +892,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)),
|
||||
@ -909,7 +909,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.
|
||||
@ -1000,7 +1000,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
38920
vere/ivory.c
Normal file
File diff suppressed because it is too large
Load Diff
26
vere/loop.c
26
vere/loop.c
@ -348,6 +348,7 @@ _lo_wall(u3_noun wol)
|
||||
FILE* fil_u = u3_term_io_hija();
|
||||
u3_noun wal = wol;
|
||||
|
||||
fil_u = stderr; // XX
|
||||
while ( u3_nul != wal ) {
|
||||
_lo_tape(fil_u, u3k(u3h(wal)));
|
||||
|
||||
@ -386,6 +387,7 @@ u3_lo_punt(c3_l tab_l, u3_noun tac)
|
||||
if ( c3__leaf == u3h(act) ) {
|
||||
FILE* fil_u = u3_term_io_hija();
|
||||
|
||||
fil_u = stderr; // XX
|
||||
_lo_tape(fil_u, u3k(u3t(act)));
|
||||
putc(13, fil_u);
|
||||
putc(10, fil_u);
|
||||
@ -485,6 +487,8 @@ u3_lo_shut(c3_o inn)
|
||||
// clean shutdown
|
||||
//
|
||||
if ( c3n == u3_Host.liv ) {
|
||||
fprintf(stderr, "loop: shut: exit\r\n");
|
||||
|
||||
// direct save and die
|
||||
//
|
||||
// u3_lo_grab("lo_exit", u3_none);
|
||||
@ -493,8 +497,13 @@ u3_lo_shut(c3_o inn)
|
||||
u3t_damp();
|
||||
u3_lo_exit();
|
||||
|
||||
// save a checkpoint before exiting
|
||||
u3e_save();
|
||||
if ( _(u3_Host.ops_u.mad) ) {
|
||||
u3_pier_exit();
|
||||
}
|
||||
else {
|
||||
// save a checkpoint before exiting
|
||||
u3e_save();
|
||||
}
|
||||
exit(u3_Host.xit_i);
|
||||
}
|
||||
else {
|
||||
@ -651,16 +660,18 @@ _lo_slow()
|
||||
void
|
||||
u3_lo_loop()
|
||||
{
|
||||
uv_loop_t* lup_u = uv_default_loop();
|
||||
|
||||
u3_Host.lup_u = lup_u;
|
||||
if ( !u3_Host.lup_u ) {
|
||||
u3_Host.lup_u = uv_default_loop();
|
||||
}
|
||||
|
||||
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.mad) ) {
|
||||
u3_raft_init();
|
||||
}
|
||||
|
||||
if ( _(u3_Host.ops_u.tex) ) {
|
||||
u3t_boff();
|
||||
@ -691,7 +702,7 @@ u3_lo_lead(void)
|
||||
_lo_talk();
|
||||
{
|
||||
u3_unix_ef_look(c3n);
|
||||
u3v_plan(u3nt(u3_blip, c3__ames, u3_nul),
|
||||
u3_pier_plan(u3nt(u3_blip, c3__ames, u3_nul),
|
||||
u3nc(c3__kick, u3k(u3A->now)));
|
||||
}
|
||||
_lo_poll();
|
||||
@ -706,6 +717,7 @@ u3_lo_lead(void)
|
||||
if ( u3_Host.ops_u.who_c ) {
|
||||
u3_term_ef_ticket(u3_Host.ops_u.who_c, u3_Host.ops_u.tic_c);
|
||||
}
|
||||
} else {
|
||||
u3_term_ef_boil(1);
|
||||
}
|
||||
|
||||
|
87
vere/main.c
87
vere/main.c
@ -1,5 +1,4 @@
|
||||
/* v/main.c
|
||||
**
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -75,6 +74,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
u3_Host.ops_u.tex = c3n;
|
||||
u3_Host.ops_u.pro = c3n;
|
||||
u3_Host.ops_u.dry = c3n;
|
||||
u3_Host.ops_u.mad = c3n;
|
||||
u3_Host.ops_u.veb = c3n;
|
||||
u3_Host.ops_u.qui = c3n;
|
||||
u3_Host.ops_u.nuu = c3n;
|
||||
@ -82,7 +82,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
u3_Host.ops_u.rep = c3n;
|
||||
u3_Host.ops_u.kno_w = DefaultKernel;
|
||||
|
||||
while ( (ch_i=getopt(argc, argv,"G:B:A:I:w:t:f:k:l:n:p:r:LabcdgmqvxFMPDXR")) != -1 ) {
|
||||
while ( (ch_i=getopt(argc, argv,"G:B:A:I:w:t:f:k:l:n:p:r:LabcdgjmqvxFMPDXR")) != -1 ) {
|
||||
switch ( ch_i ) {
|
||||
case 'M': {
|
||||
u3_Host.ops_u.mem = c3y;
|
||||
@ -113,6 +113,10 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
u3_Host.ops_u.tic_c = _main_presig(optarg);
|
||||
break;
|
||||
}
|
||||
case 'j': {
|
||||
u3_Host.ops_u.mad = c3y;
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
u3_Host.ops_u.tex = c3y;
|
||||
break;
|
||||
@ -441,6 +445,20 @@ 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,18 +471,21 @@ 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 ( c3n == u3_Host.ops_u.mad ) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,33 +567,29 @@ 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 ( _(u3_Host.ops_u.mad) ) {
|
||||
u3_pier_boot(u3_Host.dir_c, u3_Host.ops_u.pil_c);
|
||||
}
|
||||
else {
|
||||
u3m_boot(u3_Host.ops_u.nuu,
|
||||
u3_Host.dir_c,
|
||||
u3_Host.ops_u.pil_c);
|
||||
|
||||
/* Start Arvo.
|
||||
*/
|
||||
#if 1
|
||||
{
|
||||
struct timeval tim_tv;
|
||||
u3_noun now;
|
||||
{
|
||||
struct timeval tim_tv;
|
||||
u3_noun now;
|
||||
|
||||
gettimeofday(&tim_tv, 0);
|
||||
now = u3_time_in_tv(&tim_tv);
|
||||
gettimeofday(&tim_tv, 0);
|
||||
now = u3_time_in_tv(&tim_tv);
|
||||
|
||||
u3v_start(now);
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// u3e_grab("main", u3_none);
|
||||
|
335
vere/newt.c
Normal file
335
vere/newt.c
Normal 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));
|
||||
}
|
||||
}
|
1463
vere/pier.c
Normal file
1463
vere/pier.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -379,7 +379,7 @@ u3_reck_kick(u3_noun ovo)
|
||||
(c3__init == u3h(u3t(ovo))) )
|
||||
#endif
|
||||
{
|
||||
u3v_plan(u3nt(u3_blip, c3__term, u3_nul),
|
||||
u3_pier_plan(u3nt(u3_blip, c3__term, u3_nul),
|
||||
u3nc(c3__flog, u3k(u3t(ovo))));
|
||||
}
|
||||
else {
|
||||
|
408
vere/serf.c
Normal file
408
vere/serf.c
Normal file
@ -0,0 +1,408 @@
|
||||
/* 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) ) {
|
||||
fprintf(stderr, "1\r\n");
|
||||
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) )
|
||||
{
|
||||
fprintf(stderr, "2\r\n");
|
||||
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: {
|
||||
fprintf(stderr, "3\r\n");
|
||||
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;
|
||||
}
|
36
vere/term.c
36
vere/term.c
@ -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;
|
||||
}
|
||||
}
|
||||
@ -1218,7 +1218,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,7 +1228,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_pier_plan(pax, u3nt(c3__belt, c3__ctl, 'c'));
|
||||
}
|
||||
|
||||
/* u3_term_ef_boil(): initial effects for loaded servers.
|
||||
@ -1239,10 +1239,10 @@ 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));
|
||||
// u3_pier_plan(u3k(pax), u3nc(c3__init, u3k(u3h(u3A->own))));
|
||||
u3_pier_plan(u3k(pax), u3nc(c3__harm, 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);
|
||||
}
|
||||
@ -1255,7 +1255,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,7 +1281,7 @@ 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.
|
||||
@ -1291,10 +1291,10 @@ u3_term_ef_bake(u3_noun fav)
|
||||
{
|
||||
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), u3nc(c3__boot, fav));
|
||||
// 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);
|
||||
}
|
||||
|
@ -962,7 +962,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));
|
||||
}
|
||||
}
|
||||
@ -1337,7 +1337,7 @@ u3_unix_io_init(void)
|
||||
unx_u->dyr = c3n;
|
||||
|
||||
if ( c3n == u3_Host.ops_u.nuu ) {
|
||||
u3v_plan(u3nt(u3_blip, c3__boat, u3_nul),
|
||||
u3_pier_plan(u3nt(u3_blip, c3__boat, u3_nul),
|
||||
u3nc(c3__boat, u3_nul));
|
||||
}
|
||||
}
|
||||
@ -1450,7 +1450,7 @@ u3_unix_ef_initial_into()
|
||||
{
|
||||
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),
|
||||
u3_pier_plan(u3nq(u3_blip, c3__sync, u3k(u3A->sen), u3_nul),
|
||||
u3nq(c3__into, u3_nul, c3y, can));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user