@ai-ecoverse/slicc-kernel 1.124.3 → 1.124.5

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.
@@ -1253,9 +1253,13 @@ var OpfsFs = class {
1253
1253
  if (this.remote) this.remote.quiet = () => this.quiet().then(() => this.settle?.());
1254
1254
  if (this.channel) {
1255
1255
  const remote = this.remote;
1256
- meta.listen?.(
1257
- (c) => remote?.emit({ paths: c.paths ?? [], trees: c.trees ?? [] })
1258
- );
1256
+ meta.listen?.((c) => {
1257
+ for (const path of [...c.paths ?? [], ...c.trees ?? []]) this.forget(path);
1258
+ remote?.emit({ paths: c.paths ?? [], trees: c.trees ?? [] });
1259
+ });
1260
+ remote?.listen((c) => {
1261
+ for (const path of [...c.paths, ...c.trees]) this.forget(path);
1262
+ });
1259
1263
  this.channel.onmessage = ({ data }) => {
1260
1264
  for (const path of data) this.forget(path);
1261
1265
  remote?.emit({ paths: data, trees: [] });
@@ -1416,9 +1420,13 @@ var OpfsFs = class {
1416
1420
  joined: () => remote.peered(),
1417
1421
  crowded: () => remote.crowded(),
1418
1422
  watch: (listener) => {
1419
- remote.crowd = listener;
1423
+ remote.crowd = (crowded) => {
1424
+ this.fresh();
1425
+ listener(crowded);
1426
+ };
1420
1427
  listener(remote.crowded());
1421
- }
1428
+ },
1429
+ fresh: () => this.fresh()
1422
1430
  };
1423
1431
  }
1424
1432
  quiet() {
@@ -1471,6 +1479,7 @@ var OpfsFs = class {
1471
1479
  async walk(parts2, from, start2) {
1472
1480
  let dir = start2;
1473
1481
  for (let at = from; at < parts2.length; at++) {
1482
+ this.calls++;
1474
1483
  dir = await dir.getDirectoryHandle(parts2[at]);
1475
1484
  this.dirs.set(`/${parts2.slice(0, at + 1).join("/")}`, dir);
1476
1485
  this.checked.set(dir, performance.now());
@@ -1499,11 +1508,29 @@ var OpfsFs = class {
1499
1508
  async current(path, dir) {
1500
1509
  if (dir === this.root) return path === "/";
1501
1510
  if (performance.now() - (this.checked.get(dir) ?? -CHECK_MS) < CHECK_MS) return true;
1511
+ this.calls++;
1502
1512
  const where = await this.root.resolve(dir).catch(() => null);
1503
1513
  if (where === null || `/${where.join("/")}` !== path) return false;
1504
1514
  this.checked.set(dir, performance.now());
1505
1515
  return true;
1506
1516
  }
1517
+ exact = 0;
1518
+ calls = 0;
1519
+ opfsCalls() {
1520
+ return this.calls;
1521
+ }
1522
+ fresh() {
1523
+ this.changes++;
1524
+ this.absent.clear();
1525
+ }
1526
+ async exactly(op) {
1527
+ this.exact++;
1528
+ try {
1529
+ return await op();
1530
+ } finally {
1531
+ this.exact--;
1532
+ }
1533
+ }
1507
1534
  forget(path) {
1508
1535
  this.changes++;
1509
1536
  this.dirs.deleteTree(path);
@@ -1538,6 +1565,7 @@ var OpfsFs = class {
1538
1565
  }
1539
1566
  }
1540
1567
  async child(parent, name2, kind) {
1568
+ this.calls++;
1541
1569
  return kind === "file" ? parent.getFileHandle(name2) : parent.getDirectoryHandle(name2);
1542
1570
  }
1543
1571
  async parent(path) {
@@ -1566,7 +1594,7 @@ var OpfsFs = class {
1566
1594
  const kept = this.dirs.get(path);
1567
1595
  if (kept && await this.current(path, kept)) return kept;
1568
1596
  const gone = this.absent.get(path);
1569
- if (gone !== void 0 && !this.shared() && performance.now() - gone < ABSENT_MS) {
1597
+ if (gone !== void 0 && this.exact === 0 && performance.now() - gone < ABSENT_MS) {
1570
1598
  throw translate({ name: "NotFoundError" }, path);
1571
1599
  }
1572
1600
  const seen = this.changes;
@@ -1727,6 +1755,7 @@ var OpfsFs = class {
1727
1755
  flushing = {};
1728
1756
  touch(now, ...dirs) {
1729
1757
  this.changes++;
1758
+ if (this.shared()) this.channel?.postMessage(dirs);
1730
1759
  for (const dir of dirs) {
1731
1760
  this.absent.deleteTree(dir);
1732
1761
  this.dirTimes.set(dir, now);
@@ -1758,7 +1787,7 @@ var OpfsFs = class {
1758
1787
  return this.remote?.crowded() === true;
1759
1788
  }
1760
1789
  glanced(handle) {
1761
- if (this.shared()) return void 0;
1790
+ if (this.exact > 0) return void 0;
1762
1791
  const seen = this.glances.get(handle);
1763
1792
  const fresh2 = seen && seen.changes === this.changes && performance.now() - seen.at < GLANCE_MS;
1764
1793
  return fresh2 ? seen.file : void 0;
@@ -1766,6 +1795,7 @@ var OpfsFs = class {
1766
1795
  async glance(handle) {
1767
1796
  const at = performance.now();
1768
1797
  const before = this.changes;
1798
+ this.calls++;
1769
1799
  const file = await handle.getFile();
1770
1800
  if (before === this.changes) this.glances.set(handle, { at, file, changes: before });
1771
1801
  else this.glances.delete(handle);
@@ -2051,7 +2081,7 @@ var OpfsFs = class {
2051
2081
  if (!options.recursive) return this.mkdirExcl(path, options.owner);
2052
2082
  let found;
2053
2083
  try {
2054
- found = await this.locate(path, true);
2084
+ found = await this.exactly(() => this.locate(path, true));
2055
2085
  } catch (err) {
2056
2086
  if (!missing2(err)) throw err;
2057
2087
  }
@@ -2124,6 +2154,7 @@ var OpfsFs = class {
2124
2154
  });
2125
2155
  }
2126
2156
  async handleExists(dir, name2) {
2157
+ this.calls++;
2127
2158
  try {
2128
2159
  await dir.getDirectoryHandle(name2);
2129
2160
  return true;
@@ -2178,7 +2209,7 @@ var OpfsFs = class {
2178
2209
  async link(from, to, follow2) {
2179
2210
  await (follow2 ? this.stat(from) : this.lstat(from));
2180
2211
  if (!(await this.stat(parentOf3(to))).isDirectory) throw fsError("ENOTDIR", to);
2181
- const taken = await this.lstat(to).then(
2212
+ const taken = await this.exactly(() => this.lstat(to)).then(
2182
2213
  () => true,
2183
2214
  (err) => {
2184
2215
  if (missing2(err)) return false;
@@ -2201,7 +2232,7 @@ var OpfsFs = class {
2201
2232
  async moveTo(source, parent, destination, to) {
2202
2233
  const sourceStat = await this.describe(source);
2203
2234
  if (sourceStat.isDirectory && within2(destination, source.path)) throw fsError("EINVAL", to);
2204
- const target = await this.locate(destination, false).catch((err) => {
2235
+ const target = await this.exactly(() => this.locate(destination, false)).catch((err) => {
2205
2236
  if (missing2(err)) return null;
2206
2237
  throw err;
2207
2238
  });
@@ -2320,7 +2351,7 @@ var OpfsFs = class {
2320
2351
  if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
2321
2352
  const at = resolvePath(parent.path, baseOf(path));
2322
2353
  this.refuse(at);
2323
- if (await this.locate(at, false).then(
2354
+ if (await this.exactly(() => this.locate(at, false)).then(
2324
2355
  () => true,
2325
2356
  (err) => !missing2(err)
2326
2357
  )) {
@@ -6594,7 +6625,7 @@ function satisfies(version, range2) {
6594
6625
  }
6595
6626
 
6596
6627
  // src/version.ts
6597
- var KERNEL_VERSION = true ? "1.124.3" : "0.0.0-dev";
6628
+ var KERNEL_VERSION = true ? "1.124.5" : "0.0.0-dev";
6598
6629
  var OS_RELEASE = "6.0.0-slicc";
6599
6630
  function procVersion() {
6600
6631
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -7514,15 +7545,21 @@ var UnlinkedKeeper = class {
7514
7545
  };
7515
7546
  const unreplaced = async (path, op) => {
7516
7547
  const at = fs.resolvePath("/", path);
7548
+ const pending = async () => {
7549
+ for (let p = at; replacing.size > 0; p = parentOf5(p)) {
7550
+ await replacing.get(p)?.done;
7551
+ if (p === "/") return;
7552
+ }
7553
+ };
7517
7554
  for (let attempt = 1; ; attempt++) {
7518
- await replacing.get(at)?.done;
7555
+ await pending();
7519
7556
  const seen = keeper.replaced;
7520
7557
  try {
7521
7558
  return await op();
7522
7559
  } catch (err) {
7523
7560
  const code = err?.code;
7524
7561
  if (attempt >= 3 || code !== "ENOENT") throw err;
7525
- await replacing.get(at)?.done;
7562
+ await pending();
7526
7563
  if (keeper.replaced === seen) throw err;
7527
7564
  }
7528
7565
  }
@@ -7547,9 +7584,11 @@ var UnlinkedKeeper = class {
7547
7584
  lstat: (path) => unreplaced(path, async () => counted2(await fs.lstat(path))),
7548
7585
  async rm(path, options) {
7549
7586
  const target = fs.resolvePath("/", path);
7550
- const pinned = await keeper.pin(target);
7551
- if (pinned.moved.has(target)) pinned.commit();
7552
- else await keeper.settle(pinned, () => fs.rm(path, options));
7587
+ await replace(target, async (gated) => {
7588
+ const pinned = await keeper.pin(target, gated);
7589
+ if (pinned.moved.has(target)) pinned.commit();
7590
+ else await keeper.settle(pinned, () => fs.rm(path, options));
7591
+ });
7553
7592
  },
7554
7593
  async rename(from, to) {
7555
7594
  const target = fs.resolvePath("/", to);
@@ -7584,9 +7623,22 @@ var UnlinkedKeeper = class {
7584
7623
  return held;
7585
7624
  }
7586
7625
  async pin(target, gated = () => void 0) {
7587
- const paths = [...this.heldWithin(target).keys()].sort();
7626
+ const paths = [];
7588
7627
  const releases = [];
7589
- for (const path of paths) releases.push(await this.gate.acquire(path));
7628
+ for (; ; ) {
7629
+ const fresh2 = [...this.heldWithin(target).keys()].filter((path) => !paths.includes(path));
7630
+ if (fresh2.length === 0) break;
7631
+ fresh2.sort();
7632
+ if (paths.some((path) => path > fresh2[0])) {
7633
+ for (const release of releases.splice(0)) release();
7634
+ fresh2.push(...paths.splice(0));
7635
+ fresh2.sort();
7636
+ }
7637
+ for (const path of fresh2) {
7638
+ paths.push(path);
7639
+ releases.push(await this.gate.acquire(path));
7640
+ }
7641
+ }
7590
7642
  gated();
7591
7643
  const now = this.heldWithin(target);
7592
7644
  const held = new Map(
@@ -12760,6 +12812,8 @@ var SYS_TREE = {
12760
12812
  slicc_shared_root: (listing) => `${listing.peers ?? 0}
12761
12813
  `,
12762
12814
  slicc_fs_calls: (listing) => `${listing.fsCalls ?? 0}
12815
+ `,
12816
+ slicc_opfs_calls: (listing) => `${listing.opfsCalls ?? 0}
12763
12817
  `
12764
12818
  }
12765
12819
  };
@@ -13931,9 +13985,13 @@ async function flock(req, ctx) {
13931
13985
  if (req.kind !== "unlock" && req.wait)
13932
13986
  await locks.flocks.wait(key, owner, req.kind, ctx.blocking);
13933
13987
  else if (!await locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
13934
- if (shared && granted2) await ctx.settle?.(req.fd, true);
13988
+ if (shared && granted2) await grantedAcross(ctx, req.fd);
13935
13989
  return shared ? json3(true) : done2;
13936
13990
  }
13991
+ async function grantedAcross(ctx, fd) {
13992
+ ctx.locks?.fresh?.();
13993
+ if (fd !== void 0) await ctx.settle?.(fd, true);
13994
+ }
13937
13995
  async function recordLock2(req, ctx) {
13938
13996
  const { locks, fileKey } = ctx;
13939
13997
  if (!locks || !fileKey) throw new KernelError("ENOLCK");
@@ -13963,7 +14021,7 @@ async function recordLock2(req, ctx) {
13963
14021
  await locks.wait(key, owner, req.kind, range2, ctx.blocking);
13964
14022
  else if (!await locks.set(key, owner, req.kind, range2.start, range2.end))
13965
14023
  throw new KernelError("EAGAIN");
13966
- if (granted2 && fd !== void 0) await ctx.settle?.(fd, true);
14024
+ if (granted2 && shared) await grantedAcross(ctx, fd);
13967
14025
  return shared ? json3(true) : done2;
13968
14026
  }
13969
14027
 
@@ -20622,6 +20680,9 @@ var LockService = class {
20622
20680
  };
20623
20681
  }
20624
20682
  peers;
20683
+ fresh() {
20684
+ this.peers?.fresh?.();
20685
+ }
20625
20686
  shared() {
20626
20687
  if (!this.leader || this.ownerOf.size > 0 || this.tokens.size > 0) return true;
20627
20688
  return this.peers?.crowded() === true;
@@ -25354,7 +25415,8 @@ var Launcher = class {
25354
25415
  cpu: this.cpuTotal(),
25355
25416
  wasm: this.memories.count(),
25356
25417
  peers: Number(this.locks.shared?.() === true),
25357
- fsCalls: servedFsCalls()
25418
+ fsCalls: servedFsCalls(),
25419
+ opfsCalls: this.rootFs.opfsCalls?.() ?? 0
25358
25420
  }),
25359
25421
  sudo: (call, signal) => this.sudo(pid, call, signal),
25360
25422
  crontab: (call) => this.crontab(pid, call),