Skip to content

Commit

Permalink
Initial version of registrar service.
Browse files Browse the repository at this point in the history
Outanding issues:
- no tests
- no iteration
- it uses `get` rather than simple property lookup
  • Loading branch information
dtribble authored and michaelfig committed Oct 22, 2019
1 parent 2874829 commit ca3092b
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
55 changes: 55 additions & 0 deletions more/registrar/registrar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (C) 2019 Agoric, under Apache License 2.0

import harden from "@agoric/harden";
import { insist } from "../../util/insist";
import { generateSparseInts } from "../../util/sparseInts";

// Example REPL imnvocations
// home.registrar~.register('handoff', home.handoffService)
// for (let i = 0; i < 3000; i++) { home.registrar~.register('handoff', home.handoffService); }

// Generated keys must end with _ and digits.
const keyFormat = new RegExp('.*_[0-9]+');

function makeRegistrar(systemVersion, seed = 0) {
// TODO make a better token algorithm.
const useCounts = new Map();
const contents = new Map();
const sparseInts = generateSparseInts(seed);

const registrar = harden({
// Register the value
register(name, value) {
const realName = name.toLowerCase();
const useCount = (useCounts.get(realName) || 0) + 1;
useCounts.set(realName, useCount);
const depth = Math.max(4, Math.floor(Math.log10(useCount) + 1.6));
const uniqueString = sparseInts.next().value.toString();
const keyString = uniqueString.slice(-depth).padStart(depth, '0');
// console.log(`RAND ${useCount} ${uniqueString} ${keyString}`);
const key = `${realName}_${keyString}`;
// if it was a random keyString, then we need to detect collision
insist(!contents.has(key), 'Generated name must not collide');
contents.set(key, value);
return key;
},
get(key, version = null) {
insist(typeof key === 'string')`\
Key must be string ${key}`;
insist(keyFormat.test(key))`\
Key must end with _<digits> ${key}`
if (version) {
insist(version === systemVersion)`\
Key is from incompatible version: ${version} should be ${systemVersion}`;
}
return contents.get(key);
},
keys() {
return contents.keys();
},
});

return registrar;
}

export { makeRegistrar };
29 changes: 29 additions & 0 deletions util/sparseInts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (C) 2019 Agoric, under Apache License 2.0

import harden from '@agoric/harden';
import { insist } from "./insist";

// Generator function to produce a stream of positive integers that are
// sparsely scattered across the number space. This supports IDs that
// are guessable, but for example mistyping a correct ID is unlikely to
// mistakenly match another generated ID.
function* generateSparseInts(seed) {
// This is a linear-feedback shift register with computed startState.
// Thus, it is totally deterministic, but at least looks a little random
// and so can be used for e.g., colors in a game or the gallery

/* eslint-disable no-bitwise */
const mask = 0xffffffff;
const startState = Math.floor(seed * mask) ^ 0xdeadbeef;
let lfsr = startState;
while (true) {
lfsr ^= lfsr >>> 7;
lfsr ^= (lfsr << 9) & mask;
lfsr ^= lfsr >>> 13;
const rand = (Math.floor(lfsr) % 0x800000) + 0x7fffff;
yield rand;
}
/* eslint-enable no-bitwise */
}
harden(generateSparseInts);
export { generateSparseInts };

0 comments on commit ca3092b

Please sign in to comment.