@ai-ecoverse/slicc-kernel 1.25.0 → 1.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.js CHANGED
@@ -3441,7 +3441,8 @@ function statOf(attr, path, mount) {
3441
3441
  dev: mount.dev,
3442
3442
  ...readonly(mount) ? { readonly: true } : {},
3443
3443
  ...mount.maxFile > 0 ? { maxFile: mount.maxFile } : {},
3444
- ...mount.caps.ranges ? { ranged: true } : {}
3444
+ ...mount.caps.ranges ? { ranged: true } : {},
3445
+ ...attr.etag !== void 0 ? { version: attr.etag } : {}
3445
3446
  };
3446
3447
  }
3447
3448
  function concat3(chunks2, total) {
@@ -3776,7 +3777,7 @@ var MountFs = class {
3776
3777
  this.table.forget(mount, real);
3777
3778
  }
3778
3779
  }
3779
- async pread(path, offset, length2) {
3780
+ async pread(path, offset, length2, version) {
3780
3781
  const real = await this.follow(path);
3781
3782
  const found = this.at(real);
3782
3783
  if (!found && this.base.pread) return this.base.pread(real, offset, length2);
@@ -3785,7 +3786,15 @@ var MountFs = class {
3785
3786
  if ((await this.table.getattr(mount, real, rel2)).kind === "directory") {
3786
3787
  throw errnoError("EISDIR", real);
3787
3788
  }
3788
- const fh = await this.open(mount, rel2, false);
3789
+ const fh = await mount.conn.call({
3790
+ op: "open",
3791
+ path: rel2,
3792
+ write: false,
3793
+ create: false,
3794
+ truncate: false,
3795
+ exclusive: false,
3796
+ ...version !== void 0 ? { ifMatch: version } : {}
3797
+ });
3789
3798
  const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
3790
3799
  const chunks2 = [];
3791
3800
  let total = 0;
@@ -4047,7 +4056,8 @@ function statJson(s) {
4047
4056
  ...s.dev !== void 0 ? { dev: s.dev } : {},
4048
4057
  ...s.readonly ? { readonly: true } : {},
4049
4058
  ...s.maxFile ? { maxFile: s.maxFile } : {},
4050
- ...s.ranged ? { ranged: true } : {}
4059
+ ...s.ranged ? { ranged: true } : {},
4060
+ ...s.version !== void 0 ? { version: s.version } : {}
4051
4061
  };
4052
4062
  }
4053
4063
  async function readdirStat(fs, dir) {
@@ -4125,7 +4135,11 @@ async function ranged(fs, path, req) {
4125
4135
  if (!ops) throw syncError("ENOSYS", path);
4126
4136
  const offset = req.offset ?? 0;
4127
4137
  if (req.op === "pread")
4128
- return { ok: true, kind: "bytes", bytes: await ops.pread(path, offset, req.length ?? 0) };
4138
+ return {
4139
+ ok: true,
4140
+ kind: "bytes",
4141
+ bytes: await ops.pread(path, offset, req.length ?? 0, req.version)
4142
+ };
4129
4143
  if (req.op === "pwrite") await ops.pwrite(path, offset, req.body ?? new Uint8Array(0), true);
4130
4144
  else await ops.truncate(path, req.length ?? 0);
4131
4145
  return done;
@@ -6401,17 +6415,21 @@ var AsyncRangedFile = class {
6401
6415
  pages;
6402
6416
  io;
6403
6417
  pinned = false;
6418
+ version;
6404
6419
  path;
6405
- constructor(io, path, size) {
6420
+ constructor(io, path, size, version) {
6406
6421
  this.io = io;
6407
6422
  this.path = path;
6423
+ this.version = version;
6408
6424
  this.pages = new Pages(size);
6409
6425
  }
6410
6426
  size() {
6411
6427
  return this.pages.length;
6412
6428
  }
6413
6429
  async fetch(runs) {
6414
- for (const [start, n] of runs) this.pages.fill(start, await this.io.pread(this.path, start, n));
6430
+ for (const [start, n] of runs) {
6431
+ this.pages.fill(start, await this.io.pread(this.path, start, n, this.version));
6432
+ }
6415
6433
  }
6416
6434
  async read(at, length2) {
6417
6435
  await this.fetch(this.pages.missing(at, length2));
@@ -6431,6 +6449,7 @@ var AsyncRangedFile = class {
6431
6449
  if (plan.shrink !== void 0) await this.io.truncate(this.path, plan.shrink);
6432
6450
  for (const run2 of plan.runs) await this.io.pwrite(this.path, run2.offset, run2.bytes, true);
6433
6451
  if (plan.extend !== void 0) await this.io.truncate(this.path, plan.extend);
6452
+ this.version = void 0;
6434
6453
  this.pages.flushed();
6435
6454
  }
6436
6455
  async pin() {
@@ -6498,7 +6517,7 @@ var VfsNode = class {
6498
6517
  const io = rangedOps(this.fs);
6499
6518
  const st = io && !this.orphaned ? await this.fs.stat?.(this.path).catch(() => void 0) : void 0;
6500
6519
  if (io && st?.ranged) {
6501
- this.ranged = new AsyncRangedFile(io, this.path, st.size ?? 0);
6520
+ this.ranged = new AsyncRangedFile(io, this.path, st.size ?? 0, st.version);
6502
6521
  return this.ranged;
6503
6522
  }
6504
6523
  await this.load();
@@ -7792,7 +7811,8 @@ async function dispatch(h, req) {
7792
7811
  write: req.write,
7793
7812
  create: req.create,
7794
7813
  truncate: req.truncate,
7795
- exclusive: req.exclusive
7814
+ exclusive: req.exclusive,
7815
+ ...req.ifMatch !== void 0 ? { ifMatch: req.ifMatch } : {}
7796
7816
  });
7797
7817
  case "read":
7798
7818
  return h.read(req.fh, req.offset, req.size);
@@ -8333,7 +8353,8 @@ function hostfsHandlers(current) {
8333
8353
  };
8334
8354
  const call = (op, body = {}) => current().call(op, body);
8335
8355
  async function writable(client, path, flags) {
8336
- const opening = () => client.call("open", { path: rel(path), ...flags });
8356
+ const { ifMatch: _, ...asked } = flags;
8357
+ const opening = () => client.call("open", { path: rel(path), ...asked });
8337
8358
  try {
8338
8359
  return { opened: await opening(), restore: void 0 };
8339
8360
  } catch (err) {
@@ -8349,7 +8370,7 @@ function hostfsHandlers(current) {
8349
8370
  return { opened: opened2, restore };
8350
8371
  }
8351
8372
  }
8352
- return {
8373
+ const handlers = {
8353
8374
  getattr: async (path) => await call("stat", { path: rel(path) }),
8354
8375
  async readdir(path) {
8355
8376
  const { entries } = await call(
@@ -8362,6 +8383,10 @@ function hostfsHandlers(current) {
8362
8383
  const client = current();
8363
8384
  const token = client.token;
8364
8385
  const { opened: opened2, restore } = await writable(client, path, flags);
8386
+ if (flags.ifMatch !== void 0 && opened2.attr?.etag !== flags.ifMatch) {
8387
+ await client.call("release", { fh: opened2.fh }, true);
8388
+ throw fsError2("ESTALE", `${path} changed on the host while it was being read`);
8389
+ }
8365
8390
  handles.set(++nextFh, {
8366
8391
  client,
8367
8392
  token,
@@ -8403,9 +8428,44 @@ function hostfsHandlers(current) {
8403
8428
  rename: async (from, to) => void await call("rename", { from: rel(from), to: rel(to) }),
8404
8429
  symlink: async (target, path) => void await call("symlink", { target, path: rel(path) }),
8405
8430
  readlink: async (path) => (await call("readlink", { path: rel(path) })).target,
8406
- setattr: async (path, change) => void await call("setattr", { path: rel(path), ...change }),
8431
+ async setattr(path, { size, ...change }) {
8432
+ if (size !== void 0 && !current().capabilities.ranges) await resize(handlers, path, size);
8433
+ else if (size !== void 0) change = { ...change, size };
8434
+ if (Object.keys(change).length > 0) await call("setattr", { path: rel(path), ...change });
8435
+ },
8407
8436
  statfs: () => call("statfs")
8408
8437
  };
8438
+ return handlers;
8439
+ }
8440
+ var KEEP = { write: false, create: false, truncate: false, exclusive: false };
8441
+ async function resize(h, path, size) {
8442
+ const was = (await h.getattr(path)).size;
8443
+ if (size === was) return;
8444
+ const kept = [];
8445
+ if (size < was && size > 0) {
8446
+ const fh2 = await h.open(path, KEEP);
8447
+ try {
8448
+ for (let at = 0; at < size; ) {
8449
+ const bytes = await h.read(fh2, at, size - at);
8450
+ if (bytes.length === 0) break;
8451
+ kept.push(bytes);
8452
+ at += bytes.length;
8453
+ }
8454
+ } finally {
8455
+ await h.release(fh2);
8456
+ }
8457
+ }
8458
+ const fh = await h.open(path, { ...KEEP, write: true, truncate: size < was });
8459
+ try {
8460
+ if (size > was) await h.write(fh, size - 1, new Uint8Array(1));
8461
+ let at = 0;
8462
+ for (const bytes of kept) {
8463
+ await h.write(fh, at, bytes);
8464
+ at += bytes.length;
8465
+ }
8466
+ } finally {
8467
+ await h.release(fh);
8468
+ }
8409
8469
  }
8410
8470
  function sleep(ms, signal) {
8411
8471
  return new Promise((resolve) => {
@@ -8499,13 +8559,18 @@ async function openHostfs(spec, hook, fetch2, timing = {}) {
8499
8559
  const grant = () => hook(spec.source, { readonly: readonly2 });
8500
8560
  let active;
8501
8561
  const handlers = hostfsHandlers(() => active);
8502
- const served = serveFilesystem(port2, slot.handlers, {
8503
- symlinks: true,
8504
- chmod: true,
8505
- listingStats: true,
8506
- maxIo: HOSTFS_IO,
8507
- ...readonly2 ? { readonly: true } : {}
8508
- });
8562
+ const ranged2 = () => active?.capabilities.ranges === true ? { ranges: true } : {};
8563
+ const served = serveFilesystem(
8564
+ port2,
8565
+ { ...slot.handlers, mount: ranged2 },
8566
+ {
8567
+ symlinks: true,
8568
+ chmod: true,
8569
+ listingStats: true,
8570
+ maxIo: HOSTFS_IO,
8571
+ ...readonly2 ? { readonly: true } : {}
8572
+ }
8573
+ );
8509
8574
  const watching = keepWatching(
8510
8575
  {
8511
8576
  connect: async () => new HostfsClient(await grant(), grant, fetch2),