Skip to content

Commit

Permalink
chore(swingset): track vat deliveryNum persistently
Browse files Browse the repository at this point in the history
Previously, the concept of "deliveryNum" (a counter of how many deliveries
have been made to any particular vat) only existed within the slogger, which
used an internal (ephemeral) counter, and attached the count to each slogfile
delivery record. That meant two successive slogfiles, created by two
successive launches of the same kernel (one building upon the saved state of
the other), would get overlapping delivery numbers. The problem would get
worse with the #2277 VatWarehouse, which will create a new `vatSlogger` each
time the vat is paged in (multiple times per kernel process).

This moves the `deliveryNum` counter into the kernelDB's durable `kvStore`,
in a new `$vatID.nextDeliveryNum` key. It is incremented for each delivery by
`deliverAndLogToVat()`. The slogger simply receives and remembers
`deliveryNum` (just like what it's always done with `crankNum`), and no
longer attempts to increment a counter itself.

closes #3254
  • Loading branch information
warner committed Jun 7, 2021
1 parent ae2ac52 commit 30b4631
Show file tree
Hide file tree
Showing 8 changed files with 22 additions and 6 deletions.
3 changes: 3 additions & 0 deletions packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,15 @@ export default function buildKernel(
async function deliverAndLogToVat(vatID, kernelDelivery, vatDelivery) {
const vat = ephemeral.vats.get(vatID);
assert(vat);
const vatKeeper = kernelKeeper.getVatKeeper(vatID);
const crankNum = kernelKeeper.getCrankNumber();
const deliveryNum = vatKeeper.nextDeliveryNum(); // increments
/** @typedef { any } FinishFunction TODO: static types for slog? */
/** @type { FinishFunction } */
const finish = kernelSlog.delivery(
vatID,
crankNum,
deliveryNum,
kernelDelivery,
vatDelivery,
);
Expand Down
6 changes: 3 additions & 3 deletions packages/SwingSet/src/kernel/slogger.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export function makeSlogger(slogCallbacks, writeObj) {
function makeVatSlog(vatID) {
let state = IDLE; // or STARTUP or DELIVERY
let crankNum;
let deliveryNum = 0;
let deliveryNum;
let syscallNum;

function assertOldState(exp, msg) {
Expand Down Expand Up @@ -137,10 +137,11 @@ export function makeSlogger(slogCallbacks, writeObj) {
}

// kd: kernelDelivery, vd: vatDelivery
function delivery(newCrankNum, kd, vd) {
function delivery(newCrankNum, newDeliveryNum, kd, vd) {
assertOldState(IDLE, 'reentrant delivery?');
state = DELIVERY;
crankNum = newCrankNum;
deliveryNum = newDeliveryNum;
const when = { crankNum, vatID, deliveryNum };
write({ type: 'deliver', ...when, kd, vd });
syscallNum = 0;
Expand All @@ -149,7 +150,6 @@ export function makeSlogger(slogCallbacks, writeObj) {
function finish(dr) {
assertOldState(DELIVERY, 'delivery-finish called twice?');
write({ type: 'deliver-result', ...when, dr });
deliveryNum += 1;
state = IDLE;
}
return harden(finish);
Expand Down
1 change: 1 addition & 0 deletions packages/SwingSet/src/kernel/state/kernelKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const enableKernelPromiseGC = true;
// $R is 'R' when reachable, '_' when merely recognizable
// $vatSlot is one of: o+$NN/o-$NN/p+$NN/p-$NN/d+$NN/d-$NN
// v$NN.c.$vatSlot = $kernelSlot = ko$NN/kp$NN/kd$NN
// v$NN.nextDeliveryNum = $NN
// v$NN.t.endPosition = $NN
// v$NN.vs.$key = string

Expand Down
8 changes: 8 additions & 0 deletions packages/SwingSet/src/kernel/state/vatKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export function initializeVatState(kvStore, streamStore, vatID) {
kvStore.set(`${vatID}.o.nextID`, `${FIRST_OBJECT_ID}`);
kvStore.set(`${vatID}.p.nextID`, `${FIRST_PROMISE_ID}`);
kvStore.set(`${vatID}.d.nextID`, `${FIRST_DEVICE_ID}`);
kvStore.set(`${vatID}.nextDeliveryNum`, `0`);
kvStore.set(
`${vatID}.t.endPosition`,
`${JSON.stringify(streamStore.STREAM_START)}`,
Expand Down Expand Up @@ -90,6 +91,12 @@ export function makeVatKeeper(
return harden({ source, options });
}

function nextDeliveryNum() {
const num = Nat(BigInt(kvStore.get(`${vatID}.nextDeliveryNum`)));
kvStore.set(`${vatID}.nextDeliveryNum`, `${num + 1n}`);
return num;
}

function getReachableFlag(kernelSlot) {
const kernelKey = `${vatID}.c.${kernelSlot}`;
const data = kvStore.get(kernelKey);
Expand Down Expand Up @@ -391,6 +398,7 @@ export function makeVatKeeper(
return harden({
setSourceAndOptions,
getSourceAndOptions,
nextDeliveryNum,
importsKernelSlot,
mapVatSlotToKernelSlot,
mapKernelSlotToVatSlot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ async function runOneTest(t, explosion, managerType) {
await c.run();
t.is(JSON.parse(kvStore.get('vat.dynamicIDs')).length, 1);
t.is(kvStore.get(`${root}.owner`), vatID);
t.is(Array.from(kvStore.getKeys(`${vatID}`, `${vatID}/`)).length, 10);
t.is(Array.from(kvStore.getKeys(`${vatID}`, `${vatID}/`)).length, 11);
// neverKPID should still be unresolved
t.is(kvStore.get(`${neverKPID}.state`), 'unresolved');

Expand Down
4 changes: 4 additions & 0 deletions packages/SwingSet/test/test-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -616,11 +616,15 @@ test('vatKeeper', async t => {
t.is(kernelExport1, 'ko20');
t.is(vk.mapVatSlotToKernelSlot(vatExport1), kernelExport1);
t.is(vk.mapKernelSlotToVatSlot(kernelExport1), vatExport1);
t.is(vk.nextDeliveryNum(), 0n);
t.is(vk.nextDeliveryNum(), 1n);

commitCrank();
let vk2 = duplicateKeeper(getState).allocateVatKeeper(v1);
t.is(vk2.mapVatSlotToKernelSlot(vatExport1), kernelExport1);
t.is(vk2.mapKernelSlotToVatSlot(kernelExport1), vatExport1);
t.is(vk2.nextDeliveryNum(), 2n);
t.is(vk2.nextDeliveryNum(), 3n);

const kernelImport2 = k.addKernelObject('v1', 25);
const vatImport2 = vk.mapKernelSlotToVatSlot(kernelImport2);
Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/test/test-syscall-failure.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async function vatSyscallFailure(t, beDynamic) {
'["bootstrap","badvatStatic","vatAdmin","comms","vattp","timer"]',
);
t.is(kvStore.get(`${badVatRootObject}.owner`), badVatID);
t.is(Array.from(kvStore.getKeys(`${badVatID}.`, `${badVatID}/`)).length, 8);
t.is(Array.from(kvStore.getKeys(`${badVatID}.`, `${badVatID}/`)).length, 9);
t.is(kvStore.get('vat.name.badvatStatic'), badVatID);
}
await controller.run();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ test('dead vat state removed', async t => {
const kvStore = hostStorage.kvStore;
t.is(kvStore.get('vat.dynamicIDs'), '["v6"]');
t.is(kvStore.get('ko26.owner'), 'v6');
t.is(Array.from(kvStore.getKeys('v6.', 'v6/')).length, 8);
t.is(Array.from(kvStore.getKeys('v6.', 'v6/')).length, 9);

controller.queueToVatExport('bootstrap', 'o+0', 'phase2', capargs([]));
await controller.run();
Expand Down

0 comments on commit 30b4631

Please sign in to comment.