Skip to content

Commit

Permalink
chore(swingset): add kernelKeeper.getImporters
Browse files Browse the repository at this point in the history
This function takes an object kref and returns a list of vatIDs which have
imported that object. As mentioned in #3223, this would be more efficient
with an index.
  • Loading branch information
warner committed Jun 3, 2021
1 parent c1a162a commit 987c4d4
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
17 changes: 17 additions & 0 deletions packages/SwingSet/src/kernel/state/kernelKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,22 @@ export default function makeKernelKeeper(kvStore, streamStore, kernelSlog) {
return harden(deviceIDs);
}

function getImporters(koid) {
// TODO maintain an index instead of scanning every single vat
const importers = [];
function doesImport(vatID) {
return getVatKeeper(vatID).importsKernelSlot(koid);
}
importers.push(...getDynamicVats().filter(doesImport));
importers.push(
...getStaticVats()
.map(nameAndVatID => nameAndVatID[1])
.filter(doesImport),
);
importers.sort();
return importers;
}

// used for debugging, and tests. This returns a JSON-serializable object.
// It includes references to live (mutable) kernel state, so don't mutate
// the pieces, and be sure to serialize/deserialize before passing it
Expand Down Expand Up @@ -891,6 +907,7 @@ export default function makeKernelKeeper(kvStore, streamStore, kernelSlog) {
addKernelObject,
ownerOfKernelObject,
ownerOfKernelDevice,
getImporters,
deleteKernelObject,

addKernelPromise,
Expand Down
14 changes: 14 additions & 0 deletions packages/SwingSet/src/kernel/state/vatKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,19 @@ export function makeVatKeeper(
kvStore.set(kernelKey, buildReachableAndVatSlot(false, vatSlot));
}

function importsKernelSlot(kernelSlot) {
const kernelKey = `${vatID}.c.${kernelSlot}`;
const data = kvStore.get(kernelKey);
if (data) {
const { vatSlot } = parseReachableAndVatSlot(data);
const { allocatedByVat } = parseVatSlot(vatSlot);
if (!allocatedByVat) {
return true;
}
}
return false;
}

/**
* Provide the kernel slot corresponding to a given vat slot, allocating a
* new one (for exports only) if it doesn't already exist. If we're allowed
Expand Down Expand Up @@ -378,6 +391,7 @@ export function makeVatKeeper(
return harden({
setSourceAndOptions,
getSourceAndOptions,
importsKernelSlot,
mapVatSlotToKernelSlot,
mapKernelSlotToVatSlot,
getReachableFlag,
Expand Down
40 changes: 40 additions & 0 deletions packages/SwingSet/test/test-clist.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,43 @@ test(`clist reachability`, async t => {
t.is(vk.mapVatSlotToKernelSlot('o+3', false), 'ko22');
t.is(s.get(`${vatID}.c.ko22`), '_ o+3');
});

test('getImporters', async t => {
const slog = makeDummySlogger({});
const hostStorage = initSimpleSwingStore();
const { enhancedCrankBuffer: s } = wrapStorage(hostStorage.kvStore);

const kk = makeKernelKeeper(s, hostStorage.streamStore, slog);
kk.createStartingKernelState('local');
const vatID1 = kk.allocateUnusedVatID();
kk.addDynamicVatID(vatID1);
const vk1 = kk.allocateVatKeeper(vatID1);
const vatID2 = kk.allocateUnusedVatID();
kk.addDynamicVatID(vatID2);
const vk2 = kk.allocateVatKeeper(vatID2);
const vatID3 = kk.allocateUnusedVatID();
kk.addDynamicVatID(vatID3);
const vk3 = kk.allocateVatKeeper(vatID3);

const kref = kk.addKernelObject('v1', 1);
t.deepEqual(kk.getImporters(kref), []);

const vref1 = vk1.mapKernelSlotToVatSlot(kref);
t.deepEqual(kk.getImporters(kref), [vatID1]);

// add 3 before 2 to check that the result is really sorted
const vref3 = vk3.mapKernelSlotToVatSlot(kref);
t.deepEqual(kk.getImporters(kref), [vatID1, vatID3]);

const vref2 = vk2.mapKernelSlotToVatSlot(kref);
t.deepEqual(kk.getImporters(kref), [vatID1, vatID2, vatID3]);

vk3.deleteCListEntry(kref, vref3);
t.deepEqual(kk.getImporters(kref), [vatID1, vatID2]);

vk1.deleteCListEntry(kref, vref1);
t.deepEqual(kk.getImporters(kref), [vatID2]);

vk2.deleteCListEntry(kref, vref2);
t.deepEqual(kk.getImporters(kref), []);
});

0 comments on commit 987c4d4

Please sign in to comment.