mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-24 10:33:22 +03:00
commit
21f7023198
9
.github/workflows/tarballs.yml
vendored
9
.github/workflows/tarballs.yml
vendored
@ -23,12 +23,13 @@ jobs:
|
||||
name: ${{ secrets.CACHIX_NAME }}
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
|
||||
- uses: google-github-actions/setup-gcloud@v0.2.0
|
||||
- uses: google-github-actions/auth@v1
|
||||
with:
|
||||
credentials_json: ${{ secrets.GCP_CREDENTIALS }}
|
||||
|
||||
- uses: google-github-actions/setup-gcloud@v1
|
||||
with:
|
||||
version: '290.0.1'
|
||||
service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}
|
||||
project_id: ${{ secrets.GCS_PROJECT }}
|
||||
export_default_credentials: true
|
||||
|
||||
- run: nix-build -A tarball --arg enableStatic true
|
||||
|
||||
|
12
.github/workflows/vere.yml
vendored
12
.github/workflows/vere.yml
vendored
@ -125,13 +125,14 @@ jobs:
|
||||
echo -n "$version" > ./version-string
|
||||
|
||||
- name: upload version string artifact
|
||||
if: matrix.type == 'linux'
|
||||
if: inputs.upload && matrix.type == 'linux'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: version-string
|
||||
path: version-string
|
||||
|
||||
- uses: google-github-actions/auth@v1
|
||||
if: inputs.upload
|
||||
with:
|
||||
credentials_json: ${{ secrets.GCP_CREDENTIALS }}
|
||||
|
||||
@ -244,12 +245,13 @@ jobs:
|
||||
needs: [urbit, mingw]
|
||||
if: inputs.upload
|
||||
steps:
|
||||
- uses: google-github-actions/setup-gcloud@v0.2.0
|
||||
- uses: google-github-actions/auth@v1
|
||||
with:
|
||||
credentials_json: ${{ secrets.GCP_CREDENTIALS }}
|
||||
|
||||
- uses: google-github-actions/setup-gcloud@v1
|
||||
with:
|
||||
version: '290.0.1'
|
||||
service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}
|
||||
project_id: ${{ secrets.GCS_PROJECT }}
|
||||
export_default_credentials: true
|
||||
|
||||
- name: download version-string
|
||||
uses: actions/download-artifact@v3
|
||||
|
@ -2,6 +2,7 @@ include config.mk
|
||||
compat_mks := $(foreach dir,$(compat),$(wildcard compat/$(dir)/*.mk))
|
||||
include $(compat_mks)
|
||||
|
||||
c = $(wildcard c/*.c)
|
||||
jets = jets/tree.c $(wildcard jets/*/*.c)
|
||||
noun = $(wildcard noun/*.c)
|
||||
ur = $(wildcard ur/*.c)
|
||||
@ -13,7 +14,7 @@ bench = $(wildcard bench/*.c)
|
||||
|
||||
compat := $(foreach dir,$(compat),$(wildcard compat/$(dir)/*.c))
|
||||
|
||||
common = $(jets) $(noun) $(ur) $(vere) $(compat)
|
||||
common = $(c) $(jets) $(noun) $(ur) $(vere) $(compat)
|
||||
headers = $(shell find include -type f)
|
||||
|
||||
common_objs = $(shell echo $(common) | sed 's/\.c/.o/g')
|
||||
|
@ -7,9 +7,7 @@
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
u3m_init(1 << 24);
|
||||
u3m_pave(c3y);
|
||||
u3e_init();
|
||||
u3m_boot_lite(1 << 24);
|
||||
}
|
||||
|
||||
/* _ames_writ_ex(): |hi packet from fake ~zod to fake ~nec
|
||||
|
96
pkg/urbit/c/defs.c
Normal file
96
pkg/urbit/c/defs.c
Normal file
@ -0,0 +1,96 @@
|
||||
/// @file defs.c
|
||||
|
||||
#include "c/defs.h"
|
||||
|
||||
/* c3_pread(): full positioned read(), up to eof, retrying errors.
|
||||
*/
|
||||
ssize_t
|
||||
c3_pread(c3_i fid_i, void* buf_v, size_t len_i, off_t off_i)
|
||||
{
|
||||
c3_w max_w = 128;
|
||||
c3_w try_w = 0;
|
||||
size_t rem_i = len_i;
|
||||
ssize_t ret_i;
|
||||
|
||||
do {
|
||||
if ( (0 > (ret_i = pread(fid_i, buf_v, rem_i, off_i)))
|
||||
&& ( (++try_w == max_w)
|
||||
|| ( (EINTR != errno)
|
||||
&& (EAGAIN != errno)
|
||||
&& (EWOULDBLOCK != errno) )))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if ( 0 == ret_i ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
buf_v = (void*)((c3_c*)buf_v + ret_i);
|
||||
rem_i -= ret_i;
|
||||
off_i += ret_i;
|
||||
}
|
||||
|
||||
}
|
||||
while ( rem_i );
|
||||
|
||||
return len_i - rem_i;
|
||||
}
|
||||
|
||||
/* c3_pwrite(): full positioned write(), retrying errors.
|
||||
*/
|
||||
ssize_t
|
||||
c3_pwrite(c3_i fid_i, const void* buf_v, size_t len_i, off_t off_i)
|
||||
{
|
||||
c3_w max_w = 128;
|
||||
c3_w try_w = 0;
|
||||
size_t rem_i = len_i;
|
||||
ssize_t ret_i;
|
||||
|
||||
do {
|
||||
if ( (0 > (ret_i = pwrite(fid_i, buf_v, rem_i, off_i)))
|
||||
&& ( (++try_w == max_w)
|
||||
|| ( (EINTR != errno)
|
||||
&& (EAGAIN != errno)
|
||||
&& (EWOULDBLOCK != errno) )))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
buf_v = (void*)((c3_c*)buf_v + ret_i);
|
||||
rem_i -= ret_i;
|
||||
off_i += ret_i;
|
||||
}
|
||||
}
|
||||
while ( rem_i );
|
||||
|
||||
return len_i;
|
||||
}
|
||||
|
||||
/* c3_write(): full write(), retrying errors.
|
||||
*/
|
||||
ssize_t
|
||||
c3_write(c3_i fid_i, const void* buf_v, size_t len_i)
|
||||
{
|
||||
c3_w max_w = 128;
|
||||
c3_w try_w = 0;
|
||||
size_t rem_i = len_i;
|
||||
ssize_t ret_i;
|
||||
|
||||
do {
|
||||
if ( (0 > (ret_i = write(fid_i, buf_v, rem_i)))
|
||||
&& ( (++try_w == max_w)
|
||||
|| ( (EINTR != errno)
|
||||
&& (EAGAIN != errno)
|
||||
&& (EWOULDBLOCK != errno) )))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
buf_v = (void*)((c3_c*)buf_v + ret_i);
|
||||
rem_i -= ret_i;
|
||||
}
|
||||
}
|
||||
while ( rem_i );
|
||||
|
||||
return len_i;
|
||||
}
|
@ -144,6 +144,63 @@ int link(const char *path1, const char *path2)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t pread(int fd, void *buf, size_t count, off_t offset)
|
||||
{
|
||||
DWORD len = 0;
|
||||
|
||||
OVERLAPPED overlapped = {0};
|
||||
|
||||
overlapped.OffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
|
||||
(DWORD)0 : (DWORD)((offset >> 32) & 0xFFFFFFFFL);
|
||||
overlapped.Offset = (sizeof(off_t) <= sizeof(DWORD)) ?
|
||||
(DWORD)offset : (DWORD)(offset & 0xFFFFFFFFL);
|
||||
|
||||
HANDLE h = (HANDLE)_get_osfhandle(fd);
|
||||
|
||||
if ( INVALID_HANDLE_VALUE == h ) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( !ReadFile(h, buf, count, &len, &overlapped) ) {
|
||||
DWORD err = GetLastError();
|
||||
|
||||
if ( ERROR_HANDLE_EOF != err ) {
|
||||
errno = err_win_to_posix(err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (ssize_t)len;
|
||||
}
|
||||
|
||||
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
|
||||
{
|
||||
DWORD len = 0;
|
||||
|
||||
OVERLAPPED overlapped = {0};
|
||||
|
||||
overlapped.OffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
|
||||
(DWORD)0 : (DWORD)((offset >> 32) & 0xFFFFFFFFL);
|
||||
overlapped.Offset = (sizeof(off_t) <= sizeof(DWORD)) ?
|
||||
(DWORD)offset : (DWORD)(offset & 0xFFFFFFFFL);
|
||||
|
||||
HANDLE h = (HANDLE)_get_osfhandle(fd);
|
||||
|
||||
if ( INVALID_HANDLE_VALUE == h ) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( !WriteFile(h, buf, count, &len, &overlapped) ) {
|
||||
errno = err_win_to_posix(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (ssize_t)len;
|
||||
}
|
||||
|
||||
|
||||
// from msys2 mingw-packages-dev patches
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#define mkdir(A, B) mkdir(A)
|
||||
|
||||
int link(const char *path1, const char *path2);
|
||||
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
|
||||
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
|
||||
char *realpath(const char *path, char *resolved_path);
|
||||
int fdatasync(int fd);
|
||||
int utimes(const char *path, const struct timeval times[2]);
|
||||
|
@ -12,7 +12,7 @@ EXCEPTION_DISPOSITION _mingw_exception_filter(
|
||||
{
|
||||
if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
|
||||
ExceptionRecord->ExceptionInformation[0] == 1 &&
|
||||
u3e_fault((void*)ExceptionRecord->ExceptionInformation[1], 1))
|
||||
u3m_fault((void*)ExceptionRecord->ExceptionInformation[1], 1))
|
||||
{
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "rsignal.h"
|
||||
#include <vere/serf.h>
|
||||
#include "vere/vere.h"
|
||||
#include "vere/mars.h"
|
||||
#include "noun/events.h"
|
||||
#if !defined(U3_OS_mingw)
|
||||
#include <sigsegv.h>
|
||||
#endif
|
||||
@ -153,6 +155,15 @@ _main_init(void)
|
||||
//
|
||||
u3_Host.ops_u.has = c3y;
|
||||
|
||||
// demand paging (ie, file-backed mapping for the loom)
|
||||
// is not yet supported on windows
|
||||
//
|
||||
#ifdef U3_OS_mingw
|
||||
u3_Host.ops_u.map = c3n;
|
||||
#else
|
||||
u3_Host.ops_u.map = c3y;
|
||||
#endif
|
||||
|
||||
u3_Host.ops_u.net = c3y;
|
||||
u3_Host.ops_u.lit = c3n;
|
||||
u3_Host.ops_u.nuu = c3n;
|
||||
@ -246,6 +257,7 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
{ "scry-format", required_argument, NULL, 'Z' },
|
||||
//
|
||||
{ "urth-loom", required_argument, NULL, 5 },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
//
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
@ -266,6 +278,10 @@ _main_getopt(c3_i argc, c3_c** argv)
|
||||
u3_Host.ops_u.lut_y = lut_w;
|
||||
break;
|
||||
}
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
break;
|
||||
}
|
||||
case 'X': {
|
||||
u3_Host.ops_u.pek_c = strdup(optarg);
|
||||
break;
|
||||
@ -630,14 +646,17 @@ _cw_usage(c3_c* bin_c)
|
||||
"utilities:\n",
|
||||
" %s cram %.*s jam state:\n",
|
||||
" %s dock %.*s copy binary:\n",
|
||||
" %s eval %.*s eval hoon:\n",
|
||||
" %s grab %.*s measure memory usage:\n",
|
||||
" %s info %.*s print pier info:\n",
|
||||
" %s meld %.*s deduplicate snapshot:\n",
|
||||
" %s pack %.*s defragment snapshot:\n",
|
||||
" %s play %.*s recompute events:\n",
|
||||
" %s prep %.*s prepare for upgrade:\n",
|
||||
" %s next %.*s request upgrade:\n",
|
||||
" %s queu %.*s<at-event> cue state:\n",
|
||||
" %s vere ARGS <output dir> download binary:\n",
|
||||
" %s vile %.*s print keyfile:\n",
|
||||
"\n run as a 'serf':\n",
|
||||
" %s serf <pier> <key> <flags> <cache-size> <at-event>"
|
||||
#ifdef U3_OS_mingw
|
||||
@ -1372,7 +1391,8 @@ _cw_cram(c3_i argc, c3_c* argv[])
|
||||
c3_w arg_w;
|
||||
|
||||
static struct option lop_u[] = {
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -1380,6 +1400,11 @@ _cw_cram(c3_i argc, c3_c* argv[])
|
||||
|
||||
while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) {
|
||||
switch ( ch_i ) {
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
} break;
|
||||
|
||||
case c3__loom: {
|
||||
c3_w lom_w;
|
||||
c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w);
|
||||
@ -1432,7 +1457,7 @@ _cw_cram(c3_i argc, c3_c* argv[])
|
||||
|
||||
// save even on failure, as we just did all the work of deduplication
|
||||
//
|
||||
u3e_save();
|
||||
u3m_save();
|
||||
u3_disk_exit(log_u);
|
||||
|
||||
if ( c3n == ret_o ) {
|
||||
@ -1447,18 +1472,26 @@ _cw_cram(c3_i argc, c3_c* argv[])
|
||||
static void
|
||||
_cw_queu(c3_i argc, c3_c* argv[])
|
||||
{
|
||||
c3_i ch_i, lid_i;
|
||||
c3_w arg_w;
|
||||
c3_i ch_i, lid_i;
|
||||
c3_w arg_w;
|
||||
c3_c* roc_c = 0;
|
||||
|
||||
static struct option lop_u[] = {
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
{ "replay-from", required_argument, NULL, 'r' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
u3_Host.dir_c = _main_pier_run(argv[0]);
|
||||
|
||||
while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) {
|
||||
while ( -1 != (ch_i=getopt_long(argc, argv, "r:", lop_u, &lid_i)) ) {
|
||||
switch ( ch_i ) {
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
} break;
|
||||
|
||||
case c3__loom: {
|
||||
c3_w lom_w;
|
||||
c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w);
|
||||
@ -1469,6 +1502,10 @@ _cw_queu(c3_i argc, c3_c* argv[])
|
||||
u3_Host.ops_u.lom_y = lom_w;
|
||||
} break;
|
||||
|
||||
case 'r': {
|
||||
roc_c = strdup(optarg);
|
||||
} break;
|
||||
|
||||
case '?': {
|
||||
fprintf(stderr, "invalid argument\r\n");
|
||||
exit(1);
|
||||
@ -1476,9 +1513,13 @@ _cw_queu(c3_i argc, c3_c* argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if ( !roc_c ) {
|
||||
fprintf(stderr, "invalid command, -r $EVENT required\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// argv[optind] is always "queu"
|
||||
//
|
||||
|
||||
if ( !u3_Host.dir_c ) {
|
||||
if ( optind + 1 < argc ) {
|
||||
u3_Host.dir_c = argv[optind + 1];
|
||||
@ -1496,11 +1537,10 @@ _cw_queu(c3_i argc, c3_c* argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
c3_c* eve_c;
|
||||
c3_d eve_d;
|
||||
c3_d eve_d;
|
||||
|
||||
if ( 1 != sscanf(eve_c, "%" PRIu64 "", &eve_d) ) {
|
||||
fprintf(stderr, "urbit: queu: invalid number '%s'\r\n", eve_c);
|
||||
if ( 1 != sscanf(roc_c, "%" PRIu64 "", &eve_d) ) {
|
||||
fprintf(stderr, "urbit: queu: invalid number '%s'\r\n", roc_c);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
@ -1519,7 +1559,7 @@ _cw_queu(c3_i argc, c3_c* argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
u3e_save();
|
||||
u3m_save();
|
||||
u3_disk_exit(log_u);
|
||||
|
||||
fprintf(stderr, "urbit: queu: rock loaded at event %" PRIu64 "\r\n", eve_d);
|
||||
@ -1536,7 +1576,8 @@ _cw_meld(c3_i argc, c3_c* argv[])
|
||||
c3_w arg_w;
|
||||
|
||||
static struct option lop_u[] = {
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -1544,6 +1585,11 @@ _cw_meld(c3_i argc, c3_c* argv[])
|
||||
|
||||
while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) {
|
||||
switch ( ch_i ) {
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
} break;
|
||||
|
||||
case c3__loom: {
|
||||
c3_w lom_w;
|
||||
c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w);
|
||||
@ -1587,11 +1633,9 @@ _cw_meld(c3_i argc, c3_c* argv[])
|
||||
u3C.wag_w |= u3o_hashless;
|
||||
u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y);
|
||||
|
||||
pre_w = u3a_open(u3R);
|
||||
u3u_meld();
|
||||
u3a_print_memory(stderr, "urbit: meld: gained", (u3a_open(u3R) - pre_w));
|
||||
u3a_print_memory(stderr, "urbit: meld: gained", u3u_meld());
|
||||
|
||||
u3e_save();
|
||||
u3m_save();
|
||||
u3_disk_exit(log_u);
|
||||
u3m_stop();
|
||||
}
|
||||
@ -1605,8 +1649,9 @@ _cw_next(c3_i argc, c3_c* argv[])
|
||||
c3_w arg_w;
|
||||
|
||||
static struct option lop_u[] = {
|
||||
{ "arch", required_argument, NULL, 'a' },
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "arch", required_argument, NULL, 'a' },
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -1618,6 +1663,11 @@ _cw_next(c3_i argc, c3_c* argv[])
|
||||
u3_Host.arc_c = strdup(optarg);
|
||||
} break;
|
||||
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
} break;
|
||||
|
||||
case c3__loom: {
|
||||
c3_w lom_w;
|
||||
c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w);
|
||||
@ -1669,7 +1719,8 @@ _cw_pack(c3_i argc, c3_c* argv[])
|
||||
c3_w arg_w;
|
||||
|
||||
static struct option lop_u[] = {
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -1677,6 +1728,11 @@ _cw_pack(c3_i argc, c3_c* argv[])
|
||||
|
||||
while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) {
|
||||
switch ( ch_i ) {
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
} break;
|
||||
|
||||
case c3__loom: {
|
||||
c3_w lom_w;
|
||||
c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w);
|
||||
@ -1719,7 +1775,161 @@ _cw_pack(c3_i argc, c3_c* argv[])
|
||||
u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y);
|
||||
u3a_print_memory(stderr, "urbit: pack: gained", u3m_pack());
|
||||
|
||||
u3e_save();
|
||||
u3m_save();
|
||||
u3_disk_exit(log_u);
|
||||
u3m_stop();
|
||||
}
|
||||
|
||||
/* _cw_play_slog(): print during replay.
|
||||
*/
|
||||
static void
|
||||
_cw_play_slog(u3_noun hod)
|
||||
{
|
||||
u3_pier_tank(0, 0, u3k(u3t(hod)));
|
||||
u3z(hod);
|
||||
}
|
||||
|
||||
/* _cw_play_exit(): exit immediately.
|
||||
*/
|
||||
static void
|
||||
_cw_play_exit(c3_i int_i)
|
||||
{
|
||||
// explicit fprintf to avoid allocation in u3l_log
|
||||
//
|
||||
fprintf(stderr, "\r\n[received keyboard stop signal, exiting]\r\n");
|
||||
raise(SIGINT);
|
||||
}
|
||||
|
||||
/* _cw_play(): replay events, but better.
|
||||
*/
|
||||
static void
|
||||
_cw_play(c3_i argc, c3_c* argv[])
|
||||
{
|
||||
c3_i ch_i, lid_i;
|
||||
c3_w arg_w;
|
||||
c3_o ful_o = c3n;
|
||||
c3_o mel_o = c3n;
|
||||
|
||||
static struct option lop_u[] = {
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "auto-meld", no_argument, NULL, 4 },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
{ "full", required_argument, NULL, 'f' },
|
||||
{ "replay-to", no_argument, NULL, 'n' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
u3_Host.dir_c = _main_pier_run(argv[0]);
|
||||
|
||||
while ( -1 != (ch_i=getopt_long(argc, argv, "fn:", lop_u, &lid_i)) ) {
|
||||
switch ( ch_i ) {
|
||||
case 4: { // auto-meld
|
||||
mel_o = c3y;
|
||||
} break;
|
||||
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
} break;
|
||||
|
||||
case c3__loom: {
|
||||
c3_w lom_w;
|
||||
c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w);
|
||||
if ( (c3n == res_o) || (lom_w < 20) ) {
|
||||
fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2);
|
||||
exit(1);
|
||||
}
|
||||
u3_Host.ops_u.lom_y = lom_w;
|
||||
} break;
|
||||
|
||||
case 'f': {
|
||||
ful_o = c3y;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n': {
|
||||
u3_Host.ops_u.til_c = strdup(optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case '?': {
|
||||
fprintf(stderr, "invalid argument\r\n");
|
||||
exit(1);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// argv[optind] is always "play"
|
||||
//
|
||||
|
||||
if ( !u3_Host.dir_c ) {
|
||||
if ( optind + 1 < argc ) {
|
||||
u3_Host.dir_c = argv[optind + 1];
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "invalid command, pier required\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
optind++;
|
||||
}
|
||||
|
||||
if ( optind + 1 != argc ) {
|
||||
fprintf(stderr, "invalid command\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock
|
||||
|
||||
#if !defined(U3_OS_mingw)
|
||||
// Handle SIGTSTP as if it was SIGINT.
|
||||
//
|
||||
// Configured here using signal() so as to be immediately available.
|
||||
//
|
||||
signal(SIGTSTP, _cw_play_exit);
|
||||
#endif
|
||||
|
||||
if ( c3y == mel_o ) {
|
||||
u3C.wag_w |= u3o_auto_meld;
|
||||
}
|
||||
|
||||
u3C.wag_w |= u3o_hashless;
|
||||
|
||||
if ( c3y == ful_o ) {
|
||||
u3l_log("mars: preparing for full replay\r\n");
|
||||
u3m_init((size_t)1 << u3_Host.ops_u.lom_y);
|
||||
u3e_live(u3m_pier(u3_Host.dir_c));
|
||||
u3e_yolo();
|
||||
u3m_pave(c3y);
|
||||
u3j_boot(c3y);
|
||||
u3A->eve_d = 0;
|
||||
}
|
||||
else {
|
||||
u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y);
|
||||
}
|
||||
|
||||
u3C.slog_f = _cw_play_slog;
|
||||
|
||||
{
|
||||
u3_mars mar_u = {
|
||||
.log_u = log_u,
|
||||
.dir_c = u3_Host.dir_c,
|
||||
.sen_d = u3A->eve_d,
|
||||
.dun_d = u3A->eve_d,
|
||||
.mug_l = u3r_mug(u3A->roc)
|
||||
};
|
||||
c3_d eve_d = 0;
|
||||
c3_c* eve_c = u3_Host.ops_u.til_c;
|
||||
|
||||
if ( u3_Host.ops_u.til_c ) {
|
||||
if ( 1 != sscanf(eve_c, "%" PRIu64 "", &eve_d) ) {
|
||||
fprintf(stderr, "mars: replay-to invalid: '%s'\r\n", eve_c);
|
||||
}
|
||||
}
|
||||
|
||||
u3_mars_play(&mar_u, eve_d);
|
||||
}
|
||||
|
||||
u3_disk_exit(log_u);
|
||||
u3m_stop();
|
||||
}
|
||||
@ -1733,7 +1943,8 @@ _cw_prep(c3_i argc, c3_c* argv[])
|
||||
c3_w arg_w;
|
||||
|
||||
static struct option lop_u[] = {
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -1741,6 +1952,11 @@ _cw_prep(c3_i argc, c3_c* argv[])
|
||||
|
||||
while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) {
|
||||
switch ( ch_i ) {
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
} break;
|
||||
|
||||
case c3__loom: {
|
||||
c3_w lom_w;
|
||||
c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w);
|
||||
@ -1904,7 +2120,8 @@ _cw_vile(c3_i argc, c3_c* argv[])
|
||||
c3_w arg_w;
|
||||
|
||||
static struct option lop_u[] = {
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "loom", required_argument, NULL, c3__loom },
|
||||
{ "no-demand", no_argument, NULL, 6 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -1912,6 +2129,11 @@ _cw_vile(c3_i argc, c3_c* argv[])
|
||||
|
||||
while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) {
|
||||
switch ( ch_i ) {
|
||||
case 6: { // no-demand
|
||||
u3_Host.ops_u.map = c3n;
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
} break;
|
||||
|
||||
case c3__loom: {
|
||||
c3_w lom_w;
|
||||
c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w);
|
||||
@ -1999,11 +2221,13 @@ _cw_utils(c3_i argc, c3_c* argv[])
|
||||
// $@ ~ :: usage
|
||||
// $% [%cram dir=@t] :: jam state
|
||||
// [%dock dir=@t] :: copy binary
|
||||
// [%eval ~] :: eval hoon
|
||||
// [?(%grab %mass) dir=@t] :: gc
|
||||
// [%info dir=@t] :: print
|
||||
// [%meld dir=@t] :: deduplicate
|
||||
// [?(%next %upgrade) dir=@t] :: upgrade
|
||||
// [%pack dir=@t] :: defragment
|
||||
// [%play dir=@t] :: recompute
|
||||
// [%prep dir=@t] :: prep upgrade
|
||||
// [%queu dir=@t eve=@ud] :: cue state
|
||||
// [?(%vere %fetch-vere) dir=@t] :: download vere
|
||||
@ -2044,6 +2268,7 @@ _cw_utils(c3_i argc, c3_c* argv[])
|
||||
case c3__meld: _cw_meld(argc, argv); return 1;
|
||||
case c3__next: _cw_next(argc, argv); return 2; // continue on
|
||||
case c3__pack: _cw_pack(argc, argv); return 1;
|
||||
case c3__play: _cw_play(argc, argv); return 1;
|
||||
case c3__prep: _cw_prep(argc, argv); return 2; // continue on
|
||||
case c3__queu: _cw_queu(argc, argv); return 1;
|
||||
case c3__vere: _cw_vere(argc, argv); return 1;
|
||||
@ -2181,6 +2406,12 @@ main(c3_i argc,
|
||||
u3C.wag_w |= u3o_debug_ram;
|
||||
}
|
||||
|
||||
/* Set no-demand flag.
|
||||
*/
|
||||
if ( !_(u3_Host.ops_u.map) ) {
|
||||
u3C.wag_w |= u3o_no_demand;
|
||||
}
|
||||
|
||||
/* Set profile flag.
|
||||
*/
|
||||
if ( _(u3_Host.ops_u.pro) ) {
|
||||
|
@ -1,4 +1,6 @@
|
||||
// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz)
|
||||
// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses
|
||||
// without any warranty.
|
||||
// by Gregory Pakosz (@gpakosz)
|
||||
// https://github.com/gpakosz/whereami
|
||||
|
||||
// in case you want to #include "whereami.c" in a larger compilation unit
|
||||
@ -10,6 +12,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__)
|
||||
#undef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#elif defined(__APPLE__)
|
||||
#undef _DARWIN_C_SOURCE
|
||||
#define _DARWIN_C_SOURCE
|
||||
#define _DARWIN_BETTER_REALPATH
|
||||
#endif
|
||||
|
||||
#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
@ -46,7 +57,9 @@ extern "C" {
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push, 3)
|
||||
#endif
|
||||
@ -55,6 +68,7 @@ extern "C" {
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
@ -62,8 +76,9 @@ static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, i
|
||||
wchar_t buffer2[MAX_PATH];
|
||||
wchar_t* path = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (;;)
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
DWORD size;
|
||||
int length_, length__;
|
||||
@ -119,14 +134,12 @@ static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, i
|
||||
}
|
||||
|
||||
length = length__;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (path != buffer1)
|
||||
WAI_FREE(path);
|
||||
|
||||
return length;
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
@ -156,7 +169,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun)
|
||||
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -170,6 +183,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(WAI_PROC_SELF_EXE)
|
||||
#if defined(__sun)
|
||||
@ -185,8 +199,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
char buffer[PATH_MAX];
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (;;)
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
resolved = realpath(WAI_PROC_SELF_EXE, buffer);
|
||||
if (!resolved)
|
||||
@ -211,11 +226,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return length;
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
#if !defined(WAI_PROC_SELF_MAPS_RETRY)
|
||||
@ -235,6 +248,7 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
@ -281,15 +295,24 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
&&buffer[length - 4] == '.')
|
||||
{
|
||||
int fd = open(path, O_RDONLY);
|
||||
char* begin;
|
||||
char* p;
|
||||
if (fd == -1)
|
||||
{
|
||||
length = -1; // retry
|
||||
break;
|
||||
}
|
||||
|
||||
begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0);
|
||||
p = begin + offset;
|
||||
char* begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (begin == MAP_FAILED)
|
||||
{
|
||||
close(fd);
|
||||
length = -1; // retry
|
||||
break;
|
||||
}
|
||||
|
||||
char* p = begin + offset - 30; // minimum size of local file header
|
||||
while (p >= begin) // scan backwards
|
||||
{
|
||||
if (*((uint32_t*)p) == 0x04034b50UL) // local file header found
|
||||
if (*((uint32_t*)p) == 0x04034b50UL) // local file header signature found
|
||||
{
|
||||
uint16_t length_ = *((uint16_t*)(p + 26));
|
||||
|
||||
@ -303,7 +326,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
break;
|
||||
}
|
||||
|
||||
p -= 4;
|
||||
--p;
|
||||
}
|
||||
|
||||
munmap(begin, offset);
|
||||
@ -341,20 +364,17 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
break;
|
||||
}
|
||||
|
||||
if (maps)
|
||||
fclose(maps);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#define _DARWIN_BETTER_REALPATH
|
||||
#include <mach-o/dyld.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
@ -364,8 +384,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
char* path = buffer1;
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (;;)
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
uint32_t size = (uint32_t)sizeof(buffer1);
|
||||
if (_NSGetExecutablePath(path, &size) == -1)
|
||||
@ -398,14 +419,12 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (path != buffer1)
|
||||
WAI_FREE(path);
|
||||
|
||||
return length;
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
@ -459,6 +478,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(WAI_PROC_SELF_EXE)
|
||||
#define WAI_PROC_SELF_EXE "/proc/self/exefile"
|
||||
@ -472,8 +492,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
char* resolved = NULL;
|
||||
FILE* self_exe = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (;;)
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
self_exe = fopen(WAI_PROC_SELF_EXE, "r");
|
||||
if (!self_exe)
|
||||
@ -505,13 +526,11 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
fclose(self_exe);
|
||||
|
||||
return length;
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
WAI_FUNCSPEC
|
||||
@ -559,7 +578,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
}
|
||||
|
||||
#elif defined(__DragonFly__) || defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || defined(__NetBSD__)
|
||||
defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
@ -567,6 +586,116 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
char buffer1[4096];
|
||||
char buffer2[PATH_MAX];
|
||||
char buffer3[PATH_MAX];
|
||||
char** argv = (char**)buffer1;
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
|
||||
size_t size;
|
||||
|
||||
if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0)
|
||||
break;
|
||||
|
||||
if (size > sizeof(buffer1))
|
||||
{
|
||||
argv = (char**)WAI_MALLOC(size);
|
||||
if (!argv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sysctl(mib, 4, argv, &size, NULL, 0) != 0)
|
||||
break;
|
||||
|
||||
if (strchr(argv[0], '/'))
|
||||
{
|
||||
resolved = realpath(argv[0], buffer2);
|
||||
if (!resolved)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* PATH = getenv("PATH");
|
||||
if (!PATH)
|
||||
break;
|
||||
|
||||
size_t argv0_length = strlen(argv[0]);
|
||||
|
||||
const char* begin = PATH;
|
||||
while (1)
|
||||
{
|
||||
const char* separator = strchr(begin, ':');
|
||||
const char* end = separator ? separator : begin + strlen(begin);
|
||||
|
||||
if (end - begin > 0)
|
||||
{
|
||||
if (*(end -1) == '/')
|
||||
--end;
|
||||
|
||||
if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2))
|
||||
{
|
||||
memcpy(buffer2, begin, end - begin);
|
||||
buffer2[end - begin] = '/';
|
||||
memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1);
|
||||
|
||||
resolved = realpath(buffer2, buffer3);
|
||||
if (resolved)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!separator)
|
||||
break;
|
||||
|
||||
begin = ++separator;
|
||||
}
|
||||
|
||||
if (!resolved)
|
||||
break;
|
||||
}
|
||||
|
||||
length = (int)strlen(resolved);
|
||||
if (length <= capacity)
|
||||
{
|
||||
memcpy(out, resolved, length);
|
||||
|
||||
if (dirname_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = length - 1; i >= 0; --i)
|
||||
{
|
||||
if (out[i] == '/')
|
||||
{
|
||||
*dirname_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argv != (char**)buffer1)
|
||||
WAI_FREE(argv);
|
||||
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
@ -576,13 +705,18 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
char* path = buffer1;
|
||||
char* resolved = NULL;
|
||||
int length = -1;
|
||||
bool ok;
|
||||
|
||||
for (;;)
|
||||
for (ok = false; !ok; ok = true)
|
||||
{
|
||||
#if defined(__NetBSD__)
|
||||
int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
|
||||
#else
|
||||
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
||||
#endif
|
||||
size_t size = sizeof(buffer1);
|
||||
|
||||
if (sysctl(mib, (u_int)(sizeof(mib) / sizeof(mib[0])), path, &size, NULL, 0) != 0)
|
||||
if (sysctl(mib, 4, path, &size, NULL, 0) != 0)
|
||||
break;
|
||||
|
||||
resolved = realpath(path, buffer2);
|
||||
@ -608,16 +742,13 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (path != buffer1)
|
||||
WAI_FREE(path);
|
||||
|
||||
return length;
|
||||
return ok ? length : -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
WAI_NOINLINE WAI_FUNCSPEC
|
||||
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
{
|
||||
@ -670,4 +801,4 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -1,4 +1,6 @@
|
||||
// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz)
|
||||
// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses
|
||||
// without any warranty.
|
||||
// by Gregory Pakosz (@gpakosz)
|
||||
// https://github.com/gpakosz/whereami
|
||||
|
||||
#ifndef WHEREAMI_H
|
||||
@ -62,4 +64,4 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #ifndef WHEREAMI_H
|
||||
#endif // #ifndef WHEREAMI_H
|
@ -11,7 +11,6 @@
|
||||
# include "noun/aliases.h" // general u3
|
||||
|
||||
# include "noun/allocate.h" // u3a: allocation
|
||||
# include "noun/events.h" // u3e: persistence
|
||||
# include "noun/hashtable.h" // u3h: hashtables
|
||||
# include "noun/imprison.h" // u3i: noun construction
|
||||
# include "noun/jets.h" // u3j: jet control
|
||||
|
@ -1,6 +1,11 @@
|
||||
#ifndef C3_DEFS_H
|
||||
#define C3_DEFS_H
|
||||
|
||||
#include "c/portable.h"
|
||||
#include "c/types.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/** Loobeans - inverse booleans to match nock.
|
||||
**/
|
||||
# define c3y 0
|
||||
@ -157,4 +162,28 @@
|
||||
# define c3_fopen(a, b) ({ \
|
||||
fopen(a, b);})
|
||||
|
||||
/** i/o wrappers
|
||||
***
|
||||
*** these handle partial success and retry ephemeral errors
|
||||
*** up to hardcoded max try count, either reading/writing fully
|
||||
*** (up to EOF on read) or returning on error.
|
||||
***
|
||||
*** a wrapper for read() is not provided, as file cursor position
|
||||
*** is undefined on error. use pread() or loop yourself.
|
||||
**/
|
||||
/* c3_pread(): full positioned read(), up to eof, retrying errors.
|
||||
*/
|
||||
ssize_t
|
||||
c3_pread(c3_i fid_i, void* buf_v, size_t len_i, off_t off_i);
|
||||
|
||||
/* c3_pwrite(): full positioned write(), retrying errors.
|
||||
*/
|
||||
ssize_t
|
||||
c3_pwrite(c3_i fid_i, const void* buf_v, size_t len_i, off_t off_i);
|
||||
|
||||
/* c3_write(): full write(), retrying errors.
|
||||
*/
|
||||
ssize_t
|
||||
c3_write(c3_i fid_i, const void* buf_v, size_t len_i);
|
||||
|
||||
#endif /* ifndef C3_DEFS_H */
|
||||
|
@ -645,6 +645,11 @@
|
||||
void
|
||||
u3a_print_memory(FILE* fil_u, c3_c* cap_c, c3_w wor_w);
|
||||
|
||||
/* u3a_prof(): mark/measure/print memory profile. RETAIN.
|
||||
*/
|
||||
c3_w
|
||||
u3a_prof(FILE* fil_u, c3_w den_w, u3_noun mas);
|
||||
|
||||
/* u3a_maid(): maybe print memory.
|
||||
*/
|
||||
c3_w
|
||||
|
@ -39,13 +39,22 @@
|
||||
/* u3e_pool: entire memory system.
|
||||
*/
|
||||
typedef struct _u3e_pool {
|
||||
c3_c* dir_c; // path to
|
||||
c3_c* dir_c; // checkpoint dir
|
||||
c3_w dit_w[u3a_pages >> 5]; // touched since last save
|
||||
c3_w pag_w; // number of pages (<= u3a_pages)
|
||||
c3_w gar_w; // guard page
|
||||
u3e_image nor_u; // north segment
|
||||
u3e_image sou_u; // south segment
|
||||
} u3e_pool;
|
||||
|
||||
/* u3e_flaw: loom fault result.
|
||||
*/
|
||||
typedef enum {
|
||||
u3e_flaw_sham = 0, // bogus state
|
||||
u3e_flaw_base = 1, // vm fail (mprotect)
|
||||
u3e_flaw_meme = 2, // bail:meme
|
||||
u3e_flaw_good = 3 // handled
|
||||
} u3e_flaw;
|
||||
|
||||
/** Globals.
|
||||
**/
|
||||
@ -60,31 +69,26 @@
|
||||
|
||||
/** Functions.
|
||||
**/
|
||||
/* u3e_fault(): handle a memory event with libsigsegv protocol.
|
||||
/* u3e_fault(): handle a memory fault.
|
||||
*/
|
||||
c3_i
|
||||
u3e_fault(void* adr_v, c3_i ser_i);
|
||||
u3e_flaw
|
||||
u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p);
|
||||
|
||||
/* u3e_save():
|
||||
/* u3e_save(): update the checkpoint.
|
||||
*/
|
||||
void
|
||||
u3e_save(void);
|
||||
u3e_save(u3_post low_p, u3_post hig_p);
|
||||
|
||||
/* u3e_live(): start the persistence system. Return c3y if no image.
|
||||
*/
|
||||
c3_o
|
||||
u3e_live(c3_o nuu_o, c3_c* dir_c);
|
||||
u3e_live(c3_c* dir_c);
|
||||
|
||||
/* u3e_yolo(): disable dirty page tracking, read/write whole loom.
|
||||
*/
|
||||
c3_o
|
||||
u3e_yolo(void);
|
||||
|
||||
/* u3e_foul(): dirty all the pages of the loom.
|
||||
*/
|
||||
void
|
||||
u3e_foul(void);
|
||||
|
||||
/* u3e_init(): initialize guard page tracking.
|
||||
*/
|
||||
void
|
||||
|
@ -8,6 +8,11 @@
|
||||
c3_d
|
||||
u3m_boot(c3_c* dir_c, size_t len_i);
|
||||
|
||||
/* u3m_pier(): make a pier.
|
||||
*/
|
||||
c3_c*
|
||||
u3m_pier(c3_c* dir_c);
|
||||
|
||||
/* u3m_boot_lite(): start without checkpointing.
|
||||
*/
|
||||
c3_d
|
||||
@ -34,6 +39,21 @@
|
||||
c3_i
|
||||
u3m_bail(c3_m how_m) __attribute__((noreturn));
|
||||
|
||||
/* u3m_fault(): handle a memory event with libsigsegv protocol.
|
||||
*/
|
||||
c3_i
|
||||
u3m_fault(void* adr_v, c3_i ser_i);
|
||||
|
||||
/* u3m_save(): update the checkpoint.
|
||||
*/
|
||||
void
|
||||
u3m_save(void);
|
||||
|
||||
/* u3m_ward(): tend the guard page.
|
||||
*/
|
||||
void
|
||||
u3m_ward(void);
|
||||
|
||||
/* u3m_init(): start the environment.
|
||||
*/
|
||||
void
|
||||
@ -117,7 +137,7 @@
|
||||
/* u3m_water(): produce high and low watermarks. Asserts u3R == u3H.
|
||||
*/
|
||||
void
|
||||
u3m_water(c3_w *low_w, c3_w *hig_w);
|
||||
u3m_water(u3_post* low_p, u3_post* hig_p);
|
||||
|
||||
/* u3m_pretty(): dumb prettyprint to string. RETAIN.
|
||||
*/
|
||||
|
@ -22,15 +22,17 @@
|
||||
** _check flags are set inside u3 and heard outside it.
|
||||
*/
|
||||
enum u3o_flag { // execution flags
|
||||
u3o_debug_ram = 0x1, // debug: gc
|
||||
u3o_debug_cpu = 0x2, // debug: profile
|
||||
u3o_check_corrupt = 0x4, // check: gc memory
|
||||
u3o_check_fatal = 0x8, // check: unrecoverable
|
||||
u3o_verbose = 0x10, // be remarkably wordy
|
||||
u3o_dryrun = 0x20, // don't touch checkpoint
|
||||
u3o_quiet = 0x40, // disable ~&
|
||||
u3o_hashless = 0x80, // disable hashboard
|
||||
u3o_trace = 0x100 // enables trace dumping
|
||||
u3o_debug_ram = 1 << 0, // debug: gc
|
||||
u3o_debug_cpu = 1 << 1, // debug: profile
|
||||
u3o_check_corrupt = 1 << 2, // check: gc memory
|
||||
u3o_check_fatal = 1 << 3, // check: unrecoverable
|
||||
u3o_verbose = 1 << 4, // be remarkably wordy
|
||||
u3o_dryrun = 1 << 5, // don't touch checkpoint
|
||||
u3o_quiet = 1 << 6, // disable ~&
|
||||
u3o_hashless = 1 << 7, // disable hashboard
|
||||
u3o_trace = 1 << 8, // enables trace dumping
|
||||
u3o_auto_meld = 1 << 9, // enables meld under pressure
|
||||
u3o_no_demand = 1 << 10 // disables demand paging
|
||||
};
|
||||
|
||||
/** Globals.
|
||||
|
@ -5,7 +5,7 @@
|
||||
**/
|
||||
/* u3u_meld(): globally deduplicate memory.
|
||||
*/
|
||||
void
|
||||
c3_w
|
||||
u3u_meld(void);
|
||||
|
||||
/* u3u_cram(): globably deduplicate memory, and write a rock to disk.
|
||||
|
@ -87,6 +87,11 @@
|
||||
u3_noun
|
||||
u3v_poke(u3_noun ovo);
|
||||
|
||||
/* u3v_poke_sure(): inject an event, saving new state if successful.
|
||||
*/
|
||||
c3_o
|
||||
u3v_poke_sure(c3_w mil_w, u3_noun eve, u3_noun* pro);
|
||||
|
||||
/* u3v_tank(): dump single tank.
|
||||
*/
|
||||
void
|
||||
|
@ -6,6 +6,17 @@
|
||||
/* lmdb api wrapper
|
||||
*/
|
||||
|
||||
/* u3_lmdb_iter: event iterator
|
||||
*/
|
||||
typedef struct _u3_lmdb_walk {
|
||||
MDB_txn* txn_u; // transaction handle
|
||||
MDB_dbi mdb_u; // db handle
|
||||
MDB_cursor* cur_u; // db cursor
|
||||
c3_o red_o; // have we read from this yet?
|
||||
c3_d nex_d; // next event number
|
||||
c3_d las_d; // final event number, inclusive
|
||||
} u3_lmdb_walk;
|
||||
|
||||
/* u3_lmdb_init(): open lmdb at [pax_c], mmap up to [siz_i].
|
||||
*/
|
||||
MDB_env*
|
||||
@ -61,4 +72,22 @@
|
||||
size_t val_i,
|
||||
void* val_p);
|
||||
|
||||
/* u3_lmdb_walk_init(): initialize db iterator.
|
||||
*/
|
||||
c3_o
|
||||
u3_lmdb_walk_init(MDB_env* env_u,
|
||||
u3_lmdb_walk* itr_u,
|
||||
c3_d nex_d,
|
||||
c3_d las_d);
|
||||
|
||||
/* u3_lmdb_walk_next(): synchronously read next event from iterator.
|
||||
*/
|
||||
c3_o
|
||||
u3_lmdb_walk_next(u3_lmdb_walk* itr_u, size_t* len_i, void** buf_v);
|
||||
|
||||
/* u3_lmdb_walk_done(): close iterator.
|
||||
*/
|
||||
void
|
||||
u3_lmdb_walk_done(u3_lmdb_walk* itr_u);
|
||||
|
||||
#endif /* ifndef U3_VERE_DB_LMDB_H */
|
||||
|
22
pkg/urbit/include/vere/mars.h
Normal file
22
pkg/urbit/include/vere/mars.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef U3_VERE_MARS_H
|
||||
#define U3_VERE_MARS_H
|
||||
|
||||
/** Data types.
|
||||
**/
|
||||
/* u3_mars: the urbit state machine.
|
||||
*/
|
||||
typedef struct _u3_mars {
|
||||
c3_d key_d[4]; // disk key
|
||||
u3_disk* log_u; // event log
|
||||
c3_c* dir_c; // execution directory (pier)
|
||||
c3_d sen_d; // last event requested
|
||||
c3_d dun_d; // last event processed
|
||||
c3_l mug_l; // hash of state
|
||||
} u3_mars;
|
||||
|
||||
/* u3_mars_play(): replay logged events up to [eve_d].
|
||||
*/
|
||||
void
|
||||
u3_mars_play(u3_mars* mar_u, c3_d eve_d);
|
||||
|
||||
#endif /* ifndef U3_VERE_MARS_H */
|
@ -313,6 +313,7 @@
|
||||
c3_c* puf_c; // -Z, scry result format
|
||||
c3_o con; // run conn
|
||||
c3_o doc; // dock binary in pier
|
||||
c3_o map; // --no-demand (reversed)
|
||||
} u3_opts;
|
||||
|
||||
/* u3_host: entire host.
|
||||
@ -562,6 +563,10 @@
|
||||
u3_info put_u; // write queue
|
||||
} u3_disk;
|
||||
|
||||
/* u3_disk_walk: opaque event log iterator.
|
||||
*/
|
||||
typedef struct _u3_disk_walk u3_disk_walk;
|
||||
|
||||
/* u3_psat: pier state.
|
||||
*/
|
||||
typedef enum {
|
||||
@ -942,6 +947,23 @@
|
||||
u3_disk*
|
||||
u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u);
|
||||
|
||||
/* u3_disk_etch(): serialize an event for persistence. RETAIN [eve]
|
||||
*/
|
||||
size_t
|
||||
u3_disk_etch(u3_disk* log_u,
|
||||
u3_noun eve,
|
||||
c3_l mug_l,
|
||||
c3_y** out_y);
|
||||
|
||||
/* u3_disk_sift(): parse a persisted event buffer.
|
||||
*/
|
||||
c3_o
|
||||
u3_disk_sift(u3_disk* log_u,
|
||||
size_t len_i,
|
||||
c3_y* dat_y,
|
||||
c3_l* mug_l,
|
||||
u3_noun* job);
|
||||
|
||||
/* u3_disk_info(): status info as $mass.
|
||||
*/
|
||||
u3_noun
|
||||
@ -993,6 +1015,33 @@
|
||||
void
|
||||
u3_disk_plan(u3_disk* log_u, u3_fact* tac_u);
|
||||
|
||||
/* u3_disk_read_list(): synchronously read a cons list of events.
|
||||
*/
|
||||
u3_weak
|
||||
u3_disk_read_list(u3_disk* log_u, c3_d eve_d, c3_d len_d, c3_l* mug_l);
|
||||
|
||||
/* u3_disk_walk_init(): init iterator.
|
||||
*/
|
||||
u3_disk_walk*
|
||||
u3_disk_walk_init(u3_disk* log_u,
|
||||
c3_d eve_d,
|
||||
c3_d len_d);
|
||||
|
||||
/* u3_disk_walk_live(): check if live.
|
||||
*/
|
||||
c3_o
|
||||
u3_disk_walk_live(u3_disk_walk* wok_u);
|
||||
|
||||
/* u3_disk_walk_live(): get next fact.
|
||||
*/
|
||||
c3_o
|
||||
u3_disk_walk_step(u3_disk_walk* wok_u, u3_fact* tac_u);
|
||||
|
||||
/* u3_disk_walk_done(): close iterator.
|
||||
*/
|
||||
void
|
||||
u3_disk_walk_done(u3_disk_walk* wok_u);
|
||||
|
||||
/* u3_lord_init(): start serf.
|
||||
*/
|
||||
u3_lord*
|
||||
@ -1461,11 +1510,6 @@
|
||||
void
|
||||
u3_daemon_init();
|
||||
|
||||
/* u3_write_fd(): retry interrupts, continue partial writes, assert errors.
|
||||
*/
|
||||
void
|
||||
u3_write_fd(c3_i fid_i, const void* buf_v, size_t len_i);
|
||||
|
||||
c3_w
|
||||
u3_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
|
||||
|
||||
|
@ -425,8 +425,18 @@ _ca_willoc(c3_w len_w, c3_w ald_w, c3_w alp_w)
|
||||
|
||||
alp_w = (alp_w + c3_wiseof(u3a_box)) % ald_w;
|
||||
|
||||
// XX: this logic is totally bizarre, but preserve it.
|
||||
//
|
||||
/* XX: this logic is totally bizarre, but preserve it.
|
||||
**
|
||||
** This means we use the next size bigger instead of the "correct"
|
||||
** size. For example, a 20 word allocation will be freed into free
|
||||
** list 2 but will be allocated from free list 3.
|
||||
**
|
||||
** This is important to preserve because the sequential search may be
|
||||
** very slow. On a real-world task involving many compilations,
|
||||
** removing this line made this function appear in ~80% of samples.
|
||||
**
|
||||
** For reference, this was added in cgyarvin/urbit ffed9e748d8f6c.
|
||||
*/
|
||||
if ( (sel_w != 0) && (sel_w != u3a_fbox_no - 1) ) {
|
||||
sel_w += 1;
|
||||
}
|
||||
@ -1617,7 +1627,7 @@ u3a_mark_ptr(void* ptr_v)
|
||||
if ( 0 == box_u->eus_w ) {
|
||||
siz_w = box_u->siz_w;
|
||||
}
|
||||
else if ( 0xffffffff == box_u->eus_w ) { // see _raft_prof()
|
||||
else if ( 0xffffffff == box_u->eus_w ) { // see u3a_prof()
|
||||
siz_w = 0xffffffff;
|
||||
box_u->eus_w = 0;
|
||||
}
|
||||
@ -1635,7 +1645,7 @@ u3a_mark_ptr(void* ptr_v)
|
||||
else {
|
||||
c3_assert(use_ws != 0);
|
||||
|
||||
if ( 0x80000000 == (c3_w)use_ws ) { // see _raft_prof()
|
||||
if ( 0x80000000 == (c3_w)use_ws ) { // see u3a_prof()
|
||||
use_ws = -1;
|
||||
siz_w = 0xffffffff;
|
||||
}
|
||||
@ -1906,7 +1916,7 @@ u3a_print_memory(FILE* fil_u, c3_c* cap_c, c3_w wor_w)
|
||||
if ( byt_w ) {
|
||||
if ( gib_w ) {
|
||||
fprintf(fil_u, "%s: GB/%d.%03d.%03d.%03d\r\n",
|
||||
cap_c, gib_w, mib_w, kib_w, bib_w);
|
||||
cap_c, gib_w, mib_w, kib_w, bib_w);
|
||||
}
|
||||
else if ( mib_w ) {
|
||||
fprintf(fil_u, "%s: MB/%d.%03d.%03d\r\n", cap_c, mib_w, kib_w, bib_w);
|
||||
@ -1931,6 +1941,122 @@ u3a_maid(FILE* fil_u, c3_c* cap_c, c3_w wor_w)
|
||||
return wor_w;
|
||||
}
|
||||
|
||||
/* _ca_print_memory(): un-captioned u3a_print_memory().
|
||||
*/
|
||||
static void
|
||||
_ca_print_memory(FILE* fil_u, c3_w wor_w)
|
||||
{
|
||||
c3_w byt_w = (wor_w * 4);
|
||||
c3_w gib_w = (byt_w / 1000000000);
|
||||
c3_w mib_w = (byt_w % 1000000000) / 1000000;
|
||||
c3_w kib_w = (byt_w % 1000000) / 1000;
|
||||
c3_w bib_w = (byt_w % 1000);
|
||||
|
||||
if ( gib_w ) {
|
||||
fprintf(fil_u, "GB/%d.%03d.%03d.%03d\r\n",
|
||||
gib_w, mib_w, kib_w, bib_w);
|
||||
}
|
||||
else if ( mib_w ) {
|
||||
fprintf(fil_u, "MB/%d.%03d.%03d\r\n", mib_w, kib_w, bib_w);
|
||||
}
|
||||
else if ( kib_w ) {
|
||||
fprintf(fil_u, "KB/%d.%03d\r\n", kib_w, bib_w);
|
||||
}
|
||||
else {
|
||||
fprintf(fil_u, "B/%d\r\n", bib_w);
|
||||
}
|
||||
}
|
||||
|
||||
/* u3a_prof(): mark/measure/print memory profile. RETAIN.
|
||||
*/
|
||||
c3_w
|
||||
u3a_prof(FILE* fil_u, c3_w den_w, u3_noun mas)
|
||||
{
|
||||
c3_w tot_w = 0;
|
||||
u3_noun h_mas, t_mas;
|
||||
|
||||
if ( c3n == u3r_cell(mas, &h_mas, &t_mas) ) {
|
||||
fprintf(fil_u, "%.*smistyped mass\r\n", den_w, "");
|
||||
return tot_w;
|
||||
}
|
||||
else if ( _(u3du(h_mas)) ) {
|
||||
fprintf(fil_u, "%.*smistyped mass head\r\n", den_w, "");
|
||||
{
|
||||
c3_c* lab_c = u3m_pretty(h_mas);
|
||||
fprintf(fil_u, "h_mas: %s", lab_c);
|
||||
c3_free(lab_c);
|
||||
}
|
||||
return tot_w;
|
||||
}
|
||||
else {
|
||||
{
|
||||
c3_c* lab_c = u3m_pretty(h_mas);
|
||||
fprintf(fil_u, "%*s%s: ", den_w, "", lab_c);
|
||||
c3_free(lab_c);
|
||||
}
|
||||
|
||||
u3_noun it_mas, tt_mas;
|
||||
|
||||
if ( c3n == u3r_cell(t_mas, &it_mas, &tt_mas) ) {
|
||||
fprintf(fil_u, "%*smistyped mass tail\r\n", den_w, "");
|
||||
return tot_w;
|
||||
}
|
||||
else if ( c3y == it_mas ) {
|
||||
tot_w += u3a_mark_noun(tt_mas);
|
||||
_ca_print_memory(fil_u, tot_w);
|
||||
|
||||
#if 1
|
||||
/* The basic issue here is that tt_mas is included in .sac
|
||||
* (the whole profile), so they can't both be roots in the
|
||||
* normal sense. When we mark .sac later on, we want tt_mas
|
||||
* to appear unmarked, but its children should be already
|
||||
* marked.
|
||||
*
|
||||
* see u3a_mark_ptr().
|
||||
*/
|
||||
if ( _(u3a_is_dog(tt_mas)) ) {
|
||||
u3a_box* box_u = u3a_botox(u3a_to_ptr(tt_mas));
|
||||
#ifdef U3_MEMORY_DEBUG
|
||||
if ( 1 == box_u->eus_w ) {
|
||||
box_u->eus_w = 0xffffffff;
|
||||
}
|
||||
else {
|
||||
box_u->eus_w -= 1;
|
||||
}
|
||||
#else
|
||||
if ( -1 == (c3_w)box_u->use_w ) {
|
||||
box_u->use_w = 0x80000000;
|
||||
}
|
||||
else {
|
||||
box_u->use_w += 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return tot_w;
|
||||
}
|
||||
else if ( c3n == it_mas ) {
|
||||
fprintf(fil_u, "\r\n");
|
||||
|
||||
while ( _(u3du(tt_mas)) ) {
|
||||
tot_w += u3a_prof(fil_u, den_w+2, u3h(tt_mas));
|
||||
tt_mas = u3t(tt_mas);
|
||||
}
|
||||
|
||||
fprintf(fil_u, "%*s--", den_w, "");
|
||||
_ca_print_memory(fil_u, tot_w);
|
||||
|
||||
return tot_w;
|
||||
|
||||
}
|
||||
else {
|
||||
fprintf(fil_u, "%*smistyped (strange) mass tail\r\n", den_w, "");
|
||||
return tot_w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* u3a_mark_road(): mark ad-hoc persistent road structures.
|
||||
*/
|
||||
c3_w
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
||||
**
|
||||
*/
|
||||
#include "all.h"
|
||||
#include "noun/events.h"
|
||||
#include "rsignal.h"
|
||||
#include "vere/vere.h"
|
||||
#include <errno.h>
|
||||
@ -436,7 +437,7 @@ u3m_file(c3_c* pas_c)
|
||||
u3l_log("Loading file: %s\r\n", pas_c);
|
||||
struct stat buf_b;
|
||||
c3_i fid_i = c3_open(pas_c, O_RDONLY, 0644);
|
||||
c3_w fln_w, red_w;
|
||||
c3_w fln_w;
|
||||
c3_y* pad_y;
|
||||
|
||||
if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) {
|
||||
@ -448,10 +449,10 @@ u3m_file(c3_c* pas_c)
|
||||
|
||||
pad_y = c3_malloc(buf_b.st_size);
|
||||
|
||||
red_w = read(fid_i, pad_y, fln_w);
|
||||
ssize_t red_i = c3_pread(fid_i, pad_y, fln_w, 0);
|
||||
close(fid_i);
|
||||
|
||||
if ( fln_w != red_w ) {
|
||||
if ( red_i != fln_w ) {
|
||||
c3_free(pad_y);
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
@ -527,6 +528,8 @@ _pave_north(c3_w* mem_w, c3_w siz_w, c3_w len_w)
|
||||
// the stack starts at the end of the memory segment,
|
||||
// minus space for the road structure [siz_w]
|
||||
//
|
||||
// NB: the returned road is "above" the stack
|
||||
//
|
||||
c3_w* rut_w = mem_w;
|
||||
c3_w* mat_w = ((mem_w + len_w) - siz_w);
|
||||
c3_w* cap_w = mat_w;
|
||||
@ -545,6 +548,8 @@ _pave_south(c3_w* mem_w, c3_w siz_w, c3_w len_w)
|
||||
// the stack starts at the base memory pointer [mem_w],
|
||||
// and ends after the space for the road structure [siz_w]
|
||||
//
|
||||
// NB: the returned road is *on* the stack
|
||||
//
|
||||
c3_w* rut_w = (mem_w + len_w);
|
||||
c3_w* mat_w = mem_w;
|
||||
c3_w* cap_w = mat_w + siz_w;
|
||||
@ -600,7 +605,7 @@ _find_home(void)
|
||||
// this looks risky, but there are no legitimate scenarios
|
||||
// where it's wrong
|
||||
//
|
||||
u3R->cap_p = u3R->mat_p = u3C.wor_i - c3_wiseof(*u3H);
|
||||
u3R->cap_p = u3R->mat_p = u3a_outa(u3H);
|
||||
}
|
||||
|
||||
/* u3m_pave(): instantiate or activate image.
|
||||
@ -819,7 +824,6 @@ u3m_leap(c3_w pad_w)
|
||||
u3R->cap_p -= len_w;
|
||||
|
||||
rod_u = _pave_south(u3a_into(bot_p), c3_wiseof(u3a_road), len_w);
|
||||
u3e_ward(rod_u->cap_p, rod_u->hat_p);
|
||||
#if 0
|
||||
fprintf(stderr, "leap: from north %p (cap 0x%x), to south %p\r\n",
|
||||
u3R,
|
||||
@ -832,7 +836,6 @@ u3m_leap(c3_w pad_w)
|
||||
u3R->cap_p += len_w;
|
||||
|
||||
rod_u = _pave_north(u3a_into(bot_p), c3_wiseof(u3a_road), len_w);
|
||||
u3e_ward(rod_u->hat_p, rod_u->cap_p);
|
||||
#if 0
|
||||
fprintf(stderr, "leap: from south %p (cap 0x%x), to north %p\r\n",
|
||||
u3R,
|
||||
@ -854,6 +857,7 @@ u3m_leap(c3_w pad_w)
|
||||
*/
|
||||
{
|
||||
u3R = rod_u;
|
||||
u3m_ward();
|
||||
_pave_parts();
|
||||
}
|
||||
#ifdef U3_MEMORY_DEBUG
|
||||
@ -1003,12 +1007,31 @@ u3m_flog(c3_w gof_w)
|
||||
/* u3m_water(): produce watermarks.
|
||||
*/
|
||||
void
|
||||
u3m_water(c3_w* low_w, c3_w* hig_w)
|
||||
u3m_water(u3_post* low_p, u3_post* hig_p)
|
||||
{
|
||||
c3_assert(u3R == &u3H->rod_u);
|
||||
|
||||
*low_w = u3a_heap(u3R);
|
||||
*hig_w = u3a_temp(u3R) + c3_wiseof(u3v_home);
|
||||
// allow the segfault handler to fire before the road is set
|
||||
//
|
||||
// while not explicitly possible in the codebase,
|
||||
// compiler optimizations can reorder stores
|
||||
//
|
||||
if ( !u3R ) {
|
||||
*low_p = 0;
|
||||
*hig_p = u3C.wor_i - 1;
|
||||
}
|
||||
// in a north road, hat points to the end of the heap + 1 word,
|
||||
// while cap points to the top of the stack
|
||||
//
|
||||
else if ( c3y == u3a_is_north(u3R) ) {
|
||||
*low_p = u3R->hat_p - 1;
|
||||
*hig_p = u3R->cap_p;
|
||||
}
|
||||
// in a south road, hat points to the end of the heap,
|
||||
// while cap points to the top of the stack + 1 word
|
||||
//
|
||||
else {
|
||||
*low_p = u3R->cap_p - 1;
|
||||
*hig_p = u3R->hat_p;
|
||||
}
|
||||
}
|
||||
|
||||
/* u3m_soft_top(): top-level safety wrapper.
|
||||
@ -1692,6 +1715,80 @@ _cm_limits(void)
|
||||
# endif
|
||||
}
|
||||
|
||||
/* u3m_fault(): handle a memory event with libsigsegv protocol.
|
||||
*/
|
||||
c3_i
|
||||
u3m_fault(void* adr_v, c3_i ser_i)
|
||||
{
|
||||
// let the stack overflow handler run.
|
||||
//
|
||||
if ( 0 == ser_i ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
c3_w* adr_w = (c3_w*)adr_v;
|
||||
u3_post low_p, hig_p;
|
||||
|
||||
if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3C.wor_i)) ) {
|
||||
fprintf(stderr, "loom: external fault: %p (%p : %p)\r\n\r\n",
|
||||
adr_w, u3_Loom, u3_Loom + u3C.wor_i);
|
||||
c3_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u3m_water(&low_p, &hig_p);
|
||||
|
||||
switch ( u3e_fault(low_p, hig_p, u3a_outa(adr_w)) ) {
|
||||
// page tracking invariants violated, fatal
|
||||
//
|
||||
case u3e_flaw_sham: {
|
||||
c3_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual memory failure (protections), possibly recoverable XX
|
||||
//
|
||||
case u3e_flaw_base: {
|
||||
c3_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// loom limits exceeded, recoverable
|
||||
//
|
||||
case u3e_flaw_meme: {
|
||||
u3m_signal(c3__meme); // doesn't return
|
||||
return 1;
|
||||
}
|
||||
|
||||
case u3e_flaw_good: return 1;
|
||||
}
|
||||
|
||||
c3_assert(!"unpossible");
|
||||
}
|
||||
|
||||
/* u3m_save(): update the checkpoint.
|
||||
*/
|
||||
void
|
||||
u3m_save(void)
|
||||
{
|
||||
u3_post low_p, hig_p;
|
||||
u3m_water(&low_p, &hig_p);
|
||||
|
||||
c3_assert(u3R == &u3H->rod_u);
|
||||
|
||||
return u3e_save(low_p, hig_p);
|
||||
}
|
||||
|
||||
/* u3m_ward(): tend the guard page.
|
||||
*/
|
||||
void
|
||||
u3m_ward(void)
|
||||
{
|
||||
u3_post low_p, hig_p;
|
||||
u3m_water(&low_p, &hig_p);
|
||||
return u3e_ward(low_p, hig_p);
|
||||
}
|
||||
|
||||
/* _cm_signals(): set up interrupts, etc.
|
||||
*/
|
||||
static void
|
||||
@ -1707,7 +1804,7 @@ _cm_signals(void)
|
||||
// filter (see compat/mingw/seh_handler.c) that handles both memory
|
||||
// access and stack overflow exceptions. It calls u3e_fault directly.
|
||||
# else
|
||||
if ( 0 != sigsegv_install_handler(u3e_fault) ) {
|
||||
if ( 0 != sigsegv_install_handler(u3m_fault) ) {
|
||||
u3l_log("boot: sigsegv install failed\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -1864,6 +1961,46 @@ void
|
||||
u3m_stop()
|
||||
{
|
||||
u3je_secp_stop();
|
||||
|
||||
// XX move to jets.c
|
||||
//
|
||||
c3_free(u3D.ray_u);
|
||||
}
|
||||
|
||||
/* u3m_pier(): make a pier.
|
||||
*/
|
||||
c3_c*
|
||||
u3m_pier(c3_c* dir_c)
|
||||
{
|
||||
c3_c ful_c[8193];
|
||||
|
||||
u3C.dir_c = dir_c;
|
||||
|
||||
snprintf(ful_c, 8192, "%s", dir_c);
|
||||
if ( c3_mkdir(ful_c, 0700) ) {
|
||||
if ( EEXIST != errno ) {
|
||||
fprintf(stderr, "loom: pier create: %s\r\n", strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb", dir_c);
|
||||
if ( c3_mkdir(ful_c, 0700) ) {
|
||||
if ( EEXIST != errno ) {
|
||||
fprintf(stderr, "loom: .urb create: %s\r\n", strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(ful_c, 8192, "%s/.urb/chk", dir_c);
|
||||
if ( c3_mkdir(ful_c, 0700) ) {
|
||||
if ( EEXIST != errno ) {
|
||||
fprintf(stderr, "loom: .urb/chk create: %s\r\n", strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
return strdup(ful_c);
|
||||
}
|
||||
|
||||
/* u3m_boot(): start the u3 system. return next event, starting from 1.
|
||||
@ -1879,7 +2016,7 @@ u3m_boot(c3_c* dir_c, size_t len_i)
|
||||
|
||||
/* Activate the storage system.
|
||||
*/
|
||||
nuu_o = u3e_live(c3n, dir_c);
|
||||
nuu_o = u3e_live(u3m_pier(dir_c));
|
||||
|
||||
/* Activate tracing.
|
||||
*/
|
||||
@ -1892,10 +2029,6 @@ u3m_boot(c3_c* dir_c, size_t len_i)
|
||||
*/
|
||||
u3m_pave(nuu_o);
|
||||
|
||||
/* Place the guard page.
|
||||
*/
|
||||
u3e_init();
|
||||
|
||||
/* Initialize the jet system.
|
||||
*/
|
||||
{
|
||||
|
@ -278,11 +278,19 @@ void
|
||||
u3t_trace_open(c3_c* dir_c)
|
||||
{
|
||||
c3_c fil_c[2048];
|
||||
|
||||
if ( !dir_c ) {
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(fil_c, 2048, "%s/.urb/put/trace", dir_c);
|
||||
|
||||
struct stat st;
|
||||
if ( -1 == stat(fil_c, &st) ) {
|
||||
c3_mkdir(fil_c, 0700);
|
||||
if ( (-1 == stat(fil_c, &st))
|
||||
&& (-1 == c3_mkdir(fil_c, 0700)) )
|
||||
{
|
||||
fprintf(stderr, "mkdir: %s failed: %s\r\n", fil_c, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
c3_c lif_c[2056];
|
||||
@ -291,6 +299,11 @@ u3t_trace_open(c3_c* dir_c)
|
||||
u3_Host.tra_u.fil_u = c3_fopen(lif_c, "w");
|
||||
u3_Host.tra_u.nid_w = (int)getpid();
|
||||
|
||||
if ( !u3_Host.tra_u.fil_u) {
|
||||
fprintf(stderr, "trace open: %s\r\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(u3_Host.tra_u.fil_u, "[ ");
|
||||
|
||||
// We have two "threads", the event processing and the nock stuff.
|
||||
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
*/
|
||||
#include "all.h"
|
||||
#include "noun/events.h"
|
||||
#include "ur/ur.h"
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@ -416,10 +417,6 @@ _cu_realloc(FILE* fil_u, ur_root_t** tor_u, ur_nvec_t* doc_u)
|
||||
//
|
||||
u3A->eve_d = eve_d;
|
||||
|
||||
// mark all pages dirty
|
||||
//
|
||||
u3e_foul();
|
||||
|
||||
*tor_u = rot_u;
|
||||
*doc_u = cod_u;
|
||||
|
||||
@ -429,15 +426,17 @@ _cu_realloc(FILE* fil_u, ur_root_t** tor_u, ur_nvec_t* doc_u)
|
||||
/* u3u_meld(): globally deduplicate memory.
|
||||
*/
|
||||
#ifdef U3_MEMORY_DEBUG
|
||||
void
|
||||
c3_w
|
||||
u3u_meld(void)
|
||||
{
|
||||
fprintf(stderr, "u3: unable to meld under U3_MEMORY_DEBUG\r\n");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
void
|
||||
c3_w
|
||||
u3u_meld(void)
|
||||
{
|
||||
c3_w pre_w = u3a_open(u3R);
|
||||
ur_root_t* rot_u;
|
||||
ur_nvec_t cod_u;
|
||||
|
||||
@ -449,6 +448,8 @@ u3u_meld(void)
|
||||
//
|
||||
ur_nvec_free(&cod_u);
|
||||
ur_root_free(rot_u);
|
||||
|
||||
return (u3a_open(u3R) - pre_w);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -564,56 +565,14 @@ _cu_rock_save(c3_c* dir_c, c3_d eve_d, c3_d len_d, c3_y* byt_y)
|
||||
|
||||
// write jam-buffer into [fid_i]
|
||||
//
|
||||
// XX deduplicate with _write() wrapper in term.c
|
||||
//
|
||||
{
|
||||
ssize_t ret_i;
|
||||
|
||||
while ( len_d > 0 ) {
|
||||
c3_w lop_w = 0;
|
||||
// retry interrupt/async errors
|
||||
//
|
||||
do {
|
||||
// abort pathological retry loop
|
||||
//
|
||||
if ( 100 == ++lop_w ) {
|
||||
fprintf(stderr, "rock: write loop: %s\r\n", strerror(errno));
|
||||
close(fid_i);
|
||||
// XX unlink file?
|
||||
//
|
||||
return c3n;
|
||||
}
|
||||
|
||||
ret_i = write(fid_i, byt_y, len_d);
|
||||
}
|
||||
while ( (ret_i < 0)
|
||||
&& ( (errno == EINTR)
|
||||
|| (errno == EAGAIN)
|
||||
|| (errno == EWOULDBLOCK) ));
|
||||
|
||||
// assert on true errors
|
||||
//
|
||||
// NB: can't call u3l_log here or we would re-enter _write()
|
||||
//
|
||||
if ( ret_i < 0 ) {
|
||||
fprintf(stderr, "rock: write failed %s\r\n", strerror(errno));
|
||||
close(fid_i);
|
||||
// XX unlink file?
|
||||
//
|
||||
return c3n;
|
||||
}
|
||||
// continue partial writes
|
||||
//
|
||||
else {
|
||||
len_d -= ret_i;
|
||||
byt_y += ret_i;
|
||||
}
|
||||
}
|
||||
ssize_t rit_i = c3_pwrite(fid_i, byt_y, len_d, 0);
|
||||
if ( rit_i < 0 ) {
|
||||
fprintf(stderr, "rock: write failed: %s\r\n", strerror(errno));
|
||||
}
|
||||
|
||||
close(fid_i);
|
||||
|
||||
return c3y;
|
||||
return rit_i < 0 ? c3n : c3y;
|
||||
}
|
||||
|
||||
/* u3u_cram(): globably deduplicate memory, and write a rock to disk.
|
||||
@ -889,10 +848,6 @@ u3u_uncram(c3_c* dir_c, c3_d eve_d)
|
||||
//
|
||||
u3A->eve_d = eve_d;
|
||||
|
||||
// mark all pages dirty
|
||||
//
|
||||
u3e_foul();
|
||||
|
||||
// leave rocks on disk
|
||||
//
|
||||
// if ( 0 != c3_unlink(nam_c) ) {
|
||||
|
@ -27,9 +27,18 @@ u3v_life(u3_noun eve)
|
||||
c3_o
|
||||
u3v_boot(u3_noun eve)
|
||||
{
|
||||
c3_d len_d;
|
||||
|
||||
{
|
||||
u3_noun len = u3qb_lent(eve);
|
||||
c3_assert( c3y == u3r_safe_chub(len, &len_d) );
|
||||
u3z(len);
|
||||
}
|
||||
|
||||
// ensure zero-initialized kernel
|
||||
//
|
||||
u3A->roc = 0;
|
||||
u3A->roc = 0;
|
||||
u3A->eve_d = 0;
|
||||
|
||||
{
|
||||
u3_noun pro = u3m_soft(0, u3v_life, eve);
|
||||
@ -39,7 +48,8 @@ u3v_boot(u3_noun eve)
|
||||
return c3n;
|
||||
}
|
||||
|
||||
u3A->roc = u3k(u3t(pro));
|
||||
u3A->roc = u3k(u3t(pro));
|
||||
u3A->eve_d = len_d;
|
||||
u3z(pro);
|
||||
}
|
||||
|
||||
@ -260,6 +270,61 @@ u3v_poke(u3_noun ovo)
|
||||
return pro;
|
||||
}
|
||||
|
||||
/* _cv_poke_eve(): u3v_poke w/out u3A->now XX replace
|
||||
*/
|
||||
static u3_noun
|
||||
_cv_poke_eve(u3_noun sam)
|
||||
{
|
||||
u3_noun fun = u3n_nock_on(u3k(u3A->roc), u3k(u3x_at(_CVX_POKE, u3A->roc)));
|
||||
u3_noun pro;
|
||||
|
||||
{
|
||||
# ifdef U3_MEMORY_DEBUG
|
||||
c3_w cod_w = u3a_lush(u3h(u3t(u3t(sam))));
|
||||
# endif
|
||||
|
||||
pro = u3n_slam_on(fun, sam);
|
||||
|
||||
# ifdef U3_MEMORY_DEBUG
|
||||
u3a_lop(cod_w);
|
||||
# endif
|
||||
}
|
||||
|
||||
return pro;
|
||||
}
|
||||
|
||||
/* u3v_poke_sure(): inject an event, saving new state if successful.
|
||||
*/
|
||||
c3_o
|
||||
u3v_poke_sure(c3_w mil_w, u3_noun eve, u3_noun* pro)
|
||||
{
|
||||
u3_noun gon = u3m_soft(mil_w, _cv_poke_eve, eve);
|
||||
u3_noun tag, dat;
|
||||
u3x_cell(gon, &tag, &dat);
|
||||
|
||||
// event failed, produce trace
|
||||
//
|
||||
if ( u3_blip != tag ) {
|
||||
*pro = gon;
|
||||
return c3n;
|
||||
}
|
||||
|
||||
// event succeeded, persist state and produce effects
|
||||
//
|
||||
{
|
||||
u3_noun vir, cor;
|
||||
u3x_cell(dat, &vir, &cor);
|
||||
|
||||
u3z(u3A->roc);
|
||||
u3A->roc = u3k(cor);
|
||||
u3A->eve_d++;
|
||||
|
||||
*pro = u3k(vir);
|
||||
u3z(gon);
|
||||
return c3y;
|
||||
}
|
||||
}
|
||||
|
||||
/* u3v_tank(): dump single tank.
|
||||
*/
|
||||
void
|
||||
|
@ -6,8 +6,7 @@
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
u3m_init(1 << 22);
|
||||
u3m_pave(c3y);
|
||||
u3m_boot_lite(1 << 22);
|
||||
}
|
||||
|
||||
/* _test_ames(): spot check ames helpers
|
||||
|
251
pkg/urbit/tests/events_tests.c
Normal file
251
pkg/urbit/tests/events_tests.c
Normal file
@ -0,0 +1,251 @@
|
||||
#include "all.h"
|
||||
#include "noun/events.h"
|
||||
|
||||
/* _setup(): prepare for tests.
|
||||
*/
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
// NB: no loom
|
||||
//
|
||||
u3P.pag_w = u3a_pages;
|
||||
}
|
||||
|
||||
static c3_w
|
||||
_check_north_clean(void)
|
||||
{
|
||||
c3_w i_w, pag_w, blk_w, bit_w;
|
||||
|
||||
for ( i_w = 0; i_w < u3P.pag_w; i_w++ ) {
|
||||
pag_w = i_w;
|
||||
blk_w = pag_w >> 5;
|
||||
bit_w = pag_w & 31;
|
||||
|
||||
if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i_w;
|
||||
}
|
||||
|
||||
static c3_w
|
||||
_check_north_dirty(c3_w pgs_w, c3_w max_w)
|
||||
{
|
||||
c3_w i_w, pag_w, blk_w, bit_w;
|
||||
|
||||
for ( i_w = 0; i_w < max_w; i_w++ ) {
|
||||
pag_w = i_w + pgs_w;
|
||||
blk_w = pag_w >> 5;
|
||||
bit_w = pag_w & 31;
|
||||
|
||||
if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i_w;
|
||||
}
|
||||
|
||||
static c3_w
|
||||
_check_south_clean(void)
|
||||
{
|
||||
c3_w i_w, pag_w, blk_w, bit_w;
|
||||
|
||||
for ( i_w = 0; i_w < u3P.pag_w; i_w++ ) {
|
||||
pag_w = u3P.pag_w - (i_w + 1);
|
||||
blk_w = pag_w >> 5;
|
||||
bit_w = pag_w & 31;
|
||||
|
||||
if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i_w;
|
||||
}
|
||||
|
||||
static c3_w
|
||||
_check_south_dirty(c3_w pgs_w, c3_w max_w)
|
||||
{
|
||||
c3_w i_w, pag_w, blk_w, bit_w;
|
||||
|
||||
for ( i_w = 0; i_w < max_w; i_w++ ) {
|
||||
pag_w = u3P.pag_w - (i_w + pgs_w + 1);
|
||||
blk_w = pag_w >> 5;
|
||||
bit_w = pag_w & 31;
|
||||
|
||||
if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i_w;
|
||||
}
|
||||
|
||||
void
|
||||
_ce_loom_track_north(c3_w pgs_w, c3_w dif_w);
|
||||
void
|
||||
_ce_loom_track_south(c3_w pgs_w, c3_w dif_w);
|
||||
|
||||
static c3_i
|
||||
_test_tracking(void)
|
||||
{
|
||||
c3_w ret_w;
|
||||
|
||||
_ce_loom_track_north(0, u3P.pag_w);
|
||||
|
||||
if ( u3P.pag_w != (ret_w = _check_north_dirty(0, u3P.pag_w)) ) {
|
||||
fprintf(stderr, "test events track north dirty all %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 0 != (ret_w = _check_north_clean()) ) {
|
||||
fprintf(stderr, "test events track north init %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 0 != (ret_w = _check_south_clean()) ) {
|
||||
fprintf(stderr, "test events track south init %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ce_loom_track_north(100, 0);
|
||||
_ce_loom_track_south(1, 0);
|
||||
|
||||
if ( 100 != (ret_w = _check_north_clean()) ) {
|
||||
fprintf(stderr, "test events track north clean a %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 1 != (ret_w = _check_south_clean()) ) {
|
||||
fprintf(stderr, "test events track south clean a %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ce_loom_track_north(75, 25);
|
||||
_ce_loom_track_south(2, 0);
|
||||
|
||||
if ( 75 != (ret_w = _check_north_clean()) ) {
|
||||
fprintf(stderr, "test events track north clean b %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 25 != (ret_w = _check_north_dirty(75, 25)) ) {
|
||||
fprintf(stderr, "test events track north dirty b %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 2 != (ret_w = _check_south_clean()) ) {
|
||||
fprintf(stderr, "test events track south clean b %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ce_loom_track_north(55, 20);
|
||||
_ce_loom_track_south(1, 1);
|
||||
|
||||
if ( 55 != (ret_w = _check_north_clean()) ) {
|
||||
fprintf(stderr, "test events track north clean c %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 20 != (ret_w = _check_north_dirty(55, 20)) ) {
|
||||
fprintf(stderr, "test events track north dirty c %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 1 != (ret_w = _check_south_clean()) ) {
|
||||
fprintf(stderr, "test events track south clean c %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 1 != (ret_w = _check_south_dirty(1, 1)) ) {
|
||||
fprintf(stderr, "test events track north dirty c %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ce_loom_track_north(255, 0);
|
||||
_ce_loom_track_south(48, 0);
|
||||
|
||||
if ( 255 != (ret_w = _check_north_clean()) ) {
|
||||
fprintf(stderr, "test events track north clean d %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 48 != (ret_w = _check_south_clean()) ) {
|
||||
fprintf(stderr, "test events track south clean d %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ce_loom_track_north(213, 42);
|
||||
_ce_loom_track_south(15, 33);
|
||||
|
||||
if ( 213 != (ret_w = _check_north_clean()) ) {
|
||||
fprintf(stderr, "test events track north clean e %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 42 != (ret_w = _check_north_dirty(213, 42)) ) {
|
||||
fprintf(stderr, "test events track north dirty e %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 15 != (ret_w = _check_south_clean()) ) {
|
||||
fprintf(stderr, "test events track south clean e %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 33 != (ret_w = _check_south_dirty(15, 33)) ) {
|
||||
fprintf(stderr, "test events track north dirty e %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ce_loom_track_north(200, 13);
|
||||
_ce_loom_track_south(10, 5);
|
||||
|
||||
if ( 200 != (ret_w = _check_north_clean()) ) {
|
||||
fprintf(stderr, "test events track north clean f %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 13 != (ret_w = _check_north_dirty(200, 13)) ) {
|
||||
fprintf(stderr, "test events track north dirty f %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 10 != (ret_w = _check_south_clean()) ) {
|
||||
fprintf(stderr, "test events track south clean f %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 5 != (ret_w = _check_south_dirty(10, 5)) ) {
|
||||
fprintf(stderr, "test events track north dirty f %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ce_loom_track_north(0, u3P.pag_w);
|
||||
|
||||
if ( u3P.pag_w != (ret_w = _check_north_dirty(0, u3P.pag_w)) ) {
|
||||
fprintf(stderr, "test events track north dirty all %u\r\n", ret_w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* main(): run all test cases.
|
||||
*/
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
_setup();
|
||||
|
||||
if ( !_test_tracking() ) {
|
||||
fprintf(stderr, "test_events: tracking: failed\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "test_events: ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
@ -9,8 +9,7 @@ c3_w _ch_skip_slot(c3_w mug_w, c3_w lef_w);
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
u3m_init(1 << 26);
|
||||
u3m_pave(c3y);
|
||||
u3m_boot_lite(1 << 26);
|
||||
}
|
||||
|
||||
/* _test_bit_manipulation():
|
||||
|
@ -6,9 +6,7 @@
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
u3m_init(1 << 24);
|
||||
u3m_pave(c3y);
|
||||
u3e_init();
|
||||
u3m_boot_lite(1 << 24);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -5,8 +5,7 @@
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
u3m_init(1 << 20);
|
||||
u3m_pave(c3y);
|
||||
u3m_boot_lite(1 << 20);
|
||||
}
|
||||
|
||||
static inline c3_i
|
||||
|
@ -5,12 +5,7 @@
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
// XX at 1<<24, this succeeds on mac, but bail:exit's on linux.
|
||||
// investigate possible u3n_prog corruption
|
||||
//
|
||||
u3m_init(1 << 25);
|
||||
u3m_pave(c3y);
|
||||
u3e_init();
|
||||
u3m_boot_lite(1 << 24);
|
||||
}
|
||||
|
||||
static u3_noun
|
||||
@ -53,7 +48,7 @@ _test_nock_meme(void)
|
||||
}
|
||||
|
||||
static c3_i
|
||||
_test_nock(void)
|
||||
_test_meme(void)
|
||||
{
|
||||
c3_i ret_i = 1;
|
||||
|
||||
@ -72,8 +67,8 @@ main(int argc, char* argv[])
|
||||
{
|
||||
_setup();
|
||||
|
||||
if ( !_test_nock() ) {
|
||||
fprintf(stderr, "test nock: failed\r\n");
|
||||
if ( !_test_meme() ) {
|
||||
fprintf(stderr, "test meme: failed\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -81,6 +76,6 @@ main(int argc, char* argv[])
|
||||
//
|
||||
u3m_grab(u3_none);
|
||||
|
||||
fprintf(stderr, "test nock: ok\r\n");
|
||||
fprintf(stderr, "test meme: ok\r\n");
|
||||
return 0;
|
||||
}
|
@ -5,8 +5,7 @@
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
u3m_init(1 << 20);
|
||||
u3m_pave(c3y);
|
||||
u3m_boot_lite(1 << 20);
|
||||
}
|
||||
|
||||
/* _test_mug(): spot check u3r_mug hashes.
|
||||
|
@ -6,8 +6,7 @@
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
u3m_init(1 << 20);
|
||||
u3m_pave(c3y);
|
||||
u3m_boot_lite(1 << 20);
|
||||
}
|
||||
|
||||
/* _newt_encode(): synchronous serialization into a single buffer, for test purposes
|
||||
|
@ -8,8 +8,7 @@
|
||||
static void
|
||||
_setup(void)
|
||||
{
|
||||
u3m_init(1 << 20);
|
||||
u3m_pave(c3y);
|
||||
u3m_boot_lite(1 << 20);
|
||||
}
|
||||
|
||||
/* _test_u3r_chop: "extract bit slices from atom"
|
||||
|
@ -225,6 +225,112 @@ u3_lmdb_gulf(MDB_env* env_u, c3_d* low_d, c3_d* hig_d)
|
||||
}
|
||||
}
|
||||
|
||||
/* u3_lmdb_walk_init(): initialize db iterator.
|
||||
*/
|
||||
c3_o
|
||||
u3_lmdb_walk_init(MDB_env* env_u,
|
||||
u3_lmdb_walk* itr_u,
|
||||
c3_d nex_d,
|
||||
c3_d las_d)
|
||||
{
|
||||
// XX assumes little-endian
|
||||
//
|
||||
MDB_val key_u = { .mv_size = sizeof(c3_d), .mv_data = &nex_d };
|
||||
MDB_val val_u;
|
||||
c3_w ops_w, ret_w;
|
||||
|
||||
itr_u->red_o = c3n;
|
||||
itr_u->nex_d = nex_d;
|
||||
itr_u->las_d = las_d;
|
||||
|
||||
// create a read-only transaction.
|
||||
//
|
||||
ops_w = MDB_RDONLY;
|
||||
if ( (ret_w = mdb_txn_begin(env_u, 0, ops_w, &itr_u->txn_u)) ) {
|
||||
mdb_logerror(stderr, ret_w, "lmdb: read txn_begin fail");
|
||||
return c3n;
|
||||
}
|
||||
// open the database in the transaction
|
||||
//
|
||||
ops_w = MDB_CREATE | MDB_INTEGERKEY;
|
||||
if ( (ret_w = mdb_dbi_open(itr_u->txn_u, "EVENTS", ops_w, &itr_u->mdb_u)) ) {
|
||||
mdb_logerror(stderr, ret_w, "lmdb: read: dbi_open fail");
|
||||
// XX confirm
|
||||
//
|
||||
mdb_txn_abort(itr_u->txn_u);
|
||||
return c3n;
|
||||
}
|
||||
|
||||
// creates a cursor to iterate over keys starting at [eve_d]
|
||||
//
|
||||
if ( (ret_w = mdb_cursor_open(itr_u->txn_u, itr_u->mdb_u, &itr_u->cur_u)) ) {
|
||||
mdb_logerror(stderr, ret_w, "lmdb: read: cursor_open fail");
|
||||
// XX confirm
|
||||
//
|
||||
mdb_txn_abort(itr_u->txn_u);
|
||||
return c3n;
|
||||
}
|
||||
|
||||
// set the cursor to the position of [eve_d]
|
||||
//
|
||||
ops_w = MDB_SET_KEY;
|
||||
if ( (ret_w = mdb_cursor_get(itr_u->cur_u, &key_u, &val_u, ops_w)) ) {
|
||||
mdb_logerror(stderr, ret_w, "lmdb: read: initial cursor_get failed");
|
||||
fprintf(stderr, " at %" PRIu64 "\r\n", nex_d);
|
||||
mdb_cursor_close(itr_u->cur_u);
|
||||
// XX confirm
|
||||
//
|
||||
mdb_txn_abort(itr_u->txn_u);
|
||||
return c3n;
|
||||
}
|
||||
|
||||
return c3y;
|
||||
}
|
||||
|
||||
/* u3_lmdb_walk_next(): synchronously read next event from iterator.
|
||||
*/
|
||||
c3_o
|
||||
u3_lmdb_walk_next(u3_lmdb_walk* itr_u, size_t* len_i, void** buf_v)
|
||||
{
|
||||
MDB_val key_u, val_u;
|
||||
c3_w ret_w, ops_w;
|
||||
|
||||
c3_assert( itr_u->nex_d <= itr_u->las_d );
|
||||
|
||||
ops_w = ( c3y == itr_u->red_o ) ? MDB_NEXT : MDB_GET_CURRENT;
|
||||
if ( (ret_w = mdb_cursor_get(itr_u->cur_u, &key_u, &val_u, ops_w)) ) {
|
||||
mdb_logerror(stderr, ret_w, "lmdb: walk error");
|
||||
return c3n;
|
||||
}
|
||||
|
||||
// sanity check: ensure contiguous event numbers
|
||||
//
|
||||
if ( *(c3_d*)key_u.mv_data != itr_u->nex_d ) {
|
||||
fprintf(stderr, "lmdb: read gap: expected %" PRIu64
|
||||
", received %" PRIu64 "\r\n",
|
||||
itr_u->nex_d,
|
||||
*(c3_d*)key_u.mv_data);
|
||||
return c3n;
|
||||
}
|
||||
|
||||
*len_i = val_u.mv_size;
|
||||
*buf_v = val_u.mv_data;
|
||||
|
||||
itr_u->nex_d++;
|
||||
itr_u->red_o = c3y;
|
||||
|
||||
return c3y;
|
||||
}
|
||||
|
||||
/* u3_lmdb_walk_done(): close iterator.
|
||||
*/
|
||||
void
|
||||
u3_lmdb_walk_done(u3_lmdb_walk* itr_u)
|
||||
{
|
||||
mdb_cursor_close(itr_u->cur_u);
|
||||
mdb_txn_abort(itr_u->txn_u);
|
||||
}
|
||||
|
||||
/* u3_lmdb_read(): read [len_d] events starting at [eve_d].
|
||||
*/
|
||||
c3_o
|
||||
|
@ -22,6 +22,12 @@ struct _cd_save {
|
||||
struct _u3_disk* log_u;
|
||||
};
|
||||
|
||||
struct _u3_disk_walk {
|
||||
u3_lmdb_walk itr_u;
|
||||
u3_disk* log_u;
|
||||
c3_o liv_o;
|
||||
};
|
||||
|
||||
#undef VERBOSE_DISK
|
||||
#undef DISK_TRACE_JAM
|
||||
#undef DISK_TRACE_CUE
|
||||
@ -149,34 +155,47 @@ _disk_commit_start(struct _cd_save* req_u)
|
||||
_disk_commit_after_cb);
|
||||
}
|
||||
|
||||
/* _disk_serialize_v1(): serialize events in format v1.
|
||||
|
||||
/* u3_disk_etch(): serialize an event for persistence. RETAIN [eve]
|
||||
*/
|
||||
static c3_w
|
||||
_disk_serialize_v1(u3_fact* tac_u, c3_y** out_y)
|
||||
size_t
|
||||
u3_disk_etch(u3_disk* log_u,
|
||||
u3_noun eve,
|
||||
c3_l mug_l,
|
||||
c3_y** out_y)
|
||||
{
|
||||
size_t len_i;
|
||||
c3_y* dat_y;
|
||||
|
||||
#ifdef DISK_TRACE_JAM
|
||||
u3t_event_trace("king disk jam", 'B');
|
||||
u3t_event_trace("disk etch", 'B');
|
||||
#endif
|
||||
|
||||
// XX check version number in log_u
|
||||
// XX needs api redesign to limit allocations
|
||||
//
|
||||
{
|
||||
u3_atom mat = u3qe_jam(tac_u->job);
|
||||
u3_atom mat = u3qe_jam(eve);
|
||||
c3_w len_w = u3r_met(3, mat);
|
||||
c3_y* dat_y = c3_malloc(4 + len_w);
|
||||
dat_y[0] = tac_u->mug_l & 0xff;
|
||||
dat_y[1] = (tac_u->mug_l >> 8) & 0xff;
|
||||
dat_y[2] = (tac_u->mug_l >> 16) & 0xff;
|
||||
dat_y[3] = (tac_u->mug_l >> 24) & 0xff;
|
||||
|
||||
len_i = 4 + len_w;
|
||||
dat_y = c3_malloc(len_i);
|
||||
|
||||
dat_y[0] = mug_l & 0xff;
|
||||
dat_y[1] = (mug_l >> 8) & 0xff;
|
||||
dat_y[2] = (mug_l >> 16) & 0xff;
|
||||
dat_y[3] = (mug_l >> 24) & 0xff;
|
||||
u3r_bytes(0, len_w, dat_y + 4, mat);
|
||||
|
||||
u3z(mat);
|
||||
}
|
||||
|
||||
#ifdef DISK_TRACE_JAM
|
||||
u3t_event_trace("king disk jam", 'E');
|
||||
u3t_event_trace("disk etch", 'E');
|
||||
#endif
|
||||
|
||||
u3z(mat);
|
||||
|
||||
*out_y = dat_y;
|
||||
return len_w + 4;
|
||||
}
|
||||
*out_y = dat_y;
|
||||
return len_i;
|
||||
}
|
||||
|
||||
/* _disk_batch(): create a write batch
|
||||
@ -200,7 +219,8 @@ _disk_batch(u3_disk* log_u, c3_d len_d)
|
||||
for ( c3_d i_d = 0ULL; i_d < len_d; ++i_d) {
|
||||
c3_assert( (req_u->eve_d + i_d) == tac_u->eve_d );
|
||||
|
||||
req_u->siz_i[i_d] = _disk_serialize_v1(tac_u, &req_u->byt_y[i_d]);
|
||||
req_u->siz_i[i_d] = u3_disk_etch(log_u, tac_u->job,
|
||||
tac_u->mug_l, &req_u->byt_y[i_d]);
|
||||
|
||||
tac_u = tac_u->nex_u;
|
||||
}
|
||||
@ -358,6 +378,41 @@ _disk_read_done_cb(uv_timer_t* tim_u)
|
||||
_disk_read_close(red_u);
|
||||
}
|
||||
|
||||
/* u3_disk_sift(): parse a persisted event buffer.
|
||||
*/
|
||||
c3_o
|
||||
u3_disk_sift(u3_disk* log_u,
|
||||
size_t len_i,
|
||||
c3_y* dat_y,
|
||||
c3_l* mug_l,
|
||||
u3_noun* job)
|
||||
{
|
||||
if ( 4 >= len_i ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
#ifdef DISK_TRACE_CUE
|
||||
u3t_event_trace("disk sift", 'B');
|
||||
#endif
|
||||
|
||||
// XX check version in log_u
|
||||
//
|
||||
*mug_l = dat_y[0]
|
||||
^ (dat_y[1] << 8)
|
||||
^ (dat_y[2] << 16)
|
||||
^ (dat_y[3] << 24);
|
||||
|
||||
// XX u3m_soft?
|
||||
//
|
||||
*job = u3ke_cue(u3i_bytes(len_i - 4, dat_y + 4));
|
||||
|
||||
#ifdef DISK_TRACE_CUE
|
||||
u3t_event_trace("disk sift", 'E');
|
||||
#endif
|
||||
|
||||
return c3y;
|
||||
}
|
||||
|
||||
/* _disk_read_one_cb(): lmdb read callback, invoked for each event in order
|
||||
*/
|
||||
static c3_o
|
||||
@ -367,29 +422,13 @@ _disk_read_one_cb(void* ptr_v, c3_d eve_d, size_t val_i, void* val_p)
|
||||
u3_disk* log_u = red_u->log_u;
|
||||
u3_fact* tac_u;
|
||||
|
||||
if ( 4 >= val_i ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
{
|
||||
u3_noun job;
|
||||
c3_y* dat_y = val_p;
|
||||
c3_l mug_l = dat_y[0]
|
||||
^ (dat_y[1] << 8)
|
||||
^ (dat_y[2] << 16)
|
||||
^ (dat_y[3] << 24);
|
||||
c3_l mug_l;
|
||||
|
||||
#ifdef DISK_TRACE_CUE
|
||||
u3t_event_trace("king disk cue", 'B');
|
||||
#endif
|
||||
|
||||
// XX u3m_soft?
|
||||
//
|
||||
job = u3ke_cue(u3i_bytes(val_i - 4, dat_y + 4));
|
||||
|
||||
#ifdef DISK_TRACE_CUE
|
||||
u3t_event_trace("king disk cue", 'E');
|
||||
#endif
|
||||
if ( c3n == u3_disk_sift(log_u, val_i, (c3_y*)val_p, &mug_l, &job) ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
tac_u = u3_fact_init(eve_d, mug_l, job);
|
||||
}
|
||||
@ -461,6 +500,120 @@ u3_disk_read(u3_disk* log_u, c3_d eve_d, c3_d len_d)
|
||||
uv_timer_start(&red_u->tim_u, _disk_read_start_cb, 0, 0);
|
||||
}
|
||||
|
||||
struct _cd_list {
|
||||
u3_disk* log_u;
|
||||
u3_noun eve;
|
||||
c3_l mug_l;
|
||||
};
|
||||
|
||||
/* _disk_read_list_cb(): lmdb read callback, invoked for each event in order
|
||||
*/
|
||||
static c3_o
|
||||
_disk_read_list_cb(void* ptr_v, c3_d eve_d, size_t val_i, void* val_p)
|
||||
{
|
||||
struct _cd_list* ven_u = ptr_v;
|
||||
u3_disk* log_u = ven_u->log_u;
|
||||
|
||||
{
|
||||
u3_noun job;
|
||||
c3_l mug_l;
|
||||
|
||||
if ( c3n == u3_disk_sift(log_u, val_i, (c3_y*)val_p, &mug_l, &job) ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
ven_u->mug_l = mug_l;
|
||||
ven_u->eve = u3nc(job, ven_u->eve);
|
||||
}
|
||||
|
||||
return c3y;
|
||||
}
|
||||
|
||||
/* u3_disk_read_list(): synchronously read a cons list of events.
|
||||
*/
|
||||
u3_weak
|
||||
u3_disk_read_list(u3_disk* log_u, c3_d eve_d, c3_d len_d, c3_l* mug_l)
|
||||
{
|
||||
struct _cd_list ven_u = { log_u, u3_nul, 0 };
|
||||
|
||||
if ( c3n == u3_lmdb_read(log_u->mdb_u, &ven_u,
|
||||
eve_d, len_d, _disk_read_list_cb) )
|
||||
{
|
||||
return u3_none;
|
||||
}
|
||||
|
||||
*mug_l = ven_u.mug_l;
|
||||
return u3kb_flop(ven_u.eve);
|
||||
}
|
||||
|
||||
/* u3_disk_walk_init(): init iterator.
|
||||
*/
|
||||
u3_disk_walk*
|
||||
u3_disk_walk_init(u3_disk* log_u,
|
||||
c3_d eve_d,
|
||||
c3_d len_d)
|
||||
{
|
||||
u3_disk_walk* wok_u = c3_malloc(sizeof(*wok_u));
|
||||
c3_d max_d = eve_d + len_d - 1;
|
||||
|
||||
wok_u->log_u = log_u;
|
||||
wok_u->liv_o = u3_lmdb_walk_init(log_u->mdb_u,
|
||||
&wok_u->itr_u,
|
||||
eve_d,
|
||||
c3_min(max_d, log_u->dun_d));
|
||||
|
||||
return wok_u;
|
||||
}
|
||||
|
||||
/* u3_disk_walk_live(): check if live.
|
||||
*/
|
||||
c3_o
|
||||
u3_disk_walk_live(u3_disk_walk* wok_u)
|
||||
{
|
||||
if ( wok_u->itr_u.nex_d > wok_u->itr_u.las_d ) {
|
||||
wok_u->liv_o = c3n;
|
||||
}
|
||||
|
||||
return wok_u->liv_o;
|
||||
}
|
||||
|
||||
/* u3_disk_walk_step(): get next fact.
|
||||
*/
|
||||
c3_o
|
||||
u3_disk_walk_step(u3_disk_walk* wok_u, u3_fact* tac_u)
|
||||
{
|
||||
u3_disk* log_u = wok_u->log_u;
|
||||
size_t len_i;
|
||||
void* buf_v;
|
||||
|
||||
tac_u->eve_d = wok_u->itr_u.nex_d;
|
||||
|
||||
if ( c3n == u3_lmdb_walk_next(&wok_u->itr_u, &len_i, &buf_v) ) {
|
||||
fprintf(stderr, "disk: (%" PRIu64 "): read fail\r\n", tac_u->eve_d);
|
||||
return wok_u->liv_o = c3n;
|
||||
}
|
||||
|
||||
if ( c3n == u3_disk_sift(log_u, len_i,
|
||||
(c3_y*)buf_v,
|
||||
&tac_u->mug_l,
|
||||
&tac_u->job) )
|
||||
{
|
||||
fprintf(stderr, "disk: (%" PRIu64 "): sift fail\r\n", tac_u->eve_d);
|
||||
return wok_u->liv_o = c3n;
|
||||
}
|
||||
|
||||
return c3y;
|
||||
}
|
||||
|
||||
/* u3_disk_walk_done(): close iterator.
|
||||
*/
|
||||
void
|
||||
u3_disk_walk_done(u3_disk_walk* wok_u)
|
||||
{
|
||||
u3_lmdb_walk_done(&wok_u->itr_u);
|
||||
c3_free(wok_u);
|
||||
}
|
||||
|
||||
/* _disk_save_meta(): serialize atom, save as metadata at [key_c].
|
||||
*/
|
||||
static c3_o
|
||||
|
@ -1504,6 +1504,61 @@ _http_serv_init_h2o(SSL_CTX* tls_u, c3_o log, c3_o red)
|
||||
return h2o_u;
|
||||
}
|
||||
|
||||
/* _http_serv_start_err(): handle errors in starting http server.
|
||||
*/
|
||||
static c3_i
|
||||
_http_serv_start_err(const c3_c* cap_c, u3_http* htp_u, c3_i sas_i)
|
||||
{
|
||||
u3_pier* pir_u = htp_u->htd_u->car_u.pir_u;
|
||||
|
||||
if ( UV_EADDRNOTAVAIL == sas_i ) {
|
||||
u3l_log("http: unavailable ip address %s\r\n", u3_Host.ops_u.bin_c);
|
||||
u3_king_bail();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ports specified, no incrementing/retry
|
||||
//
|
||||
if ( c3y == htp_u->dis ) {
|
||||
u3l_log("http: %s (%" PRIu16 "): %s\n",
|
||||
cap_c, htp_u->por_s, uv_strerror(sas_i));
|
||||
u3_king_bail();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// increment and retry
|
||||
//
|
||||
if ( (UV_EADDRINUSE == sas_i) || (UV_EACCES == sas_i) ) {
|
||||
if ( (c3y == htp_u->sec) && (443 == htp_u->por_s) ) {
|
||||
htp_u->por_s = 8443;
|
||||
}
|
||||
else if ( (c3n == htp_u->sec) && (80 == htp_u->por_s) ) {
|
||||
htp_u->por_s = 8080;
|
||||
}
|
||||
else {
|
||||
htp_u->por_s++;
|
||||
// XX
|
||||
//
|
||||
if ( c3n == htp_u->lop ) {
|
||||
if ( c3y == htp_u->sec ) {
|
||||
pir_u->pes_s = htp_u->por_s;
|
||||
}
|
||||
else {
|
||||
pir_u->per_s = htp_u->por_s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// total failure XX bail?
|
||||
//
|
||||
u3l_log("http: %s: %s\n", cap_c, uv_strerror(sas_i));
|
||||
_http_serv_free(htp_u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* _http_serv_start(): start http server.
|
||||
*/
|
||||
static void
|
||||
@ -1519,10 +1574,12 @@ _http_serv_start(u3_http* htp_u)
|
||||
INADDR_ANY;
|
||||
|
||||
if ( 0 != u3_Host.ops_u.bin_c && c3n == htp_u->lop ) {
|
||||
// already validated in arguments parser
|
||||
//
|
||||
inet_pton(AF_INET, u3_Host.ops_u.bin_c, &adr_u.sin_addr);
|
||||
}
|
||||
|
||||
uv_tcp_init(u3L, &htp_u->wax_u);
|
||||
c3_assert( !uv_tcp_init(u3L, &htp_u->wax_u) );
|
||||
|
||||
/* Try ascending ports.
|
||||
*/
|
||||
@ -1532,46 +1589,25 @@ _http_serv_start(u3_http* htp_u)
|
||||
adr_u.sin_port = htons(htp_u->por_s);
|
||||
|
||||
if ( 0 != (sas_i = uv_tcp_bind(&htp_u->wax_u,
|
||||
(const struct sockaddr*)&adr_u, 0)) ||
|
||||
0 != (sas_i = uv_listen((uv_stream_t*)&htp_u->wax_u,
|
||||
TCP_BACKLOG, _http_serv_listen_cb)) ) {
|
||||
if ( UV_EADDRNOTAVAIL == sas_i ) {
|
||||
u3l_log("http: ip address not available\n");
|
||||
u3_king_bail();
|
||||
}
|
||||
if ( c3y == htp_u->dis ) {
|
||||
u3l_log("http: listen (%" PRIu16 "): %s\n", htp_u->por_s,
|
||||
uv_strerror(sas_i));
|
||||
u3_king_bail();
|
||||
}
|
||||
if ( (UV_EADDRINUSE == sas_i) || (UV_EACCES == sas_i) ) {
|
||||
if ( (c3y == htp_u->sec) && (443 == htp_u->por_s) ) {
|
||||
htp_u->por_s = 8443;
|
||||
}
|
||||
else if ( (c3n == htp_u->sec) && (80 == htp_u->por_s) ) {
|
||||
htp_u->por_s = 8080;
|
||||
}
|
||||
else {
|
||||
htp_u->por_s++;
|
||||
// XX
|
||||
//
|
||||
if ( c3n == htp_u->lop ) {
|
||||
if ( c3y == htp_u->sec ) {
|
||||
pir_u->pes_s = htp_u->por_s;
|
||||
}
|
||||
else {
|
||||
pir_u->per_s = htp_u->por_s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(const struct sockaddr*)&adr_u, 0)) )
|
||||
{
|
||||
if ( _http_serv_start_err("bind", htp_u, sas_i) ) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u3l_log("http: listen: %s\n", uv_strerror(sas_i));
|
||||
|
||||
_http_serv_free(htp_u);
|
||||
return;
|
||||
if ( 0 != (sas_i = uv_listen((uv_stream_t*)&htp_u->wax_u,
|
||||
TCP_BACKLOG, _http_serv_listen_cb)) )
|
||||
{
|
||||
if ( _http_serv_start_err("listen", htp_u, sas_i) ) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u3l_log("http: %s live on %s://localhost:%d\n",
|
||||
@ -1677,24 +1713,30 @@ _http_init_tls(uv_buf_t key_u, uv_buf_t cer_u)
|
||||
static void
|
||||
_http_write_ports_file(u3_httd* htd_u, c3_c *pax_c)
|
||||
{
|
||||
c3_c* nam_c = ".http.ports";
|
||||
c3_w len_w = 1 + strlen(pax_c) + 1 + strlen(nam_c);
|
||||
|
||||
c3_c* paf_c = c3_malloc(len_w);
|
||||
snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c);
|
||||
|
||||
c3_i por_i = c3_open(paf_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
c3_free(paf_c);
|
||||
|
||||
u3_http* htp_u = htd_u->htp_u;
|
||||
u3_pier* pir_u = htd_u->car_u.pir_u;
|
||||
size_t off_i = 0;
|
||||
c3_i por_i;
|
||||
|
||||
{
|
||||
c3_c* nam_c = ".http.ports";
|
||||
c3_w len_w = 1 + strlen(pax_c) + 1 + strlen(nam_c);
|
||||
c3_c* paf_c = c3_malloc(len_w);
|
||||
snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c);
|
||||
por_i = c3_open(paf_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
c3_free(paf_c);
|
||||
}
|
||||
|
||||
c3_c temp[32];
|
||||
while ( 0 != htp_u ) {
|
||||
if ( 0 < htp_u->por_s ) {
|
||||
u3_write_fd(por_i, temp, snprintf(temp, 32, "%u %s %s\n", htp_u->por_s,
|
||||
(c3y == htp_u->sec) ? "secure" : "insecure",
|
||||
(c3y == htp_u->lop) ? "loopback" : "public"));
|
||||
c3_c tmp_c[32];
|
||||
c3_i len_i = snprintf(tmp_c, 32, "%u %s %s\n",
|
||||
htp_u->por_s,
|
||||
(c3y == htp_u->sec) ? "secure" : "insecure",
|
||||
(c3y == htp_u->lop) ? "loopback" : "public");
|
||||
c3_assert( 0 < len_i);
|
||||
c3_assert( c3_pwrite(por_i, tmp_c, len_i, off_i) == len_i );
|
||||
off_i += len_i;
|
||||
}
|
||||
|
||||
htp_u = htp_u->nex_u;
|
||||
@ -1710,13 +1752,12 @@ static void
|
||||
_http_release_ports_file(c3_c *pax_c)
|
||||
{
|
||||
c3_c* nam_c = ".http.ports";
|
||||
c3_w len_w = 1 + strlen(pax_c) + 1 + strlen(nam_c);
|
||||
c3_w len_w = 1 + strlen(pax_c) + 1 + strlen(nam_c);
|
||||
c3_c* paf_c = c3_malloc(len_w);
|
||||
c3_i wit_i;
|
||||
|
||||
wit_i = snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c);
|
||||
c3_assert(wit_i > 0);
|
||||
c3_assert(len_w == (c3_w)wit_i + 1);
|
||||
c3_assert( len_w == (c3_w)wit_i + 1 );
|
||||
|
||||
c3_unlink(paf_c);
|
||||
c3_free(paf_c);
|
||||
|
@ -17,48 +17,6 @@ static void _term_read_cb(uv_stream_t* tcp_u,
|
||||
ssize_t siz_i,
|
||||
const uv_buf_t* buf_u);
|
||||
|
||||
/* u3_write_fd(): retry interrupts, continue partial writes, assert errors.
|
||||
*/
|
||||
void
|
||||
u3_write_fd(c3_i fid_i, const void* buf_v, size_t len_i)
|
||||
{
|
||||
ssize_t ret_i;
|
||||
|
||||
while ( len_i > 0 ) {
|
||||
c3_w lop_w = 0;
|
||||
// retry interrupt/async errors
|
||||
//
|
||||
do {
|
||||
// abort pathological retry loop
|
||||
//
|
||||
if ( 100 == ++lop_w ) {
|
||||
fprintf(stderr, "term: write loop: %s\r\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
ret_i = write(fid_i, buf_v, len_i);
|
||||
}
|
||||
while ( (ret_i < 0)
|
||||
&& ( (errno == EINTR)
|
||||
|| (errno == EAGAIN)
|
||||
|| (errno == EWOULDBLOCK) ));
|
||||
|
||||
// assert on true errors
|
||||
//
|
||||
// NB: can't call u3l_log here or we would re-enter u3_write_fd()
|
||||
//
|
||||
if ( ret_i < 0 ) {
|
||||
fprintf(stderr, "term: write failed %s\r\n", strerror(errno));
|
||||
c3_assert(0);
|
||||
}
|
||||
// continue partial writes
|
||||
//
|
||||
else {
|
||||
len_i -= ret_i;
|
||||
buf_v += ret_i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* _term_msc_out_host(): unix microseconds from current host time.
|
||||
*/
|
||||
static c3_d
|
||||
@ -255,7 +213,7 @@ u3_term_log_exit(void)
|
||||
if ( c3n == uty_u->sto_f(uty_u) ) {
|
||||
c3_assert(!"exit-tcsetattr");
|
||||
}
|
||||
u3_write_fd(uty_u->fid_i, "\r\n", 2);
|
||||
c3_assert(c3_write(uty_u->fid_i, "\r\n", 2) == 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -864,7 +822,7 @@ _term_spin_step(u3_utty* uty_u)
|
||||
c3_w i_w;
|
||||
|
||||
for ( i_w = bac_w; i_w < sol_w; i_w++ ) {
|
||||
if ( lef_u.len != write(fid_i, lef_u.base, lef_u.len) ) {
|
||||
if ( c3_write(fid_i, lef_u.base, lef_u.len) < 0 ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -874,7 +832,7 @@ _term_spin_step(u3_utty* uty_u)
|
||||
|
||||
{
|
||||
c3_w len_w = cur_c - buf_c;
|
||||
if ( len_w != write(fid_i, buf_c, len_w) ) {
|
||||
if ( c3_write(fid_i, buf_c, len_w) < 0 ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -882,7 +840,7 @@ _term_spin_step(u3_utty* uty_u)
|
||||
// Cursor stays on spinner.
|
||||
//
|
||||
while ( sol_w-- ) {
|
||||
if ( lef_u.len != write(fid_i, lef_u.base, lef_u.len) ) {
|
||||
if ( c3_write(fid_i, lef_u.base, lef_u.len) < 0 ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1044,7 +1002,9 @@ u3_term_ef_ctlc(void)
|
||||
_term_ovum_plan(uty_u->car_u, wir, cad);
|
||||
}
|
||||
|
||||
_term_it_refresh_line(uty_u);
|
||||
if ( c3n == u3_Host.ops_u.tem ) {
|
||||
_term_it_refresh_line(uty_u);
|
||||
}
|
||||
}
|
||||
|
||||
/* _term_it_put_value(): put numeric color value on lin_w.
|
||||
@ -1382,10 +1342,10 @@ u3_term_io_hija(void)
|
||||
if ( c3y != uty_u->hij_f(uty_u) ) {
|
||||
c3_assert(!"hija-tcsetattr");
|
||||
}
|
||||
u3_write_fd(uty_u->fid_i, "\r", 1);
|
||||
c3_assert(c3_write(uty_u->fid_i, "\r", 1) == 1);
|
||||
{
|
||||
uv_buf_t* buf_u = &uty_u->ufo_u.out.el_u;
|
||||
u3_write_fd(uty_u->fid_i, buf_u->base, buf_u->len);
|
||||
c3_assert(c3_write(uty_u->fid_i, buf_u->base, buf_u->len) == buf_u->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,11 +342,11 @@ u3_unix_save(c3_c* pax_c, u3_atom pad)
|
||||
pad_y = c3_malloc(fln_w);
|
||||
u3r_bytes(0, fln_w, pad_y, pad);
|
||||
u3z(pad);
|
||||
rit_w = write(fid_i, pad_y, fln_w);
|
||||
ssize_t rit_i = c3_pwrite(fid_i, pad_y, fln_w, 0);
|
||||
close(fid_i);
|
||||
c3_free(pad_y);
|
||||
|
||||
if ( rit_w != fln_w ) {
|
||||
if ( rit_i < 0 ) {
|
||||
u3l_log("%s: %s\n", ful_c, strerror(errno));
|
||||
c3_free(ful_c);
|
||||
u3m_bail(c3__fail);
|
||||
@ -427,7 +427,7 @@ static c3_w
|
||||
_unix_write_file_hard(c3_c* pax_c, u3_noun mim)
|
||||
{
|
||||
c3_i fid_i = c3_open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
c3_w len_w, rit_w, siz_w, mug_w = 0;
|
||||
c3_w len_w, siz_w, mug_w = 0;
|
||||
c3_y* dat_y;
|
||||
|
||||
u3_noun dat = u3t(u3t(mim));
|
||||
@ -446,11 +446,10 @@ _unix_write_file_hard(c3_c* pax_c, u3_noun mim)
|
||||
u3r_bytes(0, len_w, dat_y, dat);
|
||||
u3z(mim);
|
||||
|
||||
rit_w = write(fid_i, dat_y, siz_w);
|
||||
ssize_t rit_i = c3_pwrite(fid_i, dat_y, siz_w, 0);
|
||||
|
||||
if ( rit_w != siz_w ) {
|
||||
u3l_log("error writing %s: %s\r\n",
|
||||
pax_c, strerror(errno));
|
||||
if ( rit_i < 0 ) {
|
||||
u3l_log("error writing %s: %s\r\n", pax_c, strerror(errno));
|
||||
mug_w = 0;
|
||||
}
|
||||
else {
|
||||
@ -470,7 +469,7 @@ _unix_write_file_soft(u3_ufil* fil_u, u3_noun mim)
|
||||
{
|
||||
struct stat buf_u;
|
||||
c3_i fid_i = c3_open(fil_u->pax_c, O_RDONLY, 0644);
|
||||
c3_ws len_ws, red_ws;
|
||||
c3_ws len_ws;
|
||||
c3_w old_w;
|
||||
c3_y* old_y;
|
||||
|
||||
@ -489,21 +488,21 @@ _unix_write_file_soft(u3_ufil* fil_u, u3_noun mim)
|
||||
len_ws = buf_u.st_size;
|
||||
old_y = c3_malloc(len_ws);
|
||||
|
||||
red_ws = read(fid_i, old_y, len_ws);
|
||||
ssize_t red_i = c3_pread(fid_i, old_y, len_ws, 0);
|
||||
|
||||
if ( close(fid_i) < 0 ) {
|
||||
u3l_log("error closing file (soft) %s: %s\r\n",
|
||||
fil_u->pax_c, strerror(errno));
|
||||
}
|
||||
|
||||
if ( len_ws != red_ws ) {
|
||||
if ( red_ws < 0 ) {
|
||||
if ( red_i != len_ws ) {
|
||||
if ( red_i < 0 ) {
|
||||
u3l_log("error reading file (soft) %s: %s\r\n",
|
||||
fil_u->pax_c, strerror(errno));
|
||||
fil_u->pax_c, strerror(-red_i));
|
||||
}
|
||||
else {
|
||||
u3l_log("wrong # of bytes read in file %s: %d %d\r\n",
|
||||
fil_u->pax_c, len_ws, red_ws);
|
||||
u3l_log("wrong # of bytes read in file %s: %u %zu\r\n",
|
||||
fil_u->pax_c, len_ws, red_i);
|
||||
}
|
||||
c3_free(old_y);
|
||||
u3z(mim);
|
||||
@ -893,7 +892,7 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u)
|
||||
|
||||
struct stat buf_u;
|
||||
c3_i fid_i = c3_open(fil_u->pax_c, O_RDONLY, 0644);
|
||||
c3_ws len_ws, red_ws;
|
||||
c3_ws len_ws;
|
||||
c3_y* dat_y;
|
||||
|
||||
if ( fid_i < 0 || fstat(fid_i, &buf_u) < 0 ) {
|
||||
@ -910,21 +909,21 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u)
|
||||
len_ws = buf_u.st_size;
|
||||
dat_y = c3_malloc(len_ws);
|
||||
|
||||
red_ws = read(fid_i, dat_y, len_ws);
|
||||
ssize_t red_i = c3_pread(fid_i, dat_y, len_ws, 0);
|
||||
|
||||
if ( close(fid_i) < 0 ) {
|
||||
u3l_log("error closing file %s: %s\r\n",
|
||||
fil_u->pax_c, strerror(errno));
|
||||
}
|
||||
|
||||
if ( len_ws != red_ws ) {
|
||||
if ( red_ws < 0 ) {
|
||||
if ( red_i != len_ws ) {
|
||||
if ( red_i < 0 ) {
|
||||
u3l_log("error reading file %s: %s\r\n",
|
||||
fil_u->pax_c, strerror(errno));
|
||||
fil_u->pax_c, strerror(-red_i));
|
||||
}
|
||||
else {
|
||||
u3l_log("wrong # of bytes read in file %s: %d %d\r\n",
|
||||
fil_u->pax_c, len_ws, red_ws);
|
||||
u3l_log("wrong # of bytes read in file %s: %u %zu\r\n",
|
||||
fil_u->pax_c, len_ws, red_i);
|
||||
}
|
||||
c3_free(dat_y);
|
||||
return u3_nul;
|
||||
@ -1159,7 +1158,7 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c)
|
||||
{
|
||||
struct stat buf_u;
|
||||
c3_i fid_i = c3_open(pax_c, O_RDONLY, 0644);
|
||||
c3_ws len_ws, red_ws;
|
||||
c3_ws len_ws;
|
||||
c3_y* dat_y;
|
||||
|
||||
if ( fid_i < 0 || fstat(fid_i, &buf_u) < 0 ) {
|
||||
@ -1176,21 +1175,21 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c)
|
||||
len_ws = buf_u.st_size;
|
||||
dat_y = c3_malloc(len_ws);
|
||||
|
||||
red_ws = read(fid_i, dat_y, len_ws);
|
||||
ssize_t red_i = c3_pread(fid_i, dat_y, len_ws, 0);
|
||||
|
||||
if ( close(fid_i) < 0 ) {
|
||||
u3l_log("error closing initial file %s: %s\r\n",
|
||||
pax_c, strerror(errno));
|
||||
}
|
||||
|
||||
if ( len_ws != red_ws ) {
|
||||
if ( red_ws < 0 ) {
|
||||
if ( red_i != len_ws ) {
|
||||
if ( red_i < 0 ) {
|
||||
u3l_log("error reading initial file %s: %s\r\n",
|
||||
pax_c, strerror(errno));
|
||||
pax_c, strerror(-red_i));
|
||||
}
|
||||
else {
|
||||
u3l_log("wrong # of bytes read in initial file %s: %d %d\r\n",
|
||||
pax_c, len_ws, red_ws);
|
||||
u3l_log("wrong # of bytes read in initial file %s: %u %zu\r\n",
|
||||
pax_c, len_ws, red_i);
|
||||
}
|
||||
c3_free(dat_y);
|
||||
return u3_nul;
|
||||
|
@ -307,7 +307,7 @@ _king_get_pace(void)
|
||||
{
|
||||
struct stat buf_u;
|
||||
c3_c* pat_c;
|
||||
c3_w red_w, len_w;
|
||||
c3_w len_w;
|
||||
c3_i ret_i, fid_i;
|
||||
|
||||
ret_i = asprintf(&pat_c, "%s/.bin/pace", u3_Host.dir_c);
|
||||
@ -324,10 +324,10 @@ _king_get_pace(void)
|
||||
|
||||
len_w = buf_u.st_size;
|
||||
pat_c = c3_malloc(len_w + 1);
|
||||
red_w = read(fid_i, pat_c, len_w);
|
||||
ssize_t red_i = c3_pread(fid_i, pat_c, len_w, 0);
|
||||
close(fid_i);
|
||||
|
||||
if ( len_w != red_w ) {
|
||||
if ( red_i != len_w ) {
|
||||
c3_free(pat_c);
|
||||
u3l_log("unable to read pace file, "
|
||||
"falling back to default (\"live\")\n");
|
||||
@ -1038,9 +1038,6 @@ _king_make_pace(c3_c* pac_c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static c3_i
|
||||
_king_write_raw(c3_i fid_i, c3_y* buf_y, size_t len_i);
|
||||
|
||||
/* _king_init_pace(): save pace file if not present
|
||||
*/
|
||||
static c3_i
|
||||
@ -1064,8 +1061,11 @@ _king_init_pace(c3_c* pac_c)
|
||||
}
|
||||
}
|
||||
|
||||
if ( _king_write_raw(fid_i, (c3_y*)pac_c, strlen(pac_c)) ) {
|
||||
u3l_log("dock: init pace (%s): write %s\n", pac_c, strerror(errno));
|
||||
size_t len_i = strlen(pac_c);
|
||||
ssize_t wit_i = c3_pwrite(fid_i, pac_c, len_i, 0);
|
||||
if ( wit_i != len_i ) {
|
||||
u3l_log("dock: init pace (%s) write failed: %s\n",
|
||||
pac_c, strerror(errno));
|
||||
close(fid_i);
|
||||
c3_free(bin_c);
|
||||
return -1;
|
||||
@ -1239,62 +1239,24 @@ _king_do_upgrade(c3_c* pac_c, c3_c* ver_c)
|
||||
// XX print restart instructions
|
||||
}
|
||||
|
||||
/* _king_read_raw: read (up to) [len_i] from [fid_i] to [buf_y]
|
||||
*/
|
||||
static ssize_t
|
||||
_king_read_raw(c3_i fid_i, c3_y* buf_y, size_t len_i)
|
||||
{
|
||||
ssize_t ret_i;
|
||||
|
||||
do {
|
||||
ret_i = read(fid_i, buf_y, len_i);
|
||||
}
|
||||
while ( (ret_i < 0) && (errno == EINTR) );
|
||||
|
||||
return ret_i;
|
||||
}
|
||||
|
||||
/* _king_read_raw: write [len_i] from [buf_y] to [fid_i].
|
||||
*/
|
||||
static c3_i
|
||||
_king_write_raw(c3_i fid_i, c3_y* buf_y, size_t len_i)
|
||||
{
|
||||
ssize_t ret_i;
|
||||
|
||||
while ( len_i ) {
|
||||
|
||||
do {
|
||||
ret_i = write(fid_i, buf_y, len_i);
|
||||
}
|
||||
while ( (ret_i < 0) && (errno == EINTR) );
|
||||
|
||||
if ( ret_i < 0 ) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
len_i -= ret_i;
|
||||
buf_y += ret_i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static c3_i
|
||||
_king_copy_raw(c3_i src_i, c3_i dst_i, c3_y* buf_y, size_t pag_i)
|
||||
{
|
||||
ssize_t red_i;
|
||||
size_t off_i = 0;
|
||||
ssize_t ret_i;
|
||||
|
||||
do {
|
||||
if ( 0 > (red_i = _king_read_raw(src_i, buf_y, pag_i)) ) {
|
||||
return -1;
|
||||
if ( 0 > (ret_i = c3_pread(src_i, buf_y, pag_i, off_i)) ) {
|
||||
return ret_i;
|
||||
}
|
||||
|
||||
if ( _king_write_raw(dst_i, buf_y, (size_t)red_i) ) {
|
||||
return -1;
|
||||
if ( 0 > (ret_i = c3_pwrite(dst_i, buf_y, (size_t)ret_i, off_i)) ) {
|
||||
return ret_i;
|
||||
}
|
||||
|
||||
off_i += (size_t)ret_i;
|
||||
}
|
||||
while ( red_i );
|
||||
while ( ret_i );
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1337,6 +1299,8 @@ _king_copy_file(c3_c* src_c, c3_c* dst_c)
|
||||
goto done1;
|
||||
}
|
||||
|
||||
// XX O_TRUNC?
|
||||
//
|
||||
if ( -1 == (dst_i = open(dst_c, O_RDWR | O_CREAT, 0755)) ) {
|
||||
err_i = errno;
|
||||
ret_i = -1;
|
||||
@ -1403,8 +1367,12 @@ _king_copy_file(c3_c* src_c, c3_c* dst_c)
|
||||
{
|
||||
size_t pag_i = 1 << 14;;
|
||||
c3_y* buf_y = c3_malloc(pag_i);
|
||||
ret_i = _king_copy_raw(src_i, dst_i, buf_y, pag_i);
|
||||
err_i = errno;
|
||||
|
||||
if ( 0 > (ret_i = _king_copy_raw(src_i, dst_i, buf_y, pag_i)) ) {
|
||||
err_i = errno;
|
||||
ret_i = -1;
|
||||
}
|
||||
|
||||
c3_free(buf_y);
|
||||
}
|
||||
|
||||
|
@ -1051,7 +1051,7 @@ _lord_on_serf_err_cb(uv_stream_t* pyp_u,
|
||||
// serf used to write to 2 directly
|
||||
// this can't be any worse than that
|
||||
//
|
||||
u3_write_fd(2, buf_u->base, siz_i);
|
||||
c3_assert(c3_write(STDERR_FILENO, buf_u->base, siz_i) == siz_i);
|
||||
} else {
|
||||
uv_read_stop(pyp_u);
|
||||
|
||||
|
@ -1 +1 @@
|
||||
1.13
|
||||
1.14-rc3
|
267
pkg/urbit/worker/mars.c
Normal file
267
pkg/urbit/worker/mars.c
Normal file
@ -0,0 +1,267 @@
|
||||
/* worker/mars.c
|
||||
**
|
||||
** the main loop of a mars process.
|
||||
*/
|
||||
#include "all.h"
|
||||
#include <vere/vere.h>
|
||||
#include <vere/mars.h>
|
||||
|
||||
/* _mars_step_trace(): initialize or rotate trace file.
|
||||
*/
|
||||
static void
|
||||
_mars_step_trace(const c3_c* dir_c)
|
||||
{
|
||||
if ( u3C.wag_w & u3o_trace ) {
|
||||
if ( u3_Host.tra_u.con_w == 0 && u3_Host.tra_u.fun_w == 0 ) {
|
||||
u3t_trace_open(dir_c);
|
||||
}
|
||||
else if ( u3_Host.tra_u.con_w >= 100000 ) {
|
||||
u3t_trace_close();
|
||||
u3t_trace_open(dir_c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* _mars_poke_play(): replay an event.
|
||||
*/
|
||||
static u3_weak
|
||||
_mars_poke_play(u3_mars* mar_u, c3_d eve_d, u3_noun job)
|
||||
{
|
||||
u3_noun vir;
|
||||
|
||||
if ( c3n == u3v_poke_sure(0, job, &vir) ) {
|
||||
return vir;
|
||||
}
|
||||
|
||||
u3z(vir);
|
||||
return u3_none;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
_play_yes_e, // success
|
||||
_play_mem_e, // %meme
|
||||
_play_int_e, // %intr
|
||||
_play_log_e, // event log fail
|
||||
_play_mug_e, // mug mismatch
|
||||
_play_bad_e // total failure
|
||||
} _mars_play_e;
|
||||
|
||||
/* _mars_play_batch(): replay a batch of events.
|
||||
*/
|
||||
static _mars_play_e
|
||||
_mars_play_batch(u3_mars* mar_u, c3_o mug_o, c3_w bat_w)
|
||||
{
|
||||
u3_disk* log_u = mar_u->log_u;
|
||||
u3_disk_walk* wok_u = u3_disk_walk_init(log_u, mar_u->dun_d + 1, bat_w);
|
||||
u3_fact tac_u;
|
||||
u3_noun dud;
|
||||
|
||||
while ( c3y == u3_disk_walk_live(wok_u) ) {
|
||||
if ( c3n == u3_disk_walk_step(wok_u, &tac_u) ) {
|
||||
u3_disk_walk_done(wok_u);
|
||||
return _play_log_e;
|
||||
}
|
||||
|
||||
c3_assert( ++mar_u->sen_d == tac_u.eve_d );
|
||||
|
||||
if ( u3_none != (dud = _mars_poke_play(mar_u, tac_u.eve_d, tac_u.job)) ) {
|
||||
c3_m mot_m;
|
||||
|
||||
mar_u->sen_d = mar_u->dun_d;
|
||||
u3_disk_walk_done(wok_u);
|
||||
|
||||
c3_assert( c3y == u3r_safe_word(u3h(dud), &mot_m) );
|
||||
|
||||
switch ( mot_m ) {
|
||||
case c3__meme: {
|
||||
fprintf(stderr, "play (%" PRIu64 "): %%meme\r\n", tac_u.eve_d);
|
||||
u3z(dud);
|
||||
return _play_mem_e;
|
||||
}
|
||||
|
||||
case c3__intr: {
|
||||
fprintf(stderr, "play (%" PRIu64 "): %%intr\r\n", tac_u.eve_d);
|
||||
u3z(dud);
|
||||
return _play_int_e;
|
||||
}
|
||||
|
||||
default: {
|
||||
fprintf(stderr, "play (%" PRIu64 "): failed\r\n", tac_u.eve_d);
|
||||
u3_pier_punt_goof("play", dud);
|
||||
// XX say something uplifting
|
||||
//
|
||||
return _play_bad_e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mar_u->mug_l = u3r_mug(u3A->roc);
|
||||
|
||||
if ( tac_u.mug_l && (mar_u->mug_l != tac_u.mug_l) ) {
|
||||
fprintf(stderr, "play (%" PRIu64 "): mug mismatch "
|
||||
"expected %08x, actual %08x\r\n",
|
||||
tac_u.eve_d, tac_u.mug_l, mar_u->mug_l);
|
||||
|
||||
if ( c3y == mug_o ) {
|
||||
mar_u->sen_d = mar_u->dun_d;
|
||||
u3_disk_walk_done(wok_u);
|
||||
return _play_mug_e;
|
||||
}
|
||||
}
|
||||
|
||||
mar_u->dun_d = mar_u->sen_d;
|
||||
}
|
||||
|
||||
u3_disk_walk_done(wok_u);
|
||||
|
||||
return _play_yes_e;
|
||||
}
|
||||
|
||||
static c3_o
|
||||
_mars_do_boot(u3_disk* log_u, c3_d eve_d)
|
||||
{
|
||||
u3_weak eve;
|
||||
c3_l mug_l;
|
||||
|
||||
if ( u3_none == (eve = u3_disk_read_list(log_u, 1, eve_d, &mug_l)) ) {
|
||||
fprintf(stderr, "boot: read failed\r\n");
|
||||
return c3n;
|
||||
}
|
||||
|
||||
u3l_log("--------------- bootstrap starting ----------------\r\n");
|
||||
|
||||
u3l_log("boot: 1-%u\r\n", u3qb_lent(eve));
|
||||
|
||||
if ( c3n == u3v_boot(eve) ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
u3l_log("--------------- bootstrap complete ----------------\r\n");
|
||||
return c3y;
|
||||
}
|
||||
|
||||
/* u3_mars_play(): replay logged events up to [eve_d].
|
||||
*/
|
||||
void
|
||||
u3_mars_play(u3_mars* mar_u, c3_d eve_d)
|
||||
{
|
||||
u3_disk* log_u = mar_u->log_u;
|
||||
|
||||
if ( !eve_d ) {
|
||||
eve_d = log_u->dun_d;
|
||||
}
|
||||
else if ( eve_d <= mar_u->dun_d ) {
|
||||
u3l_log("mars: already computed %" PRIu64 "\r\n", eve_d);
|
||||
u3l_log(" state=%" PRIu64 ", log=%" PRIu64 "\r\n",
|
||||
mar_u->dun_d, log_u->dun_d);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
eve_d = c3_min(eve_d, log_u->dun_d);
|
||||
}
|
||||
|
||||
if ( !mar_u->dun_d ) {
|
||||
c3_w lif_w;
|
||||
|
||||
if ( c3n == u3_disk_read_meta(log_u, 0, 0, &lif_w) ) {
|
||||
fprintf(stderr, "mars: disk read meta fail\r\n");
|
||||
// XX exit code, cb
|
||||
//
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( c3n == _mars_do_boot(mar_u->log_u, lif_w) ) {
|
||||
fprintf(stderr, "mars: boot fail\r\n");
|
||||
// XX exit code, cb
|
||||
//
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mar_u->sen_d = mar_u->dun_d = lif_w;
|
||||
}
|
||||
|
||||
if ( mar_u->dun_d == log_u->dun_d ) {
|
||||
u3l_log("mars: nothing to do!\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
u3l_log("---------------- playback starting ----------------\r\n");
|
||||
|
||||
if ( (1ULL + eve_d) == log_u->dun_d ) {
|
||||
u3l_log("play: event %" PRIu64 "\r\n", log_u->dun_d);
|
||||
}
|
||||
else if ( eve_d != log_u->dun_d ) {
|
||||
u3l_log("play: events %" PRIu64 "-%" PRIu64 " of %" PRIu64 "\r\n",
|
||||
(c3_d)(1ULL + mar_u->dun_d),
|
||||
eve_d,
|
||||
log_u->dun_d);
|
||||
}
|
||||
else {
|
||||
u3l_log("play: events %" PRIu64 "-%" PRIu64 "\r\n",
|
||||
(c3_d)(1ULL + mar_u->dun_d),
|
||||
eve_d);
|
||||
}
|
||||
|
||||
{
|
||||
c3_d mem_d = 0; // last event to meme
|
||||
c3_w try_w = 0; // [mem_d] retry count
|
||||
|
||||
while ( mar_u->dun_d < eve_d ) {
|
||||
_mars_step_trace(mar_u->dir_c);
|
||||
|
||||
// XX get batch from args
|
||||
//
|
||||
switch ( _mars_play_batch(mar_u, c3y, 1024) ) {
|
||||
case _play_yes_e: {
|
||||
u3l_log("play (%" PRIu64 "): done\r\n", mar_u->dun_d);
|
||||
u3m_reclaim();
|
||||
|
||||
// XX save a snapshot every N events?
|
||||
//
|
||||
} break;
|
||||
|
||||
case _play_mem_e: {
|
||||
if ( mem_d != mar_u->dun_d ) {
|
||||
mem_d = mar_u->dun_d;
|
||||
try_w = 0;
|
||||
}
|
||||
else if ( 3 == ++try_w ) {
|
||||
fprintf(stderr, "play (%" PRIu64 "): failed\r\n", mar_u->dun_d + 1);
|
||||
u3m_save();
|
||||
// XX check loom size, suggest --loom X
|
||||
// XX exit code, cb
|
||||
//
|
||||
u3_disk_exit(log_u);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// XX pack before meld?
|
||||
//
|
||||
if ( u3C.wag_w & u3o_auto_meld ) {
|
||||
u3a_print_memory(stderr, "mars: meld: gained", u3u_meld());
|
||||
}
|
||||
else {
|
||||
u3a_print_memory(stderr, "mars: pack: gained", u3m_pack());
|
||||
}
|
||||
} break;
|
||||
|
||||
// XX handle any specifically?
|
||||
//
|
||||
case _play_int_e:
|
||||
case _play_log_e:
|
||||
case _play_mug_e:
|
||||
case _play_bad_e: {
|
||||
fprintf(stderr, "play (%" PRIu64 "): failed\r\n", mar_u->dun_d + 1);
|
||||
u3m_save();
|
||||
// XX exit code, cb
|
||||
//
|
||||
u3_disk_exit(log_u);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u3l_log("---------------- playback complete ----------------\r\n");
|
||||
u3m_save();
|
||||
}
|
@ -49,137 +49,6 @@
|
||||
--
|
||||
*/
|
||||
|
||||
/* _serf_space(): print n spaces.
|
||||
*/
|
||||
static void
|
||||
_serf_space(FILE* fil_u, c3_w n)
|
||||
{
|
||||
for (; n > 0; n--)
|
||||
(fprintf(fil_u," "));
|
||||
}
|
||||
|
||||
/* _serf_print_memory(): print memory amount.
|
||||
**
|
||||
** Helper for _serf_prof(), just an un-captioned u3a_print_memory().
|
||||
*/
|
||||
static void
|
||||
_serf_print_memory(FILE* fil_u, c3_w wor_w)
|
||||
{
|
||||
c3_w byt_w = (wor_w * 4);
|
||||
c3_w gib_w = (byt_w / 1000000000);
|
||||
c3_w mib_w = (byt_w % 1000000000) / 1000000;
|
||||
c3_w kib_w = (byt_w % 1000000) / 1000;
|
||||
c3_w bib_w = (byt_w % 1000);
|
||||
|
||||
if ( gib_w ) {
|
||||
(fprintf(fil_u, "GB/%d.%03d.%03d.%03d\r\n",
|
||||
gib_w, mib_w, kib_w, bib_w));
|
||||
}
|
||||
else if ( mib_w ) {
|
||||
(fprintf(fil_u, "MB/%d.%03d.%03d\r\n", mib_w, kib_w, bib_w));
|
||||
}
|
||||
else if ( kib_w ) {
|
||||
(fprintf(fil_u, "KB/%d.%03d\r\n", kib_w, bib_w));
|
||||
}
|
||||
else {
|
||||
(fprintf(fil_u, "B/%d\r\n", bib_w));
|
||||
}
|
||||
}
|
||||
|
||||
/* _serf_prof(): print memory profile. RETAIN.
|
||||
*/
|
||||
c3_w
|
||||
_serf_prof(FILE* fil_u, c3_w den, u3_noun mas)
|
||||
{
|
||||
c3_w tot_w = 0;
|
||||
u3_noun h_mas, t_mas;
|
||||
|
||||
if ( c3n == u3r_cell(mas, &h_mas, &t_mas) ) {
|
||||
_serf_space(fil_u, den);
|
||||
fprintf(fil_u, "mistyped mass\r\n");
|
||||
return tot_w;
|
||||
}
|
||||
else if ( _(u3du(h_mas)) ) {
|
||||
_serf_space(fil_u, den);
|
||||
fprintf(fil_u, "mistyped mass head\r\n");
|
||||
{
|
||||
c3_c* lab_c = u3m_pretty(h_mas);
|
||||
fprintf(fil_u, "h_mas: %s", lab_c);
|
||||
c3_free(lab_c);
|
||||
}
|
||||
return tot_w;
|
||||
}
|
||||
else {
|
||||
_serf_space(fil_u, den);
|
||||
|
||||
{
|
||||
c3_c* lab_c = u3m_pretty(h_mas);
|
||||
fprintf(fil_u, "%s: ", lab_c);
|
||||
c3_free(lab_c);
|
||||
}
|
||||
|
||||
u3_noun it_mas, tt_mas;
|
||||
|
||||
if ( c3n == u3r_cell(t_mas, &it_mas, &tt_mas) ) {
|
||||
fprintf(fil_u, "mistyped mass tail\r\n");
|
||||
return tot_w;
|
||||
}
|
||||
else if ( c3y == it_mas ) {
|
||||
tot_w += u3a_mark_noun(tt_mas);
|
||||
_serf_print_memory(fil_u, tot_w);
|
||||
|
||||
#if 1
|
||||
/* The basic issue here is that tt_mas is included in .sac
|
||||
* (the whole profile), so they can't both be roots in the
|
||||
* normal sense. When we mark .sac later on, we want tt_mas
|
||||
* to appear unmarked, but its children should be already
|
||||
* marked.
|
||||
*/
|
||||
if ( _(u3a_is_dog(tt_mas)) ) {
|
||||
u3a_box* box_u = u3a_botox(u3a_to_ptr(tt_mas));
|
||||
#ifdef U3_MEMORY_DEBUG
|
||||
if ( 1 == box_u->eus_w ) {
|
||||
box_u->eus_w = 0xffffffff;
|
||||
}
|
||||
else {
|
||||
box_u->eus_w -= 1;
|
||||
}
|
||||
#else
|
||||
if ( -1 == (c3_w)box_u->use_w ) {
|
||||
box_u->use_w = 0x80000000;
|
||||
}
|
||||
else {
|
||||
box_u->use_w += 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return tot_w;
|
||||
}
|
||||
else if ( c3n == it_mas ) {
|
||||
fprintf(fil_u, "\r\n");
|
||||
|
||||
while ( _(u3du(tt_mas)) ) {
|
||||
tot_w += _serf_prof(fil_u, den+2, u3h(tt_mas));
|
||||
tt_mas = u3t(tt_mas);
|
||||
}
|
||||
|
||||
_serf_space(fil_u, den);
|
||||
fprintf(fil_u, "--");
|
||||
_serf_print_memory(fil_u, tot_w);
|
||||
|
||||
return tot_w;
|
||||
|
||||
}
|
||||
else {
|
||||
_serf_space(fil_u, den);
|
||||
fprintf(fil_u, "mistyped (strange) mass tail\r\n");
|
||||
return tot_w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* _serf_grab(): garbage collect, checking for profiling. RETAIN.
|
||||
*/
|
||||
static void
|
||||
@ -200,7 +69,7 @@ _serf_grab(u3_noun sac)
|
||||
c3_c* wen_c = u3r_string(wen);
|
||||
|
||||
c3_c nam_c[2048];
|
||||
snprintf(nam_c, 2048, "%s/.urb/put/mass", u3P.dir_c);
|
||||
snprintf(nam_c, 2048, "%s/.urb/put/mass", u3C.dir_c);
|
||||
|
||||
struct stat st;
|
||||
if ( -1 == stat(nam_c, &st) ) {
|
||||
@ -225,7 +94,7 @@ _serf_grab(u3_noun sac)
|
||||
c3_assert( u3R == &(u3H->rod_u) );
|
||||
fprintf(fil_u, "\r\n");
|
||||
|
||||
tot_w += u3a_maid(fil_u, "total userspace", _serf_prof(fil_u, 0, sac));
|
||||
tot_w += u3a_maid(fil_u, "total userspace", u3a_prof(fil_u, 0, sac));
|
||||
tot_w += u3m_mark(fil_u);
|
||||
tot_w += u3a_maid(fil_u, "space profile", u3a_mark_noun(sac));
|
||||
|
||||
@ -839,7 +708,7 @@ _serf_writ_live_exit(u3_serf* sef_u, c3_w cod_w)
|
||||
c3_c* wen_c = u3r_string(wen);
|
||||
|
||||
c3_c nam_c[2048];
|
||||
snprintf(nam_c, 2048, "%s/.urb/put/profile", u3P.dir_c);
|
||||
snprintf(nam_c, 2048, "%s/.urb/put/profile", u3C.dir_c);
|
||||
|
||||
struct stat st;
|
||||
if ( -1 == stat(nam_c, &st) ) {
|
||||
@ -883,7 +752,7 @@ _serf_writ_live_save(u3_serf* sef_u, c3_d eve_d)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
u3e_save();
|
||||
u3m_save();
|
||||
}
|
||||
|
||||
/* u3_serf_live(): apply %live command [com], producing *ret on c3y.
|
||||
@ -954,7 +823,7 @@ u3_serf_live(u3_serf* sef_u, u3_noun com, u3_noun* ret)
|
||||
return c3n;
|
||||
}
|
||||
|
||||
u3e_save();
|
||||
u3m_save();
|
||||
u3_serf_grab();
|
||||
|
||||
*ret = u3nc(c3__live, u3_nul);
|
||||
@ -981,7 +850,7 @@ u3_serf_live(u3_serf* sef_u, u3_noun com, u3_noun* ret)
|
||||
}
|
||||
else {
|
||||
u3z(com);
|
||||
u3u_meld();
|
||||
u3a_print_memory(stderr, "serf: meld: gained", u3u_meld());
|
||||
*ret = u3nc(c3__live, u3_nul);
|
||||
return c3y;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user