Skip to content

Commit 4d5574b

Browse files
committed
fix(swing-store): replace getAllState/etc with a debug facet
Previously, `getAllState` and `setAllState` were swing-store helper methods which copy (or set) all the state of a store at once, used exclusively for testing. These tests would either want to inspect the swing-store contents directly, or clone a swing-store for e.g. replay testing. This commit replaces both with a new `debug` facet (a sibling of `kernelStorage` and `hostStorage`), which offers two methods. `debug.dump()` returns a JS Object with the store data in an easy-to-examine format (`dump.kvEntries['key']=value`, `dump.streams[vatID]=[..]`, and `dump.snapshots[vatID] = {endPos, hash, compressedSnapshot }`. For cloning, `debug.serialize()` returns a Buffer that has a raw copy of the SQLite backing store. This can be used to make a new DB by passing it as an option to `initSwingStore`: ```js const serialized = swingstore1.debug.serialize(); const swingstore2 = initSwingStore(null, { serialized }); ``` Note that both `.serialize()` and `{ serialized }` require an in-RAM database, rather than an on-disk one. It also cleans up the streamstore types exports a bit.
1 parent ad46cba commit 4d5574b

16 files changed

+265
-287
lines changed

packages/SwingSet/test/change-parameters/test-change-parameters.js

+1-12
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,14 @@ import { test } from '../../tools/prepare-test-env-ava.js';
33

44
// eslint-disable-next-line import/order
55
import { assert } from '@agoric/assert';
6-
import { initSwingStore, getAllState } from '@agoric/swing-store';
6+
import { initSwingStore } from '@agoric/swing-store';
77
import { initializeSwingset, makeSwingsetController } from '../../src/index.js';
88
import { kunser } from '../../src/lib/kmarshal.js';
99

1010
function bfile(name) {
1111
return new URL(name, import.meta.url).pathname;
1212
}
1313

14-
// eslint-disable-next-line no-unused-vars
15-
function dumpState(kernelStorage, vatID) {
16-
const s = getAllState(kernelStorage).kvStuff;
17-
const keys = Array.from(Object.keys(s)).sort();
18-
for (const k of keys) {
19-
if (k.startsWith(`${vatID}.vs.`)) {
20-
console.log(k, s[k]);
21-
}
22-
}
23-
}
24-
2514
async function testChangeParameters(t) {
2615
const config = {
2716
bootstrap: 'bootstrap',

packages/SwingSet/test/devices/test-devices.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { test } from '../../tools/prepare-test-env-ava.js';
33

44
import bundleSource from '@endo/bundle-source';
5-
import { initSwingStore, getAllState } from '@agoric/swing-store';
5+
import { initSwingStore } from '@agoric/swing-store';
66
import { parse } from '@endo/marshal';
77

88
import {
@@ -211,7 +211,7 @@ test.serial('d2.5', async t => {
211211
});
212212

213213
test.serial('device state', async t => {
214-
const kernelStorage = initSwingStore().kernelStorage;
214+
const { kernelStorage, debug } = initSwingStore();
215215
const config = {
216216
bootstrap: 'bootstrap',
217217
vats: {
@@ -236,7 +236,7 @@ test.serial('device state', async t => {
236236
const d3 = c1.deviceNameToID('d3');
237237
await c1.run();
238238
t.deepEqual(c1.dump().log, ['undefined', 'w+r', 'called', 'got {"s":"new"}']);
239-
const s = getAllState(kernelStorage).kvStuff;
239+
const s = debug.dump().kvEntries;
240240
t.deepEqual(JSON.parse(s[`${d3}.deviceState`]), kser({ s: 'new' }));
241241
t.deepEqual(JSON.parse(s[`${d3}.o.nextID`]), 10);
242242
});

packages/SwingSet/test/promise-watcher/test-promise-watcher.js

+1-12
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,13 @@ import { test } from '../../tools/prepare-test-env-ava.js';
88
// eslint-disable-next-line import/order
99
import { assert } from '@agoric/assert';
1010
// eslint-disable-next-line import/order
11-
import { initSwingStore, getAllState } from '@agoric/swing-store';
11+
import { initSwingStore } from '@agoric/swing-store';
1212
import { initializeSwingset, makeSwingsetController } from '../../src/index.js';
1313

1414
function bfile(name) {
1515
return new URL(name, import.meta.url).pathname;
1616
}
1717

18-
// eslint-disable-next-line no-unused-vars
19-
function dumpState(kernelStorage, vatID) {
20-
const s = getAllState(kernelStorage).kvStuff;
21-
const keys = Array.from(Object.keys(s)).sort();
22-
for (const k of keys) {
23-
if (k.startsWith(`${vatID}.vs.`)) {
24-
console.log(k, s[k]);
25-
}
26-
}
27-
}
28-
2918
async function testPromiseWatcher(t) {
3019
const config = {
3120
includeDevDependencies: true, // for vat-data

packages/SwingSet/test/test-activityhash-vs-start.js

+8-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { test } from '../tools/prepare-test-env-ava.js';
33

44
// eslint-disable-next-line import/order
5-
import { initSwingStore, getAllState, setAllState } from '@agoric/swing-store';
5+
import { initSwingStore } from '@agoric/swing-store';
66
import { initializeSwingset, makeSwingsetController } from '../src/index.js';
77
import { buildTimer } from '../src/devices/timer/timer.js';
88

@@ -38,7 +38,7 @@ test.serial('restarting kernel does not change activityhash', async t => {
3838
const deviceEndowments1 = {
3939
timer: { ...timer1.endowments },
4040
};
41-
const ks1 = initSwingStore().kernelStorage;
41+
const { kernelStorage: ks1, debug: debug1 } = initSwingStore();
4242
// console.log(`--c1 build`);
4343
await initializeSwingset(config, [], ks1);
4444
const c1 = await makeSwingsetController(ks1, deviceEndowments1);
@@ -48,8 +48,8 @@ test.serial('restarting kernel does not change activityhash', async t => {
4848
// console.log(`--c1 run1`);
4949
await c1.run();
5050

51-
// console.log(`--c1 getAllState`);
52-
const state = getAllState(ks1);
51+
// console.log(`--c1 serialize`);
52+
const serialized = debug1.serialize();
5353
// console.log(`ah: ${c1.getActivityhash()}`);
5454

5555
// console.log(`--c1 poll1`);
@@ -70,8 +70,7 @@ test.serial('restarting kernel does not change activityhash', async t => {
7070
const deviceEndowments2 = {
7171
timer: { ...timer2.endowments },
7272
};
73-
const ks2 = initSwingStore().kernelStorage;
74-
setAllState(ks2, state);
73+
const { kernelStorage: ks2 } = initSwingStore(null, { serialized });
7574
// console.log(`--c2 build`);
7675
const c2 = await makeSwingsetController(ks2, deviceEndowments2);
7776
// console.log(`ah: ${c2.getActivityhash()}`);
@@ -102,14 +101,14 @@ test.serial('comms initialize is deterministic', async t => {
102101
const config = {};
103102
config.bootstrap = 'bootstrap';
104103
config.vats = { bootstrap: { sourceSpec } };
105-
const ks1 = initSwingStore().kernelStorage;
104+
const { kernelStorage: ks1, debug: debug1 } = initSwingStore();
106105
await initializeSwingset(config, [], ks1);
107106
const c1 = await makeSwingsetController(ks1, {});
108107
c1.pinVatRoot('bootstrap');
109108
// the bootstrap message will cause comms to initialize itself
110109
await c1.run();
111110

112-
const state = getAllState(ks1);
111+
const serialized = debug1.serialize();
113112

114113
// but the second message should not
115114
c1.queueToVatRoot('bootstrap', 'addRemote', ['remote2']);
@@ -118,8 +117,7 @@ test.serial('comms initialize is deterministic', async t => {
118117
await c1.shutdown();
119118

120119
// a kernel restart is loading a new kernel from the same state
121-
const ks2 = initSwingStore().kernelStorage;
122-
setAllState(ks2, state);
120+
const { kernelStorage: ks2 } = initSwingStore(null, { serialized });
123121
const c2 = await makeSwingsetController(ks2, {});
124122

125123
// the "am I already initialized?" check must be identical to the

packages/SwingSet/test/test-state.js

+28-39
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { test } from '../tools/prepare-test-env-ava.js';
44
// eslint-disable-next-line import/order
55
import { createHash } from 'crypto';
6-
import { initSwingStore, getAllState, setAllState } from '@agoric/swing-store';
6+
import { initSwingStore } from '@agoric/swing-store';
77
import makeKernelKeeper from '../src/kernel/state/kernelKeeper.js';
88
import { makeKernelStats } from '../src/kernel/state/stats.js';
99
import { KERNEL_STATS_METRICS } from '../src/kernel/metrics.js';
@@ -15,8 +15,8 @@ import {
1515

1616
const ignoredStateKeys = ['activityhash', 'kernelStats', 'local.kernelStats'];
1717

18-
function checkState(t, getState, expected) {
19-
const state = getState();
18+
function checkState(t, dump, expected) {
19+
const state = dump().kvEntries;
2020
const got = [];
2121
for (const key of Object.getOwnPropertyNames(state)) {
2222
if (!ignoredStateKeys.includes(key)) {
@@ -36,7 +36,7 @@ function checkState(t, getState, expected) {
3636
t.deepEqual(got.sort(compareStrings), expected.sort(compareStrings));
3737
}
3838

39-
async function testStorage(t, s, getState, commit) {
39+
async function testStorage(t, s, dump, commit) {
4040
t.falsy(s.has('missing'));
4141
t.is(s.get('missing'), undefined);
4242

@@ -59,28 +59,23 @@ async function testStorage(t, s, getState, commit) {
5959
t.deepEqual(Array.from(s.getKeys('foo1', 'foo4')), ['foo1', 'foo3']);
6060

6161
if (commit) {
62-
checkState(t, getState, []);
62+
checkState(t, dump, []);
6363
await commit();
6464
}
65-
checkState(t, getState, [
65+
checkState(t, dump, [
6666
['foo', 'f'],
6767
['foo1', 'f1'],
6868
['foo3', 'f3'],
6969
]);
7070
}
7171

7272
test('storageInMemory', async t => {
73-
const kernelStorage = initSwingStore(null).kernelStorage;
74-
await testStorage(
75-
t,
76-
kernelStorage.kvStore,
77-
() => getAllState(kernelStorage).kvStuff,
78-
null,
79-
);
73+
const { kernelStorage, debug } = initSwingStore(null);
74+
await testStorage(t, kernelStorage.kvStore, debug.dump, null);
8075
});
8176

8277
test('storage helpers', t => {
83-
const kernelStorage = initSwingStore(null).kernelStorage;
78+
const { kernelStorage, debug } = initSwingStore(null);
8479
const kv = kernelStorage.kvStore;
8580

8681
kv.set('foo.0', 'f0');
@@ -89,7 +84,7 @@ test('storage helpers', t => {
8984
kv.set('foo.3', 'f3');
9085
// omit foo.4
9186
kv.set('foo.5', 'f5');
92-
checkState(t, () => getAllState(kernelStorage).kvStuff, [
87+
checkState(t, debug.dump, [
9388
['foo.0', 'f0'],
9489
['foo.1', 'f1'],
9590
['foo.2', 'f2'],
@@ -114,20 +109,20 @@ test('storage helpers', t => {
114109
// zero, so if there is a gap in the key sequence (e.g., 'foo.4' in the
115110
// above), they stop counting when they hit it
116111
t.truthy(kv.has('foo.5'));
117-
checkState(t, () => getAllState(kernelStorage).kvStuff, [['foo.5', 'f5']]);
112+
checkState(t, debug.dump, [['foo.5', 'f5']]);
118113
});
119114

120115
function buildKeeperStorageInMemory() {
121-
const kernelStorage = initSwingStore(null).kernelStorage;
116+
const { kernelStorage, debug } = initSwingStore(null);
122117
return {
123-
getState: () => getAllState(kernelStorage).kvStuff,
118+
...debug, // serialize, dump
124119
...kernelStorage,
125120
};
126121
}
127122

128-
function duplicateKeeper(getState) {
129-
const kernelStorage = initSwingStore(null).kernelStorage;
130-
setAllState(kernelStorage, { kvStuff: getState(), streamStuff: new Map() });
123+
function duplicateKeeper(serialize) {
124+
const serialized = serialize();
125+
const { kernelStorage } = initSwingStore(null, { serialized });
131126
const kernelKeeper = makeKernelKeeper(kernelStorage, null);
132127
kernelKeeper.loadStats();
133128
return kernelKeeper;
@@ -147,14 +142,13 @@ test('kernelStorage param guards', async t => {
147142

148143
test('kernel state', async t => {
149144
const store = buildKeeperStorageInMemory();
150-
const { getState } = store;
151145
const k = makeKernelKeeper(store, null);
152146
t.truthy(!k.getInitialized());
153147
k.createStartingKernelState({ defaultManagerType: 'local' });
154148
k.setInitialized();
155149

156150
k.emitCrankHashes();
157-
checkState(t, getState, [
151+
checkState(t, store.dump, [
158152
['crankNumber', '0'],
159153
['initialized', 'true'],
160154
['gcActions', '[]'],
@@ -180,7 +174,6 @@ test('kernel state', async t => {
180174

181175
test('kernelKeeper vat names', async t => {
182176
const store = buildKeeperStorageInMemory();
183-
const { getState } = store;
184177
const k = makeKernelKeeper(store, null);
185178
k.createStartingKernelState({ defaultManagerType: 'local' });
186179

@@ -190,7 +183,7 @@ test('kernelKeeper vat names', async t => {
190183
t.is(v2, 'v2');
191184

192185
k.emitCrankHashes();
193-
checkState(t, getState, [
186+
checkState(t, store.dump, [
194187
['crankNumber', '0'],
195188
['gcActions', '[]'],
196189
['runQueue', '[1,1]'],
@@ -220,7 +213,7 @@ test('kernelKeeper vat names', async t => {
220213
t.is(k.getVatIDForName('Frank'), v2);
221214
t.is(k.allocateVatIDForNameIfNeeded('Frank'), v2);
222215

223-
const k2 = duplicateKeeper(getState);
216+
const k2 = duplicateKeeper(store.serialize);
224217
t.deepEqual(k.getStaticVats(), [
225218
['Frank', 'v2'],
226219
['vatname5', 'v1'],
@@ -231,7 +224,6 @@ test('kernelKeeper vat names', async t => {
231224

232225
test('kernelKeeper device names', async t => {
233226
const store = buildKeeperStorageInMemory();
234-
const { getState } = store;
235227
const k = makeKernelKeeper(store, null);
236228
k.createStartingKernelState({ defaultManagerType: 'local' });
237229

@@ -241,7 +233,7 @@ test('kernelKeeper device names', async t => {
241233
t.is(d8, 'd8');
242234

243235
k.emitCrankHashes();
244-
checkState(t, getState, [
236+
checkState(t, store.dump, [
245237
['crankNumber', '0'],
246238
['gcActions', '[]'],
247239
['runQueue', '[1,1]'],
@@ -271,7 +263,7 @@ test('kernelKeeper device names', async t => {
271263
t.is(k.getDeviceIDForName('Frank'), d8);
272264
t.is(k.allocateDeviceIDForNameIfNeeded('Frank'), d8);
273265

274-
const k2 = duplicateKeeper(getState);
266+
const k2 = duplicateKeeper(store.serialize);
275267
t.deepEqual(k.getDevices(), [
276268
['Frank', 'd8'],
277269
['devicename5', 'd7'],
@@ -282,7 +274,6 @@ test('kernelKeeper device names', async t => {
282274

283275
test('kernelKeeper runQueue', async t => {
284276
const store = buildKeeperStorageInMemory();
285-
const { getState } = store;
286277
const k = makeKernelKeeper(store, null);
287278
k.createStartingKernelState({ defaultManagerType: 'local' });
288279

@@ -298,7 +289,7 @@ test('kernelKeeper runQueue', async t => {
298289
t.is(k.getRunQueueLength(), 2);
299290

300291
k.emitCrankHashes();
301-
const k2 = duplicateKeeper(getState);
292+
const k2 = duplicateKeeper(store.serialize);
302293

303294
t.deepEqual(k.getNextRunQueueMsg(), { type: 'send', stuff: 'awesome' });
304295
t.falsy(k.isRunQueueEmpty());
@@ -325,7 +316,6 @@ test('kernelKeeper runQueue', async t => {
325316

326317
test('kernelKeeper promises', async t => {
327318
const store = buildKeeperStorageInMemory();
328-
const { getState } = store;
329319
const k = makeKernelKeeper(store, null);
330320
k.createStartingKernelState({ defaultManagerType: 'local' });
331321

@@ -342,7 +332,7 @@ test('kernelKeeper promises', async t => {
342332
t.falsy(k.hasKernelPromise('kp99'));
343333

344334
k.emitCrankHashes();
345-
let k2 = duplicateKeeper(getState);
335+
let k2 = duplicateKeeper(store.serialize);
346336

347337
t.deepEqual(k2.getKernelPromise(p1), {
348338
state: 'unresolved',
@@ -365,7 +355,7 @@ test('kernelKeeper promises', async t => {
365355
});
366356

367357
k.emitCrankHashes();
368-
k2 = duplicateKeeper(getState);
358+
k2 = duplicateKeeper(store.serialize);
369359
t.deepEqual(k2.getKernelPromise(p1), {
370360
state: 'unresolved',
371361
policy: 'ignore',
@@ -405,7 +395,7 @@ test('kernelKeeper promises', async t => {
405395
expectedAcceptanceQueue.push({ type: 'send', target: 'kp40', msg: m2 });
406396

407397
k.emitCrankHashes();
408-
k2 = duplicateKeeper(getState);
398+
k2 = duplicateKeeper(store.serialize);
409399
t.deepEqual(k2.getKernelPromise(p1).queue, [m1, m2]);
410400

411401
const ko = k.addKernelObject('v1');
@@ -423,7 +413,7 @@ test('kernelKeeper promises', async t => {
423413
// all the subscriber/queue stuff should be gone
424414
k.emitCrankHashes();
425415

426-
checkState(t, getState, [
416+
checkState(t, store.dump, [
427417
['crankNumber', '0'],
428418
['device.nextID', '7'],
429419
['vat.nextID', '1'],
@@ -491,7 +481,6 @@ test('kernelKeeper promise reject', async t => {
491481

492482
test('vatKeeper', async t => {
493483
const store = buildKeeperStorageInMemory();
494-
const { getState } = store;
495484
const k = makeKernelKeeper(store, null);
496485
k.createStartingKernelState({ defaultManagerType: 'local' });
497486

@@ -509,7 +498,7 @@ test('vatKeeper', async t => {
509498
t.is(vk.nextDeliveryNum(), 1n);
510499

511500
k.emitCrankHashes();
512-
let vk2 = duplicateKeeper(getState).provideVatKeeper(v1);
501+
let vk2 = duplicateKeeper(store.serialize).provideVatKeeper(v1);
513502
t.is(vk2.mapVatSlotToKernelSlot(vatExport1), kernelExport1);
514503
t.is(vk2.mapKernelSlotToVatSlot(kernelExport1), vatExport1);
515504
t.is(vk2.nextDeliveryNum(), 2n);
@@ -522,7 +511,7 @@ test('vatKeeper', async t => {
522511
t.is(vk.mapVatSlotToKernelSlot(vatImport2), kernelImport2);
523512

524513
k.emitCrankHashes();
525-
vk2 = duplicateKeeper(getState).provideVatKeeper(v1);
514+
vk2 = duplicateKeeper(store.serialize).provideVatKeeper(v1);
526515
t.is(vk2.mapKernelSlotToVatSlot(kernelImport2), vatImport2);
527516
t.is(vk2.mapVatSlotToKernelSlot(vatImport2), kernelImport2);
528517
});

0 commit comments

Comments
 (0)