@ai-ecoverse/slicc-kernel 1.160.2 → 1.161.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.
@@ -1000,6 +1000,11 @@ var RemoteWatch = class {
1000
1000
  mourned = /* @__PURE__ */ new Set();
1001
1001
  others = /* @__PURE__ */ new Map();
1002
1002
  union = /* @__PURE__ */ new Set();
1003
+ myHolds = /* @__PURE__ */ new Map();
1004
+ peerHolds = /* @__PURE__ */ new Map();
1005
+ holdsSent = 0;
1006
+ silent = /* @__PURE__ */ new Set();
1007
+ holders = /* @__PURE__ */ new Set();
1003
1008
  listeners = /* @__PURE__ */ new Set();
1004
1009
  waiting = /* @__PURE__ */ new Map();
1005
1010
  locks;
@@ -1043,7 +1048,7 @@ var RemoteWatch = class {
1043
1048
  this.settled = true;
1044
1049
  this.recount();
1045
1050
  });
1046
- this.channel.postMessage({ hello: this.tab, renames: true });
1051
+ this.channel.postMessage({ hello: this.tab, renames: true, keeps: true });
1047
1052
  }
1048
1053
  async join() {
1049
1054
  if (!this.locks) return;
@@ -1103,8 +1108,12 @@ var RemoteWatch = class {
1103
1108
  return `${this.name}:${tab}`;
1104
1109
  }
1105
1110
  receive(data) {
1111
+ const spoke = data.hello ?? data.here ?? data.tab ?? data.from;
1112
+ if (spoke !== void 0) this.silent.delete(spoke);
1106
1113
  const sender = data.hello ?? data.here ?? (data.paths !== void 0 ? data.tab : void 0);
1107
1114
  if (sender !== void 0 && data.renames) this.ackers.add(sender);
1115
+ const keeper = data.hello ?? data.here;
1116
+ if (keeper !== void 0 && data.keeps) this.holders.add(keeper);
1108
1117
  if (data.hello !== void 0) this.greeted(data.hello);
1109
1118
  if (data.renaming !== void 0 && data.tab !== void 0) this.heard(data);
1110
1119
  if (data.renamed !== void 0) this.renamed?.(data.renamed);
@@ -1115,6 +1124,7 @@ var RemoteWatch = class {
1115
1124
  this.met?.();
1116
1125
  }
1117
1126
  if (data.tab !== void 0 && data.paths !== void 0) this.announced(data);
1127
+ if (data.tab !== void 0 && data.holds !== void 0) this.heldBy(data);
1118
1128
  if (data.ack !== void 0 && data.to === this.tab && data.from !== void 0) {
1119
1129
  this.acked(data.ack, data.from);
1120
1130
  }
@@ -1141,8 +1151,10 @@ var RemoteWatch = class {
1141
1151
  void this.locks.request(name2, async () => {
1142
1152
  this.mourned.delete(peer);
1143
1153
  this.others.delete(peer);
1154
+ this.peerHolds.delete(peer);
1144
1155
  this.peers.delete(peer);
1145
1156
  this.ackers.delete(peer);
1157
+ this.holders.delete(peer);
1146
1158
  this.flushedAt(peer);
1147
1159
  this.rebuild();
1148
1160
  this.recount();
@@ -1155,8 +1167,9 @@ var RemoteWatch = class {
1155
1167
  greeted(peer) {
1156
1168
  this.arrived(peer);
1157
1169
  const answer2 = () => {
1158
- this.channel.postMessage({ here: this.tab, to: peer, renames: true });
1170
+ this.channel.postMessage({ here: this.tab, to: peer, renames: true, keeps: true });
1159
1171
  if (this.mine.length > 0) void this.announce(this.mine);
1172
+ if (this.myHolds.size > 0) this.sendHolds([...this.myHolds], []);
1160
1173
  };
1161
1174
  if (!this.quiet) {
1162
1175
  answer2();
@@ -1179,6 +1192,69 @@ var RemoteWatch = class {
1179
1192
  this.rebuild();
1180
1193
  this.channel.postMessage({ ack: seq2, from: this.tab, to: from });
1181
1194
  }
1195
+ heldBy({ tab, holds: holds2, seq: seq2 }) {
1196
+ const from = tab;
1197
+ const { add, drop } = holds2;
1198
+ const held = this.peerHolds.get(from) ?? /* @__PURE__ */ new Map();
1199
+ for (const path of drop) held.delete(path);
1200
+ for (const [path, fid] of add) held.set(path, fid);
1201
+ if (held.size > 0) this.peerHolds.set(from, held);
1202
+ else this.peerHolds.delete(from);
1203
+ this.channel.postMessage({ ack: seq2, from: this.tab, to: from });
1204
+ }
1205
+ hold(add, drop, wait2) {
1206
+ const fresh3 = add.filter(
1207
+ ([path, fid]) => !this.myHolds.has(path) || this.myHolds.get(path) !== fid
1208
+ );
1209
+ const gone = drop.filter((path) => this.myHolds.has(path));
1210
+ for (const path of gone) this.myHolds.delete(path);
1211
+ for (const [path, fid] of fresh3) this.myHolds.set(path, fid);
1212
+ if (fresh3.length === 0 && gone.length === 0 || this.peers.size === 0)
1213
+ return Promise.resolve();
1214
+ const seq2 = this.sendHolds(fresh3, gone);
1215
+ if (!wait2) return Promise.resolve();
1216
+ const heard = new Set(
1217
+ [...this.peers].filter((peer) => this.holders.has(peer) && !this.silent.has(peer))
1218
+ );
1219
+ return this.acks(seq2, heard, (left) => {
1220
+ for (const peer of left) this.silent.add(peer);
1221
+ });
1222
+ }
1223
+ rehold(from, to) {
1224
+ const add = [];
1225
+ const drop = [];
1226
+ for (const [path, fid] of [...this.myHolds]) {
1227
+ if (path !== from && !path.startsWith(`${from}/`)) continue;
1228
+ const moved2 = to + path.slice(from.length);
1229
+ this.myHolds.delete(path);
1230
+ this.myHolds.set(moved2, fid);
1231
+ drop.push(path);
1232
+ add.push([moved2, fid]);
1233
+ }
1234
+ if (drop.length > 0 && this.peers.size > 0) this.sendHolds(add, drop);
1235
+ }
1236
+ sendHolds(add, drop) {
1237
+ const seq2 = ++this.seq;
1238
+ this.holdsSent++;
1239
+ this.channel.postMessage({ tab: this.tab, holds: { add: [...add], drop: [...drop] }, seq: seq2 });
1240
+ return seq2;
1241
+ }
1242
+ peerHeld(path) {
1243
+ const out = [];
1244
+ for (const [tab, held] of this.peerHolds)
1245
+ if (held.has(path)) out.push({ tab, fid: held.get(path) });
1246
+ return out;
1247
+ }
1248
+ peerHeldPaths() {
1249
+ const out = /* @__PURE__ */ new Set();
1250
+ for (const held of this.peerHolds.values()) for (const path of held.keys()) out.add(path);
1251
+ return [...out].sort();
1252
+ }
1253
+ holdCounts() {
1254
+ let peers = 0;
1255
+ for (const held of this.peerHolds.values()) peers += held.size;
1256
+ return { mine: this.myHolds.size, peers, sent: this.holdsSent };
1257
+ }
1182
1258
  acked(seq2, from) {
1183
1259
  const wait2 = this.waiting.get(seq2);
1184
1260
  if (!wait2) return;
@@ -1193,11 +1269,13 @@ var RemoteWatch = class {
1193
1269
  if (!this.locks) return;
1194
1270
  const held = new Set(((await this.locks.query()).held ?? []).map((lock) => lock.name));
1195
1271
  let left = false;
1196
- for (const tab of /* @__PURE__ */ new Set([...this.others.keys(), ...this.peers])) {
1272
+ for (const tab of /* @__PURE__ */ new Set([...this.others.keys(), ...this.peers, ...this.peerHolds.keys()])) {
1197
1273
  if (!held.has(this.lockOf(tab))) {
1198
1274
  if (this.peers.delete(tab)) left = true;
1199
1275
  this.others.delete(tab);
1276
+ this.peerHolds.delete(tab);
1200
1277
  this.ackers.delete(tab);
1278
+ this.holders.delete(tab);
1201
1279
  }
1202
1280
  }
1203
1281
  this.rebuild();
@@ -1245,8 +1323,9 @@ var RemoteWatch = class {
1245
1323
  renamedTree(lock) {
1246
1324
  this.channel.postMessage({ renamed: lock });
1247
1325
  }
1248
- acks(seq2, from) {
1326
+ acks(seq2, from, missed) {
1249
1327
  if (from.size === 0) return Promise.resolve();
1328
+ const left = new Set(from);
1250
1329
  return new Promise((resolve2) => {
1251
1330
  const done5 = () => {
1252
1331
  clearTimeout(timer);
@@ -1254,10 +1333,11 @@ var RemoteWatch = class {
1254
1333
  resolve2();
1255
1334
  };
1256
1335
  const timer = setTimeout(() => {
1336
+ missed?.(left);
1257
1337
  done5();
1258
1338
  void this.prune();
1259
1339
  }, ANNOUNCE_WAIT_MS);
1260
- this.waiting.set(seq2, { left: new Set(from), done: done5 });
1340
+ this.waiting.set(seq2, { left, done: done5 });
1261
1341
  });
1262
1342
  }
1263
1343
  emit(change) {
@@ -1633,6 +1713,16 @@ var OpfsFs = class {
1633
1713
  return this.remote?.listen(listener) ?? (() => {
1634
1714
  });
1635
1715
  }
1716
+ announceHolds(add, drop, wait2) {
1717
+ return this.remote?.hold(add, drop, wait2) ?? Promise.resolve();
1718
+ }
1719
+ holdCounts() {
1720
+ const remote = this.remote;
1721
+ return remote && { ...remote.holdCounts(), held: remote.peerHeldPaths() };
1722
+ }
1723
+ rehold(from, to) {
1724
+ this.remote?.rehold(from, to);
1725
+ }
1636
1726
  announceWatch(paths) {
1637
1727
  return this.remote?.announce(paths) ?? Promise.resolve();
1638
1728
  }
@@ -8236,7 +8326,7 @@ function satisfies(version, range2) {
8236
8326
  }
8237
8327
 
8238
8328
  // src/version.ts
8239
- var KERNEL_VERSION = true ? "1.160.2" : "0.0.0-dev";
8329
+ var KERNEL_VERSION = true ? "1.161.0" : "0.0.0-dev";
8240
8330
  var OS_RELEASE = "6.0.0-slicc";
8241
8331
  function procVersion() {
8242
8332
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -12880,12 +12970,15 @@ function linkedTo(mount, path) {
12880
12970
  var within6 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
12881
12971
  var HeldSet = class extends Set {
12882
12972
  idle;
12883
- constructor(idle2) {
12973
+ moved;
12974
+ constructor(idle2, moved2) {
12884
12975
  super();
12885
12976
  this.idle = idle2;
12977
+ this.moved = moved2;
12886
12978
  }
12887
12979
  add(holds2) {
12888
12980
  holds2.onIdle = this.idle;
12981
+ holds2.onMoved = this.moved;
12889
12982
  return super.add(holds2);
12890
12983
  }
12891
12984
  doubt(paths, over) {
@@ -12922,6 +13015,7 @@ var HeldPaths = class extends Map {
12922
13015
  doubted = /* @__PURE__ */ new Map();
12923
13016
  doubts = 0;
12924
13017
  onIdle;
13018
+ onMoved;
12925
13019
  keyOf(path) {
12926
13020
  return this.aliases.get(path) ?? path;
12927
13021
  }
@@ -13082,6 +13176,7 @@ var HeldPaths = class extends Map {
13082
13176
  for (const [id2, key] of this.handles) {
13083
13177
  if (within6(key, from)) this.handles.set(id2, to + key.slice(from.length));
13084
13178
  }
13179
+ this.onMoved?.(from, to);
13085
13180
  }
13086
13181
  isRevoked(path) {
13087
13182
  return this.revoked.has(path);
@@ -14709,12 +14804,18 @@ async function holdOp(entry, path, req) {
14709
14804
  if (req.nofollow && !await ownEntry(entry, path, real ?? path)) continue;
14710
14805
  const fid = req.ino === void 0 ? void 0 : await idOf(entry, real ?? path);
14711
14806
  if (!r || !r.missed(path) && !r.changedSince(path, gen) && !r.inFlight?.(path))
14712
- return json2(entry.hold?.(path, on, open2, real, void 0, req.ino, fid) ?? null);
14807
+ return json2(await heldOpen(entry, path, real, req, fid));
14713
14808
  }
14714
14809
  }
14715
14810
  entry.hold?.(path, on, open2, void 0, req.handle);
14716
14811
  return done2;
14717
14812
  }
14813
+ async function heldOpen(entry, path, real, req, fid) {
14814
+ const handle = entry.hold?.(path, true, true, real, void 0, req.ino, fid);
14815
+ if (handle === void 0) return null;
14816
+ await entry.announceHold?.(real ?? path, fid, ((req.mode ?? 0) & HOLD_CREATED) !== 0);
14817
+ return handle;
14818
+ }
14718
14819
  async function idOf(entry, path) {
14719
14820
  return await entry.fileId?.(path)?.catch(() => void 0) ?? void 0;
14720
14821
  }
@@ -15732,6 +15833,10 @@ var SYS_TREE = {
15732
15833
  `,
15733
15834
  slicc_file_ids: (listing) => `${listing.fileIds ?? 0}
15734
15835
  `,
15836
+ slicc_peer_holds: ({ holds: holds2 }) => `${holds2?.mine ?? 0} ${holds2?.peers ?? 0} ${holds2?.sent ?? 0}
15837
+ `,
15838
+ slicc_peer_held: ({ holds: holds2 }) => (holds2?.held ?? []).map((path) => `${path}
15839
+ `).join(""),
15735
15840
  slicc_rename_acks: (listing) => {
15736
15841
  const samples = [...listing.renameAcks?.ackMs ?? []].sort((a, b) => a - b);
15737
15842
  const median = samples[Math.floor(samples.length / 2)] ?? 0;
@@ -26974,6 +27079,7 @@ function holdingToken(opts, holds2, caller) {
26974
27079
  ...opts.statfs ? { statfs: opts.statfs } : {},
26975
27080
  ...opts.renames ? { renames: opts.renames } : {},
26976
27081
  ...opts.fileId ? { fileId: opts.fileId } : {},
27082
+ ...opts.announceHold ? { announceHold: opts.announceHold } : {},
26977
27083
  ...opts.renameSeq ? { renameSeq: opts.renameSeq } : {},
26978
27084
  hold: (path, on, open2, real, handle, ino, fid) => holds2.hold(path, on, open2, real, handle, ino, fid),
26979
27085
  boundIno: holds2.boundIno.bind(holds2),
@@ -30927,7 +31033,12 @@ var Launcher = class {
30927
31033
  identities = { asked: 0, timedOut: 0 };
30928
31034
  nodes;
30929
31035
  unlinked;
30930
- held = new HeldSet((path) => this.released(path));
31036
+ held = new HeldSet(
31037
+ (path) => this.released(path),
31038
+ (from, to) => {
31039
+ if (this.mounts.locate(to) === void 0) this.rootFs.rehold?.(from, to);
31040
+ }
31041
+ );
30931
31042
  processMounts;
30932
31043
  booting = new AbortController();
30933
31044
  fstab = Promise.resolve([]);
@@ -32145,7 +32256,8 @@ var Launcher = class {
32145
32256
  cwdChecks: this.cwds.checks,
32146
32257
  renameAcks: this.rootFs.renameWaits?.(),
32147
32258
  staleFds: staleFdCount(),
32148
- fileIds: this.rootFs.fileIdWrites?.() ?? 0
32259
+ fileIds: this.rootFs.fileIdWrites?.() ?? 0,
32260
+ holds: this.rootFs.holdCounts?.()
32149
32261
  }),
32150
32262
  sudo: (call, signal) => this.sudo(pid, call, signal),
32151
32263
  crontab: (call) => this.crontab(pid, call),
@@ -32157,6 +32269,7 @@ var Launcher = class {
32157
32269
  statfs: (path) => this.mounts.statfs(path),
32158
32270
  renames: (since, held) => this.renameLog.since(since, held),
32159
32271
  fileId: (path) => this.locks.shared?.() === true ? this.rootFileId(path) : void 0,
32272
+ announceHold: (path, fid, created4) => this.locks.shared?.() === true && this.mounts.locate(path) === void 0 ? this.rootFs.announceHolds?.([[path, fid]], [], !created4) : void 0,
32160
32273
  renameSeq: (from, to) => this.renameLog.seqOf(from, to),
32161
32274
  mounts: () => this.mounts.list(),
32162
32275
  mount: (call, signal) => this.processMount(pid, call, signal),
@@ -32598,6 +32711,8 @@ var Launcher = class {
32598
32711
  const at = normalizePath(path);
32599
32712
  this.unlinked.closed(at);
32600
32713
  this.writers?.unlinked.closed(at);
32714
+ if (![...this.held].some((holds2) => holds2.holding(at)))
32715
+ void this.rootFs.announceHolds?.([], [at], false);
32601
32716
  const open2 = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
32602
32717
  if (!open2) void this.mounts.commit(at).catch(() => void 0);
32603
32718
  }