Skip to content

Commit

Permalink
Merge pull request #446 from Agoric/vatStats2
Browse files Browse the repository at this point in the history
Add ability to request stats for a vat
  • Loading branch information
Chris-Hibbert authored Jan 27, 2020
2 parents d9a8d7c + 9dab5a6 commit e99ab36
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 22 deletions.
12 changes: 11 additions & 1 deletion packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,12 @@ export default function buildKernel(kernelEndowments) {
);
}

function collectVatStats(vatID) {
insistVatID(vatID);
const vatManager = ephemeral.vats.get(vatID).manager;
return vatManager.vatStats();
}

async function start(bootstrapVatName, argvString) {
if (started) {
throw new Error('kernel.start already called');
Expand Down Expand Up @@ -641,7 +647,11 @@ export default function buildKernel(kernelEndowments) {
if (vatAdminDevSetup) {
const params = {
setup: vatAdminDevSetup,
endowments: { create: createVatDynamically /* vatStats, terminate */ },
endowments: {
create: createVatDynamically,
stats: collectVatStats,
/* terminate */
},
};
genesisDevices.set('vatAdmin', params);
}
Expand Down
33 changes: 29 additions & 4 deletions packages/SwingSet/src/kernel/state/vatKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@ import kdebug from '../kdebug';

// makeVatKeeper is a pure function: all state is kept in the argument object

// TODO: tests rely on these numbers and haven't been updated to use names.
const FIRST_OBJECT_ID = 50;
const FIRST_PROMISE_ID = 60;
const FIRST_DEVICE_ID = 70;
const FIRST_TRANSCRIPT_ID = 0;

export function initializeVatState(storage, vatID) {
storage.set(`${vatID}.o.nextID`, '50');
storage.set(`${vatID}.p.nextID`, '60');
storage.set(`${vatID}.d.nextID`, '70');
storage.set(`${vatID}.t.nextID`, '0');
storage.set(`${vatID}.o.nextID`, `${FIRST_OBJECT_ID}`);
storage.set(`${vatID}.p.nextID`, `${FIRST_PROMISE_ID}`);
storage.set(`${vatID}.d.nextID`, `${FIRST_DEVICE_ID}`);
storage.set(`${vatID}.t.nextID`, `${FIRST_TRANSCRIPT_ID}`);
}

export function makeVatKeeper(
Expand Down Expand Up @@ -95,6 +101,24 @@ export function makeVatKeeper(
storage.set(`${vatID}.t.${id}`, JSON.stringify(msg));
}

function vatStats() {
function getStringAsNat(ostr) {
return Nat(Number(storage.get(ostr)));
}

const objectCount = getStringAsNat(`${vatID}.o.nextID`) - FIRST_OBJECT_ID;
const promiseCount = getStringAsNat(`${vatID}.p.nextID`) - FIRST_PROMISE_ID;
const deviceCount = getStringAsNat(`${vatID}.d.nextID`) - FIRST_DEVICE_ID;
const transcriptCount =
storage.get(`${vatID}.t.nextID`) - FIRST_TRANSCRIPT_ID;
return harden({
objectCount: Nat(objectCount),
promiseCount: Nat(promiseCount),
deviceCount: Nat(deviceCount),
transcriptCount: Nat(Number(transcriptCount)),
});
}

// pretty print for logging and testing
function dumpState() {
const res = [];
Expand All @@ -117,6 +141,7 @@ export function makeVatKeeper(
mapKernelSlotToVatSlot,
getTranscript,
addToTranscript,
vatStats,
dumpState,
});
}
29 changes: 12 additions & 17 deletions packages/SwingSet/src/kernel/vatAdmin/vatAdmin-src.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import harden from '@agoric/harden';
* root device. Selected vats that need to create new vats can be given access
* to the device.
*
* This code runs in the inner part of the device vat. It handles kernel objects
* in serialized format, and can use SO() to send messages to them. The only
* device object exposed to vats is the vat creator. The root objects for the
* new vats are returned as javascript objects.
* This code runs in the inner part of the device vat. The only device object
* exposed to vats is the vat creator. The root objects for the new vats are
* returned as javascript objects.
*
* We don't currently need to use SO, or to maintain state. All functionality is
* provided by calling kernel functions and passing in the VatID. The wrapper
Expand All @@ -22,32 +21,28 @@ import harden from '@agoric/harden';
export default function setup(syscall, state, helpers, endowments) {
const {
create: kernelVatCreationFn,
// stats: kernelVatStatsFn,
stats: kernelVatStatsFn,
// terminate: kernelTerminateFn,
} = endowments;

// call the registered kernel function to create a new vat, and receive a
// vatId in return. Clean up the outgoing and incoming arguments.
function callKernelVatCreation(src) {
return kernelVatCreationFn(`${src}`);
}

// makeRootDevice is called with { _SO, _getDeviceState, _setDeviceState } as
// a parameter, but we don't need these, as discussed above.
// makeRootDevice is called with { SO, getDeviceState, setDeviceState } as
// parameters, but we don't need these, as discussed above.
function makeRootDevice() {
// The Root Device Node.
return harden({
// Called by the wrapper vat to create a new vat. Gets a new ID from the
// kernel's vat creator fn. Remember that the root object will arrive
// separately.
// separately. Clean up the outgoing and incoming arguments.
create(code) {
return callKernelVatCreation(code);
return kernelVatCreationFn(`${code}`);
},
terminate(_vatID) {
// TODO(hibbert)
},
adminStats(_vatID) {
// TODO(hibbert)
// Call the registered kernel function to request vat stats. Clean up the
// outgoing and incoming arguments.
adminStats(vatID) {
return kernelVatStatsFn(`${vatID}`);
},
});
}
Expand Down
5 changes: 5 additions & 0 deletions packages/SwingSet/src/kernel/vatManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ export default function makeVatManager(
);
}

function vatStats() {
return vatKeeper.vatStats();
}

async function deliverOneMessage(target, msg) {
insistMessage(msg);
const targetSlot = mapKernelSlotToVatSlot(target);
Expand Down Expand Up @@ -386,6 +390,7 @@ export default function makeVatManager(
deliverOneMessage,
deliverOneNotification,
replayTranscript,
vatStats,
};
return manager;
}
13 changes: 13 additions & 0 deletions packages/SwingSet/test/vat-admin/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ export default function setup(syscall, state, helpers) {
);
return;
}
case 'vatStats': {
log(`starting stats test`);
const src = `${serviceHolder.build}`;
const vatAdminSvc = await E(vats.vatAdmin).createVatAdminService(
devices.vatAdmin,
);
const { root, adminNode } = await E(vatAdminSvc).createVat(src);
log(await E(adminNode).adminData());
const c = E(root).createRcvr(1);
log(await E(c).increment(3));
log(await E(adminNode).adminData());
return;
}
default:
throw new Error(`unknown argv mode '${argv[0]}'`);
}
Expand Down
22 changes: 22 additions & 0 deletions packages/SwingSet/test/vat-admin/test-innerVat.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,25 @@ test('VatAdmin broken vat creation', async t => {
test('VatAdmin broken vat creation non-SES', async t => {
await testBrokenVatCreation(t, false);
});

async function testGetVatStats(t, withSES) {
const config = await createConfig();
const c = await buildVatController(config, withSES, ['vatStats']);
await c.run();
t.deepEqual(c.dump().log, [
'starting stats test',
'{"objectCount":0,"promiseCount":0,"deviceCount":0,"transcriptCount":0}',
'4',
'{"objectCount":0,"promiseCount":2,"deviceCount":0,"transcriptCount":2}',
]);
await c.run();
t.end();
}

test('VatAdmin get vat stats', async t => {
await testGetVatStats(t, true);
});

test('VatAdmin get vat stats non-SES', async t => {
await testGetVatStats(t, false);
});

0 comments on commit e99ab36

Please sign in to comment.