git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 4f5114c16dd9a43185872bb26ccc8716390fd8ad

Merge branch 'master' into greenkeeper/ipfs-0.25.1

wanderer authored on 7/28/2017, 2:49:56 PM
GitHub committed on 7/28/2017, 2:49:56 PM
Parent: 8981bfd8232394c9a1de54bc36bb1d40c0f08698
Parent: 6d4d805d77e251aec5ff9f6cb442a895b5813c0a

Files changed

index.jschanged
kernel.jschanged
package.jsonchanged
tests/index.jschanged
index.jsView
@@ -2,11 +2,10 @@
22 const Message = require('primea-message')
33 const Kernel = require('./kernel.js')
44 const Scheduler = require('./scheduler.js')
55 const DFSchecker = require('./dfsChecker.js')
6 +const chunk = require('chunk')
67
7-const ROOT_ID = 'zdpuAm6aTdLVMUuiZypxkwtA7sKm7BWERy8MPbaCrFsmiyzxr'
8-
98 module.exports = class Hypervisor {
109 /**
1110 * The Hypervisor manages the container instances by instantiating them and
1211 * destorying them when possible. It also facilitates localating Containers
@@ -18,8 +17,11 @@
1817 this.scheduler = new Scheduler()
1918 this.state = state
2019 this._containerTypes = {}
2120 this._nodesToCheck = new Set()
21 +
22 + this.ROOT_ID = 'zdpuAm6aTdLVMUuiZypxkwtA7sKm7BWERy8MPbaCrFsmiyzxr'
23 + this.MAX_DATA_BYTES = 65533
2224 }
2325
2426 /**
2527 * add a potaintail node in the state graph to check for garbage collection
@@ -56,13 +58,24 @@
5658 // loads an instance of a container from the state
5759 async _loadInstance (id) {
5860 const state = await this.graph.get(this.state, id)
5961 const container = this._containerTypes[state.type]
62 + let code
6063
64 + // checks if the code stored in the state is an array and that the elements
65 + // are merkle link
66 + if (state.code && state.code[0]['/']) {
67 + await this.graph.tree(state.code, 1)
68 + code = state.code.map(a => a['/']).reduce((a, b) => a + b)
69 + } else {
70 + code = state.code
71 + }
72 +
6173 // create a new kernel instance
6274 const kernel = new Kernel({
6375 hypervisor: this,
6476 state: state,
77 + code: code,
6578 container: container,
6679 id: id
6780 })
6881
@@ -87,8 +100,9 @@
87100 return instance
88101 } else {
89102 const resolve = this.scheduler.getLock(id)
90103 const instance = await this._loadInstance(id)
104 + await instance.startup()
91105 resolve(instance)
92106 return instance
93107 }
94108 }
@@ -114,16 +128,28 @@
114128 ports: {},
115129 type: type
116130 }
117131
132 + if (message.data.length) {
133 + state.code = message.data
134 + }
135 +
118136 // save the container in the state
119137 await this.graph.set(this.state, idHash, state)
120138 // create the container instance
121139 const instance = await this._loadInstance(idHash)
122140 resolve(instance)
123141 // send the intialization message
124- await instance.initialize(message)
142 + await instance.create(message)
125143
144 + if (state.code && state.code.length > this.MAX_DATA_BYTES) {
145 + state.code = chunk(state.code, this.MAX_DATA_BYTES).map(chk => {
146 + return {
147 + '/': chk
148 + }
149 + })
150 + }
151 +
126152 return instance
127153 }
128154
129155 /**
@@ -133,9 +159,9 @@
133159 * @returns {Promise}
134160 */
135161 async createStateRoot (ticks) {
136162 await this.scheduler.wait(ticks)
137- const unlinked = await DFSchecker(this.graph, this.state, ROOT_ID, this._nodesToCheck)
163 + const unlinked = await DFSchecker(this.graph, this.state, this.ROOT_ID, this._nodesToCheck)
138164 unlinked.forEach(id => {
139165 delete this.state[id]
140166 })
141167 return this.graph.flush(this.state)
kernel.jsView
@@ -14,8 +14,9 @@
1414 * @param {Object} opts.container - the container constuctor and argments
1515 */
1616 constructor (opts) {
1717 this.state = opts.state
18 + this.code = opts.code
1819 this.hypervisor = opts.hypervisor
1920 this.id = opts.id
2021 this.container = new opts.container.Constructor(this, opts.container.args)
2122 this.timeout = 0
@@ -38,10 +39,10 @@
3839 this.ports.queue(portName, message)
3940 return this._startMessageLoop()
4041 }
4142
42- async initialize (message) {
43- await this.run(message, 'initialize')
43 + async create (message) {
44 + await this.message(message, 'onCreation')
4445 return this._startMessageLoop()
4546 }
4647
4748 // waits for the next message
@@ -62,9 +63,9 @@
6263 this.ticks = message._fromTicks
6364 this.hypervisor.scheduler.update(this)
6465 }
6566 // run the next message
66- await this.run(message)
67 + await this.message(message)
6768 }
6869
6970 this.containerState = 'idle'
7071 this.container.onIdle()
@@ -74,15 +75,19 @@
7475 shutdown () {
7576 this.hypervisor.scheduler.done(this.id)
7677 }
7778
79 + startup () {
80 + return this.container.onStartup()
81 + }
82 +
7883 /**
7984 * run the kernels code with a given enviroment
8085 * @param {object} message - the message to run
8186 * @param {boolean} init - whether or not to run the intialization routine
8287 * @returns {Promise}
8388 */
84- async run (message, method = 'run') {
89 + async message (message, method = 'onMessage') {
8590 if (message.constructor === DeleteMessage) {
8691 this.ports._delete(message.fromName)
8792 } else {
8893 const responsePort = message.responsePort
package.jsonView
@@ -1,7 +1,7 @@
11 {
22 "name": "primea-hypervisor",
3- "version": "0.0.2",
3 + "version": "0.0.3",
44 "description": "this is a JS implemention of the primea hypervisor",
55 "scripts": {
66 "coverage": "node --harmony ./node_modules/istanbul/lib/cli.js cover ./tests/index.js",
77 "coveralls": "npm run coverage && coveralls <coverage/lcov.info",
@@ -31,21 +31,21 @@
3131 "license": "MPL-2.0",
3232 "dependencies": {
3333 "binary-search-insert": "^1.0.3",
3434 "bn.js": "^4.11.6",
35- "ipld-graph-builder": "1.2.2",
36- "primea-abstract-container": "0.0.1",
35 + "chunk": "0.0.2",
36 + "ipld-graph-builder": "1.2.3",
3737 "primea-message": "0.0.1"
3838 },
3939 "devDependencies": {
40 + "primea-abstract-container": "0.0.4",
4041 "coveralls": "^2.13.1",
41- "documentation": "^4.0.0-rc.1",
42 + "documentation": "^5.0.1",
4243 "ipfs": "^0.25.1",
4344 "istanbul": "^1.1.0-alpha.1",
4445 "level-promise": "^2.1.1",
4546 "levelup": "^1.3.8",
4647 "memdown": "^1.2.4",
47- "primea-abstract-container": "0.0.2",
4848 "standard": "10.0.2",
4949 "tape": "^4.5.1"
5050 }
5151 }
tests/index.jsView
@@ -1,16 +1,17 @@
11 const tape = require('tape')
22 const IPFS = require('ipfs')
33 const AbstractContainer = require('primea-abstract-container')
4 +const Message = require('primea-message')
45 const Hypervisor = require('../')
56
67 // start ipfs
78 const node = new IPFS({
89 start: false
910 })
1011
1112 class BaseContainer extends AbstractContainer {
12- initialize (message) {
13 + onCreation (message) {
1314 this.kernel.state.code = message.data.byteLength ? message.data : undefined
1415 const port = message.ports[0]
1516 if (port) {
1617 this.kernel.ports.bind('root', port)
@@ -26,9 +27,9 @@
2627 '/': 'zdpuB1wc9Pb6jUzfNt4nAxAEUxB7kNhg4vbq7YLcEyBUb6iAB'
2728 }
2829
2930 class testVMContainer extends BaseContainer {
30- run (m) {
31 + onMessage (m) {
3132 t.true(m === message, 'should recive a message')
3233 }
3334 }
3435
@@ -60,9 +61,9 @@
6061 '/': 'zdpuAozDi6tKPbqmHJxo7aNES2xVt1MkaCLyxcioEKzz3M2WH'
6162 }
6263
6364 class testVMContainer extends BaseContainer {
64- initialize () {}
65 + onCreation () {}
6566 }
6667
6768 const hypervisor = new Hypervisor(node.dag)
6869 hypervisor.registerContainer('test', testVMContainer)
@@ -86,15 +87,15 @@
8687 '/': 'zdpuAtVcH6MUnvt2RXnLsDXyLB3CBSQ7aydfh2ogSKGCejJCQ'
8788 }
8889
8990 class testVMContainer2 extends BaseContainer {
90- run (m) {
91 + onMessage (m) {
9192 t.true(m === message, 'should recive a message')
9293 }
9394 }
9495
9596 class testVMContainer extends BaseContainer {
96- run (m) {
97 + onMessage (m) {
9798 const [portRef1, portRef2] = this.kernel.ports.createChannel()
9899 this.kernel.createInstance('test2', this.kernel.createMessage({
99100 ports: [portRef2]
100101 }))
@@ -132,9 +133,9 @@
132133 }
133134 let hasResolved = false
134135
135136 class testVMContainer2 extends BaseContainer {
136- run (m) {
137 + onMessage (m) {
137138 t.true(m === message, 'should recive a message')
138139 return new Promise((resolve, reject) => {
139140 setTimeout(() => {
140141 this.kernel.incrementTicks(1)
@@ -145,9 +146,9 @@
145146 }
146147 }
147148
148149 class testVMContainer extends BaseContainer {
149- run (m) {
150 + onMessage (m) {
150151 const [portRef1, portRef2] = this.kernel.ports.createChannel()
151152 this.kernel.createInstance('test2', this.kernel.createMessage({
152153 ports: [portRef2]
153154 }))
@@ -177,9 +178,9 @@
177178 t.deepEquals(stateRoot, expectedState, 'expected state')
178179
179180 // test reviving the state
180181 class testVMContainer3 extends BaseContainer {
181- run (m) {
182 + onMessage (m) {
182183 const port = this.kernel.ports.get('child')
183184 this.kernel.send(port, m)
184185 this.kernel.incrementTicks(1)
185186 }
@@ -193,9 +194,9 @@
193194
194195 tape('traps', async t => {
195196 t.plan(1)
196197 class Root extends BaseContainer {
197- async run (m) {
198 + async onMessage (m) {
198199 const [portRef1, portRef2] = this.kernel.ports.createChannel()
199200 const [portRef3, portRef4] = this.kernel.ports.createChannel()
200201 const [portRef5, portRef6] = this.kernel.ports.createChannel()
201202
@@ -224,9 +225,9 @@
224225 const hypervisor = new Hypervisor(node.dag)
225226
226227 hypervisor.registerContainer('root', Root)
227228 const root = await hypervisor.createInstance('root')
228- await root.run(root.createMessage())
229 + await root.message(root.createMessage())
229230 const stateRoot = await hypervisor.createStateRoot()
230231
231232 t.deepEquals(stateRoot, {
232233 '/': 'zdpuAwrMmQXqFusve7zcRYxVUuji4NVzZR5GyjwyStsjteCoW'
@@ -237,9 +238,9 @@
237238 t.plan(2)
238239 let runs = 0
239240
240241 class Root extends BaseContainer {
241- run (m) {
242 + onMessage (m) {
242243 if (!runs) {
243244 runs++
244245
245246 const [portRef1, portRef2] = this.kernel.ports.createChannel()
@@ -269,18 +270,18 @@
269270 }
270271 }
271272
272273 class First extends BaseContainer {
273- run (m) {
274 + onMessage (m) {
274275 this.kernel.incrementTicks(2)
275276 this.kernel.send(m.fromPort, this.kernel.createMessage({
276277 data: 'first'
277278 }))
278279 }
279280 }
280281
281282 class Second extends BaseContainer {
282- run (m) {
283 + onMessage (m) {
283284 this.kernel.incrementTicks(3)
284285 this.kernel.send(m.fromPort, this.kernel.createMessage({
285286 data: 'second'
286287 }))
@@ -309,9 +310,9 @@
309310 t.plan(2)
310311 let runs = 0
311312
312313 class Root extends BaseContainer {
313- run (m) {
314 + onMessage (m) {
314315 if (!runs) {
315316 runs++
316317
317318 const [portRef1, portRef2] = this.kernel.ports.createChannel()
@@ -341,18 +342,18 @@
341342 }
342343 }
343344
344345 class First extends BaseContainer {
345- run (m) {
346 + onMessage (m) {
346347 this.kernel.incrementTicks(2)
347348 this.kernel.send(m.fromPort, this.kernel.createMessage({
348349 data: 'first'
349350 }))
350351 }
351352 }
352353
353354 class Second extends BaseContainer {
354- run (m) {
355 + onMessage (m) {
355356 this.kernel.incrementTicks(1)
356357 this.kernel.send(m.fromPort, this.kernel.createMessage({
357358 data: 'second'
358359 }))
@@ -381,9 +382,9 @@
381382 t.plan(2)
382383 let runs = 0
383384
384385 class Root extends BaseContainer {
385- run (m) {
386 + onMessage (m) {
386387 if (!runs) {
387388 runs++
388389 const [portRef1, portRef2] = this.kernel.ports.createChannel()
389390 const [portRef3, portRef4] = this.kernel.ports.createChannel()
@@ -414,18 +415,18 @@
414415 }
415416 }
416417
417418 class First extends BaseContainer {
418- run (m) {
419 + onMessage (m) {
419420 this.kernel.incrementTicks(1)
420421 this.kernel.send(m.fromPort, this.kernel.createMessage({
421422 data: 'first'
422423 }))
423424 }
424425 }
425426
426427 class Second extends BaseContainer {
427- run (m) {
428 + onMessage (m) {
428429 this.kernel.incrementTicks(2)
429430 this.kernel.send(m.fromPort, this.kernel.createMessage({
430431 data: 'second'
431432 }))
@@ -453,9 +454,9 @@
453454 t.plan(2)
454455 let runs = 0
455456
456457 class Root extends BaseContainer {
457- run (m) {
458 + onMessage (m) {
458459 if (!runs) {
459460 runs++
460461 const [portRef1, portRef2] = this.kernel.ports.createChannel()
461462 const [portRef3, portRef4] = this.kernel.ports.createChannel()
@@ -487,27 +488,27 @@
487488 }
488489 }
489490
490491 class First extends BaseContainer {
491- run (m) {
492 + onMessage (m) {
492493 this.kernel.incrementTicks(2)
493494 this.kernel.send(m.fromPort, this.kernel.createMessage({
494495 data: 'first'
495496 }))
496497 }
497498 }
498499
499500 class Second extends BaseContainer {
500- run (m) {
501 + onMessage (m) {
501502 this.kernel.incrementTicks(3)
502503 this.kernel.send(m.fromPort, this.kernel.createMessage({
503504 data: 'second'
504505 }))
505506 }
506507 }
507508
508509 class Waiter extends BaseContainer {
509- initialize () {
510 + onCreation () {
510511 return new Promise((resolve, reject) => {
511512 setTimeout(() => {
512513 resolve()
513514 }, 200)
@@ -548,9 +549,9 @@
548549
549550 let runs = 0
550551
551552 class Root extends BaseContainer {
552- run (m) {
553 + onMessage (m) {
553554 if (!runs) {
554555 runs++
555556 const [portRef1, portRef2] = this.kernel.ports.createChannel()
556557 const [portRef3, portRef4] = this.kernel.ports.createChannel()
@@ -581,18 +582,18 @@
581582 }
582583 }
583584
584585 class First extends BaseContainer {
585- run (m) {
586 + onMessage (m) {
586587 this.kernel.incrementTicks(2)
587588 this.kernel.send(m.fromPort, this.kernel.createMessage({
588589 data: 'first'
589590 }))
590591 }
591592 }
592593
593594 class Second extends BaseContainer {
594- run (m) {
595 + onMessage (m) {
595596 this.kernel.incrementTicks(2)
596597 this.kernel.send(m.fromPort, this.kernel.createMessage({
597598 data: 'second'
598599 }))
@@ -621,9 +622,9 @@
621622
622623 let runs = 0
623624
624625 class Root extends BaseContainer {
625- run (m) {
626 + onMessage (m) {
626627 if (!runs) {
627628 runs++
628629 const [portRef1, portRef2] = this.kernel.ports.createChannel()
629630 const [portRef3, portRef4] = this.kernel.ports.createChannel()
@@ -654,18 +655,18 @@
654655 }
655656 }
656657
657658 class First extends BaseContainer {
658- run (m) {
659 + onMessage (m) {
659660 this.kernel.incrementTicks(2)
660661 this.kernel.send(m.fromPort, this.kernel.createMessage({
661662 data: 'first'
662663 }))
663664 }
664665 }
665666
666667 class Second extends BaseContainer {
667- run (m) {
668 + onMessage (m) {
668669 this.kernel.incrementTicks(2)
669670 this.kernel.send(m.fromPort, this.kernel.createMessage({
670671 data: 'second'
671672 }))
@@ -695,9 +696,9 @@
695696 let runs = 0
696697 let instance
697698
698699 class Root extends BaseContainer {
699- run (m) {
700 + onMessage (m) {
700701 let one = this.kernel.ports.get('one')
701702 if (!one) {
702703 const [portRef1, portRef2] = this.kernel.ports.createChannel()
703704 this.kernel.ports.bind('one', portRef1)
@@ -712,9 +713,9 @@
712713 }
713714 }
714715
715716 class First extends BaseContainer {
716- run (m) {
717 + onMessage (m) {
717718 ++runs
718719 if (runs === 2) {
719720 t.equals(instance, this, 'should have same instances')
720721 } else {
@@ -788,9 +789,9 @@
788789 const expectedSr = {
789790 '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z'
790791 }
791792 class Root extends BaseContainer {
792- run (m) {
793 + onMessage (m) {
793794 const [portRef1, portRef2] = this.kernel.ports.createChannel()
794795 this.kernel.ports.bind('one', portRef1)
795796 const message1 = this.kernel.createMessage({
796797 ports: [portRef2]
@@ -802,9 +803,9 @@
802803 }
803804 }
804805
805806 class First extends BaseContainer {
806- run (m) {
807 + onMessage (m) {
807808 this.kernel.incrementTicks(2)
808809 this.kernel.ports.delete('root')
809810 }
810811 }
@@ -834,9 +835,9 @@
834835 const expectedSr = {
835836 '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z'
836837 }
837838 class Root extends BaseContainer {
838- run (m) {
839 + onMessage (m) {
839840 this.kernel.createInstance('root')
840841 }
841842 }
842843
@@ -863,18 +864,18 @@
863864 const expectedSr = {
864865 '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z'
865866 }
866867 class Root extends BaseContainer {
867- run (m) {
868 + onMessage (m) {
868869 const [, portRef2] = this.kernel.ports.createChannel()
869870 this.kernel.createInstance('sub', this.kernel.createMessage({
870871 ports: [portRef2]
871872 }))
872873 }
873874 }
874875
875876 class Sub extends BaseContainer {
876- initailize (message) {
877 + onInitailize (message) {
877878 this.kernel.ports.bind('root', message.ports[0])
878879 const [portRef1, portRef2] = root.ports.createChannel()
879880 root.ports.bind('child', portRef1)
880881 root.createInstance('root', root.createMessage({
@@ -906,9 +907,9 @@
906907 const expectedSr = {
907908 '/': 'zdpuAwsZTd5mRZBCYA1FJSHrpYDPgSZSiaTQp9xkUeajaoMHM'
908909 }
909910 class Root extends BaseContainer {
910- run (m) {
911 + onMessage (m) {
911912 if (m.ports.length) {
912913 const port = this.kernel.ports.get('test1')
913914 this.kernel.send(port, m)
914915 this.kernel.ports.unbind('test1')
@@ -931,9 +932,9 @@
931932 }
932933 }
933934
934935 class Sub extends BaseContainer {
935- run (message) {
936 + onMessage (message) {
936937 if (message.data === 'getChannel') {
937938 const ports = this.kernel.ports.createChannel()
938939 this.kernel.ports.bind('channel', ports[0])
939940 this.kernel.send(message.fromPort, this.kernel.createMessage({
@@ -970,9 +971,9 @@
970971 const expectedSr = {
971972 '/': 'zdpuAmi9tkYTpoVsZvqQgxpQFRhCgYFVv4W3fjjfVhf1j8swv'
972973 }
973974 class Root extends BaseContainer {
974- run (m) {
975 + onMessage (m) {
975976 if (m.ports.length) {
976977 const port = this.kernel.ports.get('test1')
977978 this.kernel.send(port, m)
978979 this.kernel.ports.unbind('test1')
@@ -996,9 +997,9 @@
996997 }
997998 }
998999
9991000 class Sub extends BaseContainer {
1000- run (message) {
1001 + onMessage (message) {
10011002 if (message.data === 'getChannel') {
10021003 const ports = this.kernel.ports.createChannel()
10031004 this.kernel.ports.bind('channel', ports[0])
10041005 this.kernel.send(message.fromPort, this.kernel.createMessage({
@@ -1037,9 +1038,9 @@
10371038 let runs = 0
10381039 const returnValue = 'this is a test'
10391040
10401041 class testVMContainer extends BaseContainer {
1041- run (m) {
1042 + onMessage (m) {
10421043 runs++
10431044 if (runs === 1) {
10441045 return returnValue
10451046 } else {
@@ -1070,5 +1071,34 @@
10701071
10711072 rootContainer.send(portRef1, message)
10721073 rootContainer.ports.bind('response', rPort)
10731074 })
1075 +
1076 + tape('start up', async t => {
1077 + t.plan(1)
1078 + class testVMContainer extends BaseContainer {
1079 + onMessage () {}
1080 + onStartup () {
1081 + t.true(true, 'should start up')
1082 + }
1083 + }
1084 +
1085 + const hypervisor = new Hypervisor(node.dag)
1086 + hypervisor.registerContainer('test', testVMContainer)
1087 + await hypervisor.createInstance('test')
1088 + hypervisor.getInstance(hypervisor.ROOT_ID)
1089 + })
1090 +
1091 + tape('large code size', async t => {
1092 + t.plan(1)
1093 + const content = Buffer.from(new ArrayBuffer(1000000))
1094 + class testVMContainer extends BaseContainer {
1095 + onMessage () {}
1096 + }
1097 +
1098 + const hypervisor = new Hypervisor(node.dag)
1099 + hypervisor.registerContainer('test', testVMContainer)
1100 + await hypervisor.createInstance('test', new Message({data: content}))
1101 + const instance = await hypervisor.getInstance(hypervisor.ROOT_ID)
1102 + t.equals(content.length, instance.code.length)
1103 + })
10741104 })

Built with git-ssb-web