Commit 0de9abab60ad6c7b9852a3219889dc1a080484d5
Merge branch 'master' into greenkeeper/documentation-6.0.0
wanderer authored on 3/21/2018, 6:26:19 PMGitHub committed on 3/21/2018, 6:26:19 PM
Parent: cffaab0554c3a8228f13ad2e78df2cc6aab77296
Parent: 8aa474dcde21c44a2049cae1deeb33baa977dad8
Files changed
actor.js | ||
---|---|---|
@@ -1,7 +1,4 @@ | ||
1 | -const Pipe = require('buffer-pipe') | |
2 | -const leb128 = require('leb128').unsigned | |
3 | - | |
4 | 1 | module.exports = class Actor { |
5 | 2 | /** |
6 | 3 | * the Actor manages the varous message passing functions and provides |
7 | 4 | * an interface for the containers to use |
@@ -19,25 +16,15 @@ | ||
19 | 16 | this.running = false |
20 | 17 | this.container = new this.Container(this) |
21 | 18 | } |
22 | 19 | |
23 | - serializeMetaData () { | |
24 | - return Actor.serializeMetaData(this.type, this.nonce) | |
25 | - } | |
26 | - | |
27 | - getFuncRef (name) { | |
28 | - return { | |
29 | - name, | |
30 | - destId: this.id | |
31 | - } | |
32 | - } | |
33 | - | |
34 | 20 | /** |
35 | 21 | * Runs the shutdown routine for the actor |
36 | 22 | */ |
37 | 23 | async shutdown () { |
38 | - await this.state.done() | |
39 | - this.state.root['/'][3] = this.serializeMetaData() | |
24 | + await this.tree.set(this.id.id, [this.type, this.nonce]) | |
25 | + const state = await this.tree.get(this.id.id) | |
26 | + return this.tree.graph.set(state.root, '2', this.storage) | |
40 | 27 | } |
41 | 28 | |
42 | 29 | /** |
43 | 30 | * Runs the startup routine for the actor |
@@ -61,9 +48,9 @@ | ||
61 | 48 | await this.container.onMessage(message) |
62 | 49 | } catch (e) { |
63 | 50 | message.emit('execution:error', e) |
64 | 51 | } |
65 | - message.emit('done') | |
52 | + message.emit('done', this) | |
66 | 53 | } |
67 | 54 | |
68 | 55 | /** |
69 | 56 | * updates the number of ticks that the actor has run |
@@ -103,22 +90,5 @@ | ||
103 | 90 | message._fromId = this.id |
104 | 91 | |
105 | 92 | this.hypervisor.scheduler.queue([message]) |
106 | 93 | } |
107 | - | |
108 | - static serializeMetaData (type, nonce = 0) { | |
109 | - const p = new Pipe() | |
110 | - leb128.write(type, p) | |
111 | - leb128.write(nonce, p) | |
112 | - return p.buffer | |
113 | - } | |
114 | - | |
115 | - static deserializeMetaData (buffer) { | |
116 | - const pipe = new Pipe(buffer) | |
117 | - const type = leb128.read(pipe) | |
118 | - const nonce = leb128.read(pipe) | |
119 | - return { | |
120 | - nonce, | |
121 | - type | |
122 | - } | |
123 | - } | |
124 | 94 | } |
customTypes.js | ||
---|---|---|
@@ -4,8 +4,11 @@ | ||
4 | 4 | |
5 | 5 | const LANGUAGE_TYPES = { |
6 | 6 | 'actor': 0x0, |
7 | 7 | 'buf': 0x1, |
8 | + 'elem': 0x2, | |
9 | + 'link': 0x3, | |
10 | + 'id': 0x4, | |
8 | 11 | 'i32': 0x7f, |
9 | 12 | 'i64': 0x7e, |
10 | 13 | 'f32': 0x7d, |
11 | 14 | 'f64': 0x7c, |
@@ -14,8 +17,11 @@ | ||
14 | 17 | 'block_type': 0x40, |
15 | 18 | |
16 | 19 | 0x0: 'actor', |
17 | 20 | 0x1: 'buf', |
21 | + 0x02: 'elem', | |
22 | + 0x03: 'link', | |
23 | + 0x04: 'id', | |
18 | 24 | 0x7f: 'i32', |
19 | 25 | 0x7e: 'i64', |
20 | 26 | 0x7d: 'f32', |
21 | 27 | 0x7c: 'f64', |
@@ -25,28 +31,54 @@ | ||
25 | 31 | } |
26 | 32 | |
27 | 33 | function encodeJSON (json) { |
28 | 34 | const stream = new Stream() |
29 | - encodeCustomSection('type', json, stream, encodeType) | |
35 | + encodeCustomSection('types', json, stream, encodeType) | |
30 | 36 | encodeCustomSection('typeMap', json, stream, encodeTypeMap) |
37 | + encodeCustomSection('globals', json, stream, encodeGlobals) | |
31 | 38 | |
32 | 39 | return stream.buffer |
33 | 40 | } |
34 | 41 | |
35 | 42 | function encodeCustomSection (name, json, stream, encodingFunc) { |
36 | - stream.write([0]) | |
37 | 43 | let payload = new Stream() |
44 | + json = json[name] | |
38 | 45 | |
39 | - // encode type | |
40 | - leb.unsigned.write(name.length, payload) | |
41 | - payload.write(name) | |
42 | - encodingFunc(json[name], payload) | |
43 | - // write the size of the payload | |
44 | - leb.unsigned.write(payload.bytesWrote, stream) | |
45 | - stream.write(payload.buffer) | |
46 | + if (json) { | |
47 | + stream.write([0]) | |
48 | + // encode type | |
49 | + leb.unsigned.write(name.length, payload) | |
50 | + payload.write(name) | |
51 | + encodingFunc(json, payload) | |
52 | + // write the size of the payload | |
53 | + leb.unsigned.write(payload.bytesWrote, stream) | |
54 | + stream.write(payload.buffer) | |
55 | + } | |
46 | 56 | return stream |
47 | 57 | } |
48 | 58 | |
59 | +function encodeGlobals (json, stream) { | |
60 | + leb.unsigned.write(json.length, stream) | |
61 | + for (const entry of json) { | |
62 | + leb.unsigned.write(entry.index, stream) | |
63 | + leb.unsigned.write(LANGUAGE_TYPES[entry.type], stream) | |
64 | + } | |
65 | + return stream | |
66 | +} | |
67 | + | |
68 | +function decodeGlobals (buf) { | |
69 | + const stream = new Stream(Buffer.from(buf)) | |
70 | + let numOfEntries = leb.unsigned.read(stream) | |
71 | + const json = [] | |
72 | + while (numOfEntries--) { | |
73 | + json.push({ | |
74 | + index: leb.unsigned.readBn(stream).toNumber(), | |
75 | + type: LANGUAGE_TYPES[leb.unsigned.readBn(stream).toNumber()] | |
76 | + }) | |
77 | + } | |
78 | + return json | |
79 | +} | |
80 | + | |
49 | 81 | function encodeTypeMap (json, stream) { |
50 | 82 | leb.unsigned.write(json.length, stream) |
51 | 83 | for (let entry of json) { |
52 | 84 | leb.unsigned.write(entry.func, stream) |
@@ -82,9 +114,8 @@ | ||
82 | 114 | binEntries.write(entry.params.map(type => LANGUAGE_TYPES[type])) // the paramter types |
83 | 115 | } |
84 | 116 | |
85 | 117 | binEntries.write([entry.return_type ? 1 : 0]) // number of return types |
86 | - | |
87 | 118 | if (entry.return_type) { |
88 | 119 | binEntries.write([LANGUAGE_TYPES[entry.return_type]]) |
89 | 120 | } |
90 | 121 | } |
@@ -136,28 +167,34 @@ | ||
136 | 167 | function mergeTypeSections (json) { |
137 | 168 | const result = { |
138 | 169 | types: [], |
139 | 170 | indexes: {}, |
140 | - exports: {} | |
171 | + exports: {}, | |
172 | + globals: [] | |
141 | 173 | } |
142 | 174 | |
143 | - const wantedSections = ['custom', 'custom', 'type', 'import', 'function', 'export'] | |
175 | + const wantedSections = ['types', 'typeMap', 'globals', 'type', 'import', 'function', 'export'] | |
144 | 176 | const iterator = findSections(json, wantedSections) |
145 | 177 | const mappedFuncs = new Map() |
146 | 178 | const mappedTypes = new Map() |
147 | - const {value: customType} = iterator.next('custom') | |
179 | + const {value: customType} = iterator.next() | |
148 | 180 | if (customType) { |
149 | 181 | const type = decodeType(customType.payload) |
150 | 182 | result.types = type |
151 | 183 | } |
152 | - let {value: typeMap} = iterator.next('custom') | |
184 | + let {value: typeMap} = iterator.next() | |
153 | 185 | if (typeMap) { |
154 | 186 | decodeTypeMap(typeMap.payload).forEach(map => mappedFuncs.set(map.func, map.type)) |
155 | 187 | } |
156 | 188 | |
157 | - const {value: type} = iterator.next('type') | |
158 | - const {value: imports = {entries: []}} = iterator.next('import') | |
159 | - const {value: functions} = iterator.next('function') | |
189 | + let {value: globals} = iterator.next() | |
190 | + if (globals) { | |
191 | + result.globals = decodeGlobals(globals.payload) | |
192 | + } | |
193 | + | |
194 | + const {value: type} = iterator.next() | |
195 | + const {value: imports = {entries: []}} = iterator.next() | |
196 | + const {value: functions = {entries: []}} = iterator.next() | |
160 | 197 | functions.entries.forEach((typeIndex, funcIndex) => { |
161 | 198 | let customIndex = mappedFuncs.get(funcIndex) |
162 | 199 | if (customIndex === undefined) { |
163 | 200 | customIndex = mappedTypes.get(typeIndex) |
@@ -168,9 +205,9 @@ | ||
168 | 205 | } |
169 | 206 | result.indexes[funcIndex + imports.entries.length] = customIndex |
170 | 207 | }) |
171 | 208 | |
172 | - const {value: exports = {entries: []}} = iterator.next('export') | |
209 | + const {value: exports = {entries: []}} = iterator.next() | |
173 | 210 | exports.entries.forEach(entry => { |
174 | 211 | if (entry.kind === 'function') { |
175 | 212 | result.exports[entry.field_str] = entry.index |
176 | 213 | } |
@@ -182,8 +219,9 @@ | ||
182 | 219 | injectCustomSection, |
183 | 220 | inject, |
184 | 221 | decodeType, |
185 | 222 | decodeTypeMap, |
223 | + decodeGlobals, | |
186 | 224 | encodeType, |
187 | 225 | encodeTypeMap, |
188 | 226 | encodeJSON, |
189 | 227 | mergeTypeSections |
docs/actor.md | ||
---|---|---|
@@ -2,9 +2,8 @@ | ||
2 | 2 | |
3 | 3 | ### Table of Contents |
4 | 4 | |
5 | 5 | - [constructor](#constructor) |
6 | -- [queue](#queue) | |
7 | 6 | - [shutdown](#shutdown) |
8 | 7 | - [startup](#startup) |
9 | 8 | - [runMessage](#runmessage) |
10 | 9 | - [incrementTicks](#incrementticks) |
@@ -12,9 +11,9 @@ | ||
12 | 11 | - [send](#send) |
13 | 12 | |
14 | 13 | ## constructor |
15 | 14 | |
16 | -[actor.js:15-25](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/actor.js#L15-L25 "Source code on GitHub") | |
15 | +[actor.js:11-18](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/actor.js#L11-L18 "Source code on GitHub") | |
17 | 16 | |
18 | 17 | the Actor manages the varous message passing functions and provides |
19 | 18 | an interface for the containers to use |
20 | 19 | |
@@ -25,34 +24,23 @@ | ||
25 | 24 | - `opts.state` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the state of the container |
26 | 25 | - `opts.hypervisor` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the instance of the hypervisor |
27 | 26 | - `opts.container` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the container constuctor and argments |
28 | 27 | |
29 | -## queue | |
30 | - | |
31 | -[actor.js:32-39](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/actor.js#L32-L39 "Source code on GitHub") | |
32 | - | |
33 | -adds a message to this actor's message queue | |
34 | - | |
35 | -**Parameters** | |
36 | - | |
37 | -- `message` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** | |
38 | -- `portName` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** | |
39 | - | |
40 | 28 | ## shutdown |
41 | 29 | |
42 | -[actor.js:89-92](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/actor.js#L89-L92 "Source code on GitHub") | |
30 | +[actor.js:23-29](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/actor.js#L23-L29 "Source code on GitHub") | |
43 | 31 | |
44 | 32 | Runs the shutdown routine for the actor |
45 | 33 | |
46 | 34 | ## startup |
47 | 35 | |
48 | -[actor.js:97-99](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/actor.js#L97-L99 "Source code on GitHub") | |
36 | +[actor.js:34-36](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/actor.js#L34-L36 "Source code on GitHub") | |
49 | 37 | |
50 | 38 | Runs the startup routine for the actor |
51 | 39 | |
52 | 40 | ## runMessage |
53 | 41 | |
54 | -[actor.js:107-114](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/actor.js#L107-L114 "Source code on GitHub") | |
42 | +[actor.js:44-56](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/actor.js#L44-L56 "Source code on GitHub") | |
55 | 43 | |
56 | 44 | run the Actor with a given message |
57 | 45 | |
58 | 46 | **Parameters** |
@@ -63,9 +51,9 @@ | ||
63 | 51 | Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** |
64 | 52 | |
65 | 53 | ## incrementTicks |
66 | 54 | |
67 | -[actor.js:120-123](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/actor.js#L120-L123 "Source code on GitHub") | |
55 | +[actor.js:62-64](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/actor.js#L62-L64 "Source code on GitHub") | |
68 | 56 | |
69 | 57 | updates the number of ticks that the actor has run |
70 | 58 | |
71 | 59 | **Parameters** |
@@ -73,9 +61,9 @@ | ||
73 | 61 | - `count` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** the number of ticks to add |
74 | 62 | |
75 | 63 | ## createActor |
76 | 64 | |
77 | -[actor.js:130-133](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/actor.js#L130-L133 "Source code on GitHub") | |
65 | +[actor.js:71-74](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/actor.js#L71-L74 "Source code on GitHub") | |
78 | 66 | |
79 | 67 | creates an actor |
80 | 68 | |
81 | 69 | **Parameters** |
@@ -85,9 +73,9 @@ | ||
85 | 73 | - `message` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an intial [message](https://github.com/primea/js-primea-message) to send newly created actor |
86 | 74 | |
87 | 75 | ## send |
88 | 76 | |
89 | -[actor.js:150-155](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/actor.js#L150-L155 "Source code on GitHub") | |
77 | +[actor.js:91-96](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/actor.js#L91-L96 "Source code on GitHub") | |
90 | 78 | |
91 | 79 | sends a message to a given port |
92 | 80 | |
93 | 81 | **Parameters** |
docs/hypervisor.md | ||
---|---|---|
@@ -3,16 +3,15 @@ | ||
3 | 3 | ### Table of Contents |
4 | 4 | |
5 | 5 | - [constructor](#constructor) |
6 | 6 | - [send](#send) |
7 | -- [getActor](#getactor) | |
8 | 7 | - [createActor](#createactor) |
9 | 8 | - [createStateRoot](#createstateroot) |
10 | 9 | - [registerContainer](#registercontainer) |
11 | 10 | |
12 | 11 | ## constructor |
13 | 12 | |
14 | -[index.js:10-15](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/index.js#L10-L15 "Source code on GitHub") | |
13 | +[index.js:12-17](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/index.js#L12-L17 "Source code on GitHub") | |
15 | 14 | |
16 | 15 | The Hypervisor manages the container instances by instantiating them and |
17 | 16 | destorying them when possible. It also facilitates localating Containers |
18 | 17 | |
@@ -22,34 +21,23 @@ | ||
22 | 21 | - `nonce` (optional, default `0`) |
23 | 22 | |
24 | 23 | ## send |
25 | 24 | |
26 | -[index.js:23-27](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/index.js#L23-L27 "Source code on GitHub") | |
25 | +[index.js:25-30](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/index.js#L25-L30 "Source code on GitHub") | |
27 | 26 | |
28 | 27 | sends a message |
29 | 28 | |
30 | 29 | **Parameters** |
31 | 30 | |
31 | +- `messages` | |
32 | +- `cap` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the capabilitly used to send the message | |
32 | 33 | - `message` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the [message](https://github.com/primea/js-primea-message) to send |
33 | -- `cap` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the capabilitly used to send the message | |
34 | 34 | |
35 | 35 | Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** a promise that resolves once the receiving container is loaded |
36 | 36 | |
37 | -## getActor | |
38 | - | |
39 | -[index.js:55-63](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/index.js#L55-L63 "Source code on GitHub") | |
40 | - | |
41 | -gets an existsing actor | |
42 | - | |
43 | -**Parameters** | |
44 | - | |
45 | -- `id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the actor's ID | |
46 | - | |
47 | -Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** | |
48 | - | |
49 | 37 | ## createActor |
50 | 38 | |
51 | -[index.js:71-85](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/index.js#L71-L85 "Source code on GitHub") | |
39 | +[index.js:65-83](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/index.js#L65-L83 "Source code on GitHub") | |
52 | 40 | |
53 | 41 | creates an instance of an Actor |
54 | 42 | |
55 | 43 | **Parameters** |
@@ -60,22 +48,22 @@ | ||
60 | 48 | - `message` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an intial [message](https://github.com/primea/js-primea-message) to send newly created actor |
61 | 49 | |
62 | 50 | ## createStateRoot |
63 | 51 | |
64 | -[index.js:98-101](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/index.js#L98-L101 "Source code on GitHub") | |
52 | +[index.js:98-104](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/index.js#L98-L104 "Source code on GitHub") | |
65 | 53 | |
66 | 54 | creates a state root starting from a given container and a given number of |
67 | 55 | ticks |
68 | 56 | |
69 | 57 | **Parameters** |
70 | 58 | |
71 | -- `ticks` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** the number of ticks at which to create the state root (optional, default `Infinity`) | |
59 | +- `ticks` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** the number of ticks at which to create the state root | |
72 | 60 | |
73 | 61 | Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** |
74 | 62 | |
75 | 63 | ## registerContainer |
76 | 64 | |
77 | -[index.js:109-111](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/index.js#L109-L111 "Source code on GitHub") | |
65 | +[index.js:112-114](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/index.js#L112-L114 "Source code on GitHub") | |
78 | 66 | |
79 | 67 | regirsters a container with the hypervisor |
80 | 68 | |
81 | 69 | **Parameters** |
docs/index.md | ||
---|---|---|
@@ -1,7 +1,6 @@ | ||
1 | 1 | # API |
2 | 2 | - [Hypervisor](./hypervisor.md) |
3 | -- [Kernel](./kernel.md) | |
4 | -- [PortManager](./portManager.md) | |
3 | +- [Actor](./actor.md) | |
5 | 4 | |
6 | -## internal API's | |
5 | +## Internal APIs | |
7 | 6 | - [Scheduler](./scheduler.md) |
docs/scheduler.md | ||
---|---|---|
@@ -2,87 +2,15 @@ | ||
2 | 2 | |
3 | 3 | ### Table of Contents |
4 | 4 | |
5 | 5 | - [constructor](#constructor) |
6 | -- [lock](#lock) | |
7 | -- [update](#update) | |
8 | -- [getInstance](#getinstance) | |
9 | -- [done](#done) | |
10 | -- [wait](#wait) | |
11 | -- [leastNumberOfTicks](#leastnumberofticks) | |
12 | 6 | |
13 | 7 | ## constructor |
14 | 8 | |
15 | -[scheduler.js:13-17](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/scheduler.js#L13-L17 "Source code on GitHub") | |
9 | +[scheduler.js:19-26](https://github.com/dfinity/js-primea/blob/21960d62467278cd5659e2eb5f80cc6ddd87e663/scheduler.js#L19-L26 "Source code on GitHub") | |
16 | 10 | |
17 | 11 | The Scheduler manages the actor instances and tracks how many "ticks" they |
18 | 12 | have ran. |
19 | 13 | |
20 | -## lock | |
21 | - | |
22 | -[scheduler.js:24-34](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/scheduler.js#L24-L34 "Source code on GitHub") | |
23 | - | |
24 | -locks the scheduler from clearing waits untill the lock is resolved | |
25 | - | |
26 | 14 | **Parameters** |
27 | 15 | |
28 | -- `id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** | |
29 | - | |
30 | -Returns **[function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** the resolve function to call once it to unlock | |
31 | - | |
32 | -## update | |
33 | - | |
34 | -[scheduler.js:40-44](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/scheduler.js#L40-L44 "Source code on GitHub") | |
35 | - | |
36 | -updates an instance with a new tick count | |
37 | - | |
38 | -**Parameters** | |
39 | - | |
40 | -- `instance` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an actor instance | |
41 | - | |
42 | -## getInstance | |
43 | - | |
44 | -[scheduler.js:56-59](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/scheduler.js#L56-L59 "Source code on GitHub") | |
45 | - | |
46 | -returns an Actor instance | |
47 | - | |
48 | -**Parameters** | |
49 | - | |
50 | -- `id` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** | |
51 | - | |
52 | -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** | |
53 | - | |
54 | -## done | |
55 | - | |
56 | -[scheduler.js:65-70](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/scheduler.js#L65-L70 "Source code on GitHub") | |
57 | - | |
58 | -deletes an instance from the scheduler | |
59 | - | |
60 | -**Parameters** | |
61 | - | |
62 | -- `id` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the containers id | |
63 | - | |
64 | -## wait | |
65 | - | |
66 | -[scheduler.js:79-93](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/scheduler.js#L79-L93 "Source code on GitHub") | |
67 | - | |
68 | -returns a promise that resolves once all containers have reached the given | |
69 | -number of ticks | |
70 | - | |
71 | -**Parameters** | |
72 | - | |
73 | -- `ticks` **interger** the number of ticks to wait | |
74 | -- `id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** optional id of the container that is waiting | |
75 | - | |
76 | -Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** | |
77 | - | |
78 | -## leastNumberOfTicks | |
79 | - | |
80 | -[scheduler.js:99-109](https://github.com/dfinity/js-primea/blob/3d3fc0d82dd65f14b8533dcd2fb881c9fbbb1bd3/scheduler.js#L99-L109 "Source code on GitHub") | |
81 | - | |
82 | -returns the oldest container's ticks | |
83 | - | |
84 | -**Parameters** | |
85 | - | |
86 | -- `exclude` | |
87 | - | |
88 | -Returns **integer** | |
16 | +- `hypervisor` |
index.js | ||
---|---|---|
@@ -1,6 +1,8 @@ | ||
1 | 1 | const Actor = require('./actor.js') |
2 | 2 | const Scheduler = require('./scheduler.js') |
3 | +const {ID} = require('./systemObjects.js') | |
4 | +const crypto = require('crypto') | |
3 | 5 | |
4 | 6 | module.exports = class Hypervisor { |
5 | 7 | /** |
6 | 8 | * The Hypervisor manages the container instances by instantiating them and |
@@ -27,11 +29,14 @@ | ||
27 | 29 | this.scheduler.queue(messages) |
28 | 30 | } |
29 | 31 | |
30 | 32 | async loadActor (id) { |
31 | - const state = await this.tree.getSubTree(id) | |
32 | - const code = state.get(Buffer.from([0])) | |
33 | - const {type, nonce} = Actor.deserializeMetaData(state.root['/'][3]) | |
33 | + const state = await this.tree.get(id.id, true) | |
34 | + const [code, storage] = await Promise.all([ | |
35 | + this.tree.graph.get(state.node, '1'), | |
36 | + this.tree.graph.get(state.node, '2') | |
37 | + ]) | |
38 | + const [type, nonce] = state.value | |
34 | 39 | const Container = this._containerTypes[type] |
35 | 40 | |
36 | 41 | // create a new actor instance |
37 | 42 | const actor = new Actor({ |
@@ -41,9 +46,10 @@ | ||
41 | 46 | id, |
42 | 47 | nonce, |
43 | 48 | type, |
44 | 49 | code, |
45 | - cachedb: this.tree.dag._dag | |
50 | + storage: storage || [], | |
51 | + tree: this.tree | |
46 | 52 | }) |
47 | 53 | |
48 | 54 | await actor.startup() |
49 | 55 | return actor |
@@ -57,26 +63,34 @@ | ||
57 | 63 | */ |
58 | 64 | async createActor (type, code, id = {nonce: this.nonce++, parent: null}) { |
59 | 65 | const Container = this._containerTypes[type] |
60 | 66 | const encoded = encodedID(id) |
61 | - const idHash = await this._getHashFromObj(encoded) | |
62 | - const module = await Container.onCreation(code, idHash, this.tree.dag._dag) | |
63 | - const metaData = Actor.serializeMetaData(type) | |
67 | + let idHash = this._hash(encoded) | |
68 | + idHash = new ID(idHash) | |
69 | + const module = await Container.onCreation(code, idHash, this.tree) | |
70 | + const metaData = [type, 0] | |
64 | 71 | |
65 | 72 | // save the container in the state |
66 | - this.tree.set(idHash, metaData) | |
67 | - if (code) { | |
68 | - this.tree.set(Buffer.concat([idHash, Buffer.from([0])]), code) | |
73 | + const node = await this.tree.set(idHash.id, metaData) | |
74 | + // save the code | |
75 | + node[1] = { | |
76 | + '/': code | |
69 | 77 | } |
78 | + // save the storage | |
79 | + node[2] = { | |
80 | + '/': [] | |
81 | + } | |
82 | + | |
70 | 83 | return { |
71 | 84 | id: idHash, |
72 | - module: module | |
85 | + module | |
73 | 86 | } |
74 | 87 | } |
75 | 88 | |
76 | - // get a hash from a POJO | |
77 | - _getHashFromObj (obj) { | |
78 | - return this.tree.constructor.getMerkleLink(obj) | |
89 | + _hash (buf) { | |
90 | + const hash = crypto.createHash('sha256') | |
91 | + hash.update(buf) | |
92 | + return hash.digest().slice(0, 20) | |
79 | 93 | } |
80 | 94 | |
81 | 95 | /** |
82 | 96 | * creates a state root starting from a given container and a given number of |
@@ -85,11 +99,15 @@ | ||
85 | 99 | * @returns {Promise} |
86 | 100 | */ |
87 | 101 | createStateRoot () { |
88 | 102 | return new Promise((resolve, reject) => { |
89 | - this.scheduler.on('idle', () => { | |
103 | + if (!this.scheduler._running) { | |
90 | 104 | this.tree.flush().then(resolve) |
91 | - }) | |
105 | + } else { | |
106 | + this.scheduler.on('idle', () => { | |
107 | + this.tree.flush().then(resolve) | |
108 | + }) | |
109 | + } | |
92 | 110 | }) |
93 | 111 | } |
94 | 112 | |
95 | 113 | /** |
@@ -105,9 +123,9 @@ | ||
105 | 123 | |
106 | 124 | function encodedID (id) { |
107 | 125 | const nonce = Buffer.from([id.nonce]) |
108 | 126 | if (id.parent) { |
109 | - return Buffer.concat([nonce, id.parent]) | |
127 | + return Buffer.concat([nonce, id.parent.id]) | |
110 | 128 | } else { |
111 | 129 | return nonce |
112 | 130 | } |
113 | 131 | } |
message.js | ||
---|---|---|
@@ -1,5 +1,6 @@ | ||
1 | 1 | const EventEmitter = require('events') |
2 | +const {ID} = require('./systemObjects.js') | |
2 | 3 | |
3 | 4 | /** |
4 | 5 | * This implements Messages for Primea |
5 | 6 | * @module primea-message |
@@ -31,9 +32,9 @@ | ||
31 | 32 | ticks: 0, |
32 | 33 | funcRef: null, |
33 | 34 | funcArguments: [], |
34 | 35 | funcParameters: [], |
35 | - _fromId: Buffer.alloc(20), | |
36 | + _fromId: new ID(Buffer.alloc(20)), | |
36 | 37 | _fromTicks: 0 |
37 | 38 | } |
38 | 39 | } |
39 | 40 | } |
package-lock.json | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 344343 bytes New file size: 337905 bytes |
package.json | ||
---|---|---|
@@ -5,13 +5,14 @@ | ||
5 | 5 | "scripts": { |
6 | 6 | "coveralls": "npm run coverage && nyc report --reporter=text-lcov | coveralls", |
7 | 7 | "coverage": "nyc npm test", |
8 | 8 | "lint": "standard", |
9 | - "build:docs": "npm run build:docs:hypervisor && npm run build:docs:actor && npm run build:docs:scheduler && npm run build:docs:capsStore && npm run build:docs:inbox", | |
9 | + "build:docs": "npm run build:docs:hypervisor && npm run build:docs:actor && npm run build:docs:scheduler", | |
10 | 10 | "build:docs:hypervisor": "documentation build ./index.js --github --shallow --sort-order source -f md > ./docs/hypervisor.md", |
11 | 11 | "build:docs:actor": "documentation build ./actor.js --github --shallow --sort-order source -f md > ./docs/actor.md", |
12 | - "build:docs:capsStore": "documentation build ./capsStore.js --github --shallow --sort-order source -f md > ./docs/capsStore.md", | |
13 | - "test": "node ./tests/index.js" | |
12 | + "build:docs:scheduler": "documentation build ./scheduler.js --github --shallow --sort-order source -f md > ./docs/scheduler.md", | |
13 | + "test": "node ./tests/index.js", | |
14 | + "test:wasm": "node ./tests/wasmContainer.js" | |
14 | 15 | }, |
15 | 16 | "repository": { |
16 | 17 | "type": "git", |
17 | 18 | "url": "git+https://github.com/primea/js-primea-hypervisor.git" |
@@ -28,27 +29,24 @@ | ||
28 | 29 | "author": "mjbecze <mjbecze@gmail.com>", |
29 | 30 | "contributors": "Alex Beregszaszi <alex@rtfs.hu>", |
30 | 31 | "license": "MPL-2.0", |
31 | 32 | "dependencies": { |
32 | - "binary-search": "^1.3.3", | |
33 | 33 | "binary-search-insert": "^1.0.3", |
34 | - "buffer-pipe": "0.0.2", | |
34 | + "borc": "^2.0.2", | |
35 | 35 | "events": "^2.0.0", |
36 | - "leb128": "0.0.4", | |
37 | - "levelup": "^2.0.1", | |
38 | - "reference-map": "^1.2.1", | |
36 | + "reference-map": "^1.2.3", | |
39 | 37 | "safe-buffer": "^5.1.1", |
40 | - "wasm-json-toolkit": "^0.2.1", | |
38 | + "wasm-json-toolkit": "^0.2.2", | |
41 | 39 | "wasm-metering": "^0.1.1" |
42 | 40 | }, |
43 | 41 | "devDependencies": { |
42 | + "levelup": "^2.0.2", | |
44 | 43 | "coveralls": "^3.0.0", |
45 | - "dfinity-radix-tree": "0.0.9", | |
44 | + "dfinity-radix-tree": "0.1.1", | |
46 | 45 | "documentation": "^6.0.0", |
47 | 46 | "level-browserify": "^1.1.1", |
48 | 47 | "nyc": "^11.4.1", |
49 | - "primea-abstract-container": "0.0.6", | |
50 | - "standard": "10.0.3", | |
51 | - "tape": "^4.6.3", | |
48 | + "standard": "11.0.0", | |
49 | + "tape": "^4.9.0", | |
52 | 50 | "wabt": "^1.0.0" |
53 | 51 | } |
54 | 52 | } |
scheduler.js | ||
---|---|---|
@@ -6,9 +6,9 @@ | ||
6 | 6 | // order by number of ticks if messages have different number of ticks |
7 | 7 | if (messageA._fromTicks !== messageB._fromTicks) { |
8 | 8 | return messageA._fromTicks > messageB._fromTicks |
9 | 9 | } else { |
10 | - return Buffer.compare(messageA._fromId, messageB._fromId) | |
10 | + return Buffer.compare(messageA._fromId.id, messageB._fromId.id) | |
11 | 11 | } |
12 | 12 | } |
13 | 13 | |
14 | 14 | module.exports = class Scheduler extends EventEmitter { |
@@ -46,9 +46,9 @@ | ||
46 | 46 | this.emit('idle') |
47 | 47 | } |
48 | 48 | |
49 | 49 | async _processMessage (message) { |
50 | - const to = message.funcRef.destId.toString('hex') | |
50 | + const to = message.funcRef.destId.id.toString('hex') | |
51 | 51 | let actor = this.actors.get(to) |
52 | 52 | if (!actor) { |
53 | 53 | actor = await this.hypervisor.loadActor(message.funcRef.destId) |
54 | 54 | this.actors.set(to, actor) |
tests/index.js | ||
---|---|---|
@@ -31,9 +31,9 @@ | ||
31 | 31 | |
32 | 32 | tape('basic', async t => { |
33 | 33 | t.plan(2) |
34 | 34 | const expectedState = { |
35 | - '/': Buffer.from('926de6b7eb39cfa8d7f8a44d1ef191d3bcb765a7', 'hex') | |
35 | + '/': Buffer.from('cd80335de00c2bf38570b41c55a79174c1c64e9f', 'hex') | |
36 | 36 | } |
37 | 37 | |
38 | 38 | const tree = new RadixTree({ |
39 | 39 | db: db |
@@ -62,9 +62,9 @@ | ||
62 | 62 | |
63 | 63 | tape('two communicating actors', async t => { |
64 | 64 | t.plan(2) |
65 | 65 | const expectedState = { |
66 | - '/': Buffer.from('a4c7ceacd8c867ae1d0b472d8bffa3cb10048331', 'hex') | |
66 | + '/': Buffer.from('b063f3e53b2ea40f50afe964b9f9b49aad491155', 'hex') | |
67 | 67 | } |
68 | 68 | |
69 | 69 | const tree = new RadixTree({ |
70 | 70 | db: db |
@@ -110,9 +110,9 @@ | ||
110 | 110 | |
111 | 111 | tape('three communicating actors', async t => { |
112 | 112 | t.plan(3) |
113 | 113 | const expectedState = { |
114 | - '/': Buffer.from('4633ac4b9f8212e501b6c56906039ec081fbe5a3', 'hex') | |
114 | + '/': Buffer.from('db532195ac569b142415cc9bdbec37f18f344a59', 'hex') | |
115 | 115 | } |
116 | 116 | |
117 | 117 | const tree = new RadixTree({ |
118 | 118 | db: db |
@@ -165,9 +165,9 @@ | ||
165 | 165 | |
166 | 166 | tape('three communicating actors, with tick counting', async t => { |
167 | 167 | t.plan(3) |
168 | 168 | const expectedState = { |
169 | - '/': Buffer.from('4633ac4b9f8212e501b6c56906039ec081fbe5a3', 'hex') | |
169 | + '/': Buffer.from('db532195ac569b142415cc9bdbec37f18f344a59', 'hex') | |
170 | 170 | } |
171 | 171 | |
172 | 172 | const tree = new RadixTree({ |
173 | 173 | db: db |
@@ -220,9 +220,9 @@ | ||
220 | 220 | |
221 | 221 | tape('errors', async t => { |
222 | 222 | t.plan(3) |
223 | 223 | const expectedState = { |
224 | - '/': Buffer.from('a4c7ceacd8c867ae1d0b472d8bffa3cb10048331', 'hex') | |
224 | + '/': Buffer.from('b063f3e53b2ea40f50afe964b9f9b49aad491155', 'hex') | |
225 | 225 | } |
226 | 226 | |
227 | 227 | const tree = new RadixTree({ |
228 | 228 | db: db |
@@ -268,9 +268,9 @@ | ||
268 | 268 | |
269 | 269 | tape('actor creation', async t => { |
270 | 270 | t.plan(2) |
271 | 271 | const expectedState = { |
272 | - '/': Buffer.from('f47377a763c91247e62138408d706a09bccaaf36', 'hex') | |
272 | + '/': Buffer.from('8a21d80cd7ca04e64be7cb2726a72060fc546ed6', 'hex') | |
273 | 273 | } |
274 | 274 | |
275 | 275 | const tree = new RadixTree({ |
276 | 276 | db: db |
@@ -280,9 +280,12 @@ | ||
280 | 280 | async start (funcRef) { |
281 | 281 | const {module} = await this.actor.createActor(testVMContainerB.typeId) |
282 | 282 | const message = new Message({ |
283 | 283 | funcRef: module.main, |
284 | - funcArguments: [this.actor.getFuncRef('main')] | |
284 | + funcArguments: [{ | |
285 | + name: 'main', | |
286 | + destId: this.actor.id | |
287 | + }] | |
285 | 288 | }) |
286 | 289 | this.actor.send(message) |
287 | 290 | } |
288 | 291 | main (data) { |
@@ -308,14 +311,15 @@ | ||
308 | 311 | await hypervisor.send(new Message({funcRef: module.start})) |
309 | 312 | |
310 | 313 | const stateRoot = await hypervisor.createStateRoot() |
311 | 314 | t.deepEquals(stateRoot, expectedState, 'expected root!') |
315 | + t.end() | |
312 | 316 | }) |
313 | 317 | |
314 | 318 | tape('simple message arbiter test', async t => { |
315 | 319 | t.plan(4) |
316 | 320 | const expectedState = { |
317 | - '/': Buffer.from('a4c7ceacd8c867ae1d0b472d8bffa3cb10048331', 'hex') | |
321 | + '/': Buffer.from('b063f3e53b2ea40f50afe964b9f9b49aad491155', 'hex') | |
318 | 322 | } |
319 | 323 | |
320 | 324 | const tree = new RadixTree({ |
321 | 325 | db: db |
@@ -382,9 +386,9 @@ | ||
382 | 386 | tape('arbiter test for id comparision', async t => { |
383 | 387 | t.plan(4) |
384 | 388 | let message |
385 | 389 | const expectedState = { |
386 | - '/': Buffer.from('4633ac4b9f8212e501b6c56906039ec081fbe5a3', 'hex') | |
390 | + '/': Buffer.from('db532195ac569b142415cc9bdbec37f18f344a59', 'hex') | |
387 | 391 | } |
388 | 392 | |
389 | 393 | const tree = new RadixTree({ |
390 | 394 | db: db |
@@ -449,9 +453,9 @@ | ||
449 | 453 | |
450 | 454 | tape('async work', async t => { |
451 | 455 | t.plan(3) |
452 | 456 | const expectedState = { |
453 | - '/': Buffer.from('a4c7ceacd8c867ae1d0b472d8bffa3cb10048331', 'hex') | |
457 | + '/': Buffer.from('b063f3e53b2ea40f50afe964b9f9b49aad491155', 'hex') | |
454 | 458 | } |
455 | 459 | |
456 | 460 | const tree = new RadixTree({ |
457 | 461 | db: db |
tests/wasm/caller.wasm | ||
---|---|---|
@@ -1,4 +1,3 @@ | ||
1 | - asm | |
2 | -type`` typeMap | |
1 | + asm types`` typeMap | |
3 | 2 | ` ` funcinternalize ptable call |
4 | 3 | A A A |
tests/wasm/funcRef_caller.wasm | ||
---|---|---|
@@ -1,3 +1,2 @@ | ||
1 | - asm | |
2 | -type`` typeMap ` ` `` @funcinternalize testcheck moduleself moduleexports p $memory table call callback | |
3 | - A AA A A A callback | |
1 | + asm types`` typeMap ` ` `` Tfuncinternalize testcheck moduleself moduleexport memoryexternalize p $memory table call callback | |
2 | +" A AA A A A callback |
tests/wasm/funcRef_reciever.wasm | ||
---|---|---|
@@ -1,4 +1,3 @@ | ||
1 | - asm | |
2 | -type`` typeMap | |
3 | -` ` funcinternalize ptable receive | |
4 | - A AA | |
1 | + asm types`` typeMap | |
2 | +` ` *funcinternalize funcset_gas_budget ptable receive | |
3 | + A�� A AA |
tests/wasm/empty.wasm | ||
---|---|---|
@@ -1,0 +1,1 @@ | ||
1 | + asm ���� p ���� ���� ���� memory |
tests/wasm/globals.wasm | ||
---|---|---|
@@ -1,0 +1,4 @@ | ||
1 | + asm globals `` ` +memoryexternalize memoryinternalize A~A~memory load store | |
2 | + | |
3 | + A A $ # A AA | |
4 | + A test |
tests/wasm/memory.wasm | ||
---|---|---|
@@ -1,0 +1,3 @@ | ||
1 | + asm `` ` +memoryexternalize memoryinternalize memory test | |
2 | + A A A AA | |
3 | + A test |