Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to request stats for a Vat. #411

Merged
merged 3 commits into from
Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,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 @@ -656,7 +662,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
29 changes: 25 additions & 4 deletions packages/SwingSet/src/kernel/state/vatKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ import { insistVatID } from '../id';

// 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 @@ -101,6 +107,20 @@ export function makeVatKeeper(
storage.set(`${vatID}.t.${id}`, JSON.stringify(msg));
}

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

// pretty print for logging and testing
function dumpState() {
const res = [];
Expand All @@ -123,6 +143,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 @@ -288,6 +288,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 @@ -385,6 +389,7 @@ export default function makeVatManager(
deliverOneMessage,
deliverOneNotification,
replayTranscript,
vatStats,
};
return manager;
}
10 changes: 10 additions & 0 deletions packages/SwingSet/test/vat-admin/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ export default function setup(syscall, state, helpers) {
log(await E(vatAdminSvc).createVat(src));
return;
}
case 'vatStats': {
log(`starting stats test`);
const src = `${serviceHolder.build}`;
const vatAdminSvc = await E(vats.vatAdmin).createVatAdminService(
devices.vatAdmin,
);
const { adminNode } = await E(vatAdminSvc).createVat(src);
log(await E(adminNode).adminData());
return;
}
default:
throw new Error(`unknown argv mode '${argv[0]}'`);
}
Expand Down
19 changes: 19 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,22 @@ 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}',
]);
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);
});