git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 9a29a994ba1f806c908192747458ddc1cf46c9d1

changed gernateID to return string

wanderer committed on 4/27/2017, 6:30:30 PM
Parent: 3820100dc50eb86a7f6f941410dc7e8dd2c7aaa7

Files changed

index.jschanged
kernel.jschanged
port.jschanged
portManager.jschanged
tests/index.jschanged
index.jsView
@@ -3,9 +3,8 @@
33
44 module.exports = class Hypervisor {
55 constructor (opts) {
66 this._opts = {
7- hypervisor: this,
87 VMs: {}
98 }
109
1110 this.graph = new Graph(opts.dag)
@@ -14,23 +13,26 @@
1413 Object.assign(this._opts, opts)
1514 }
1615
1716 async getInstance (port) {
18- const id = await this.generateID(port)
17+ let id = await this.generateID(port)
1918 let kernel = this._vmInstances.get(id)
2019 if (!kernel) {
2120 // load the container from the state
2221 await this.graph.tree(port, 2)
22+ // if (port['/']) {
23+ // port = port['/']
24+ // }
2325
2426 // create a new kernel instance
2527 const VM = this._opts.VMs[port.type]
26- const opts = Object.assign({
27- state: port.link,
28- id: port.id,
28+
29+ kernel = new Kernel({
30+ parentPort: port,
31+ hypervisor: this,
2932 VM: VM
30- }, this._opts)
33+ })
3134
32- kernel = new Kernel(opts)
3335 await kernel.start()
3436 kernel.on('idle', () => {
3537 this._vmInstances.delete(id)
3638 })
@@ -47,11 +49,11 @@
4749 }
4850
4951 // given a port, wait untill its source contract has reached the threshold
5052 // tick count
51- async wait (port, ticks) {
53+ async wait (port, threshold) {
5254 let kernel = await this.getInstance(port)
53- await kernel.wait(ticks)
55+ await kernel.wait(threshold)
5456 return kernel
5557 }
5658
5759 createPort (type, payload = {}, id = {nonce: [0], parent: null}) {
@@ -72,10 +74,11 @@
7274 await this.wait(port, ticks)
7375 return this.graph.flush(port)
7476 }
7577
76- generateID (port) {
77- return this.graph.flush(port.id)
78+ async generateID (port) {
79+ const id = await this.graph.flush(port.id)
80+ return id['/']
7881 }
7982
8083 addVM (type, vm) {
8184 this._opts.VMs[type] = vm
kernel.jsView
@@ -6,16 +6,22 @@
66 module.exports = class Kernel extends EventEmitter {
77 constructor (opts) {
88 super()
99 this._opts = opts
10+ this.state = opts.parentPort.link['/']
1011 this.vmState = 'idle'
1112 this.ticks = 0
1213 this.ports = new PortManager(this)
1314 this.vm = new opts.VM(this)
1415 this._waitingQueue = new PriorityQueue((a, b) => {
1516 return a.threshold > b.threshold
1617 })
1718 this.on('result', this._runNextMessage)
19+ this.on('idle', () => {
20+ while (!this._waitingQueue.isEmpty()) {
21+ this._waitingQueue.poll().resolve()
22+ }
23+ })
1824 }
1925
2026 start () {
2127 return this.ports.start()
@@ -33,8 +39,9 @@
3339 }
3440 }
3541
3642 _runNextMessage () {
43+ this._updateVmState('running')
3744 this.ports.getNextMessage(this.ticks).then(message => {
3845 if (message) {
3946 this.run(message)
4047 } else {
@@ -48,9 +55,8 @@
4855 * The Kernel Stores all of its state in the Environment. The Interface is used
4956 * to by the VM to retrive infromation from the Environment.
5057 */
5158 async run (message) {
52- this._updateVmState('running', message)
5359 // shallow copy
5460 const oldState = Object.assign({}, this._opts.state)
5561 let result
5662 try {
@@ -60,67 +66,65 @@
6066 result = {
6167 exception: true,
6268 exceptionError: e
6369 }
64- }
65-
66- if (result.exception) {
67- // revert to the old state
6870 clearObject(this._opts.state)
6971 Object.assign(this._opts.state, oldState)
7072 }
7173
72- this._updateVmState('result', result)
74+ this.emit('result', result)
7375 return result
7476 }
7577
7678 // returns a promise that resolves once the kernel hits the threshould tick
7779 // count
7880 async wait (threshold) {
79- if (this.vmState !== 'running' && threshold > this.ticks) {
80- // the cotract is at idle so wait
81- return this.ports.wait(threshold)
82- } else {
83- return new Promise((resolve, reject) => {
84- if (threshold <= this.ticks) {
85- resolve(this.ticks)
86- } else {
87- this._waitingQueue.add({
88- threshold: threshold,
89- resolve: resolve
90- })
91- }
92- })
93- }
81+ return new Promise((resolve, reject) => {
82+ if (threshold <= this.ticks) {
83+ resolve(this.ticks)
84+ } else {
85+ this._waitingQueue.add({
86+ threshold: threshold,
87+ resolve: resolve
88+ })
89+ }
90+ })
9491 }
9592
96- _updateTickCount (count) {
97- this.ticks = count
98- while (this._waitingQueue.peek().threshold <= count) {
99- this._waitingQueue.poll().resolve(count)
93+ incrementTicks (count) {
94+ this.ticks += count
95+ while (!this._waitingQueue.isEmpty()) {
96+ const waiter = this._waitingQueue.peek()
97+ if (waiter.threshold > this.ticks) {
98+ break
99+ } else {
100+ this._waitingQueue.poll().resolve(this.ticks)
101+ }
100102 }
101103 }
102104
103105 async createPort (manager, type, name, payload) {
104106 // incerment the nonce
105- const nonce = new BN(this.nonce)
107+ const nonce = new BN(this._opts.state.nonce)
106108 nonce.iaddn(1)
107- this.nonce = nonce.toArrayLike(Buffer)
109+ this._opts.state.nonce = nonce.toArrayLike(Buffer)
108110
109111 const parentID = await this._opts.hypervisor.generateID({
110112 id: this._opts.id
111113 })
112114
113- const port = this._opts.hypervisor.createPort(type, payload, {
115+ let port = this._opts.hypervisor.createPort(type, payload, {
114116 nonce: this.nonce,
115117 parent: parentID
116118 })
117- manager.set(name, port)
119+ await manager.set(name, port)
118120 return port
119121 }
120122
121123 async send (port, message) {
122124 message._ticks = this.ticks
125+ const portObject = await this.ports.get(port)
126+ portObject.hasSent = true
123127 return this._opts.hypervisor.send(port, message)
124128 }
125129 }
126130
port.jsView
@@ -1,7 +1,8 @@
11 module.exports = class Port {
22 constructor (name) {
33 this.name = name
4+ this.hasSent = false
45 this._queue = []
56 this.ticks = 0
67 }
78
portManager.jsView
@@ -1,8 +1,11 @@
11 const Port = require('./port.js')
2+const PARENT = Symbol('parent')
23
34 // decides which message to go firts
45 function messageArbiter (portA, portB) {
6+ portA = portA[1]
7+ portB = portB[1]
58 const a = portA.peek()
69 const b = portB.peek()
710
811 if (!a) {
@@ -25,9 +28,10 @@
2528 module.exports = class PortManager {
2629 constructor (kernel) {
2730 this.kernel = kernel
2831 this.hypervisor = kernel._opts.hypervisor
29- this.ports = kernel._opts.state['/'].ports
32+ this.ports = kernel.state.ports
33+ this.parentPort = kernel._opts.parentPort
3034 this._portMap = new Map()
3135 }
3236
3337 async start () {
@@ -38,15 +42,16 @@
3842 })
3943
4044 // create the parent port
4145 await Promise.all(ports)
42- this._portMap.set(this.kernel._opts.id, new Port('parent'))
46+ const parentID = await this.hypervisor.generateID(this.kernel._opts.parentPort)
47+ this._portMap.set(parentID, new Port(PARENT))
4348 }
4449
45- _mapPort (name, port) {
46- this.hypervisor.generateID(port).then(id => {
47- this._portMap.set(id, new Port(name))
48- })
50+ async _mapPort (name, port) {
51+ const id = await this.hypervisor.generateID(port)
52+ port = new Port(name)
53+ this._portMap.set(id, port)
4954 }
5055
5156 queue (message) {
5257 this._portMap.get(message.fromPort).queue(message)
@@ -65,36 +70,43 @@
6570 this.ports[to] = this.ports[from]
6671 delete this.ports[from]
6772 }
6873
69- async get (name) {
70- const port = await this.graph.get(this.state.ports, name)
74+ async get (port) {
7175 const id = await this.hypervisor.generateID(port)
7276 return this._portMap.get(id)
7377 }
7478
7579 async getParent () {
76- const id = await this.hypervisor.generateID(this.kernel._opts)
80+ const id = await this.hypervisor.generateID(this.kernel._opt.parentPort)
7781 return this._portMap.get(id)
7882 }
7983
8084 // waits till all ports have reached a threshold tick count
8185 async wait (threshold) {
8286 // find the ports that have a smaller tick count then the threshold tick count
8387 const unkownPorts = [...this._portMap].filter(([id, port]) => {
84- return port._ticks < threshold
88+ return (port.hasSent || port.name === PARENT) && port.ticks < threshold
8589 })
8690
8791 const promises = unkownPorts.map(([id, port]) => {
88- this.hypervisor.wait(id, threshold).then(ticks => {
92+ if (port.name === PARENT) {
93+ port = this.parentPort
94+ } else {
95+ port = this.ports[port.name]
96+ }
97+ this.hypervisor.wait(port, threshold).then(ticks => {
8998 // update the port's tick count
9099 port.ticks = ticks
91100 })
92101 })
93- await Promise.all(promises)
102+ return await Promise.all(promises)
94103 }
95104
96105 async getNextMessage (ticks) {
97106 await this.wait(ticks)
98- return [...this._portMap].reduce(messageArbiter)[1].shift()
107+ const portMap = [...this._portMap].reduce(messageArbiter)
108+ if (portMap) {
109+ return portMap[1].shift()
110+ }
99111 }
100112 }
tests/index.jsView
@@ -5,11 +5,15 @@
55
66 const node = new IPFS()
77
88 class BaseContainer {
9+ constructor (kernel) {
10+ this.kernel = kernel
11+ }
12+
913 static createState (code) {
1014 return {
11- nonce: Buffer.from([0]),
15+ nonce: [0],
1216 ports: {}
1317 }
1418 }
1519 }
@@ -20,63 +24,79 @@
2024
2125 node.on('start', () => {
2226 tape.only('basic', async t => {
2327 const message = new Message()
24- const expectedState = { '/': 'zdpuB2hzCvqE34W71CFtqqzHLP8kyuwGZm1bz8Cy2kAVCh1fP' }
28+ const expectedState = {
29+ '/': 'zdpuB2hzCvqE34W71CFtqqzHLP8kyuwGZm1bz8Cy2kAVCh1fP'
30+ }
2531
2632 class testVMContainer extends BaseContainer {
2733 run (m) {
2834 t.true(m === message, 'should recive a message')
2935 }
3036 }
3137
32- const hypervisor = new Hypervisor({dag: node.dag})
33- hypervisor.addVM('test', testVMContainer)
34- const port = hypervisor.createPort('test')
38+ try {
39+ const hypervisor = new Hypervisor({dag: node.dag})
40+ hypervisor.addVM('test', testVMContainer)
41+ const port = hypervisor.createPort('test')
3542
36- await hypervisor.send(port, message)
37- await hypervisor.createStateRoot(port, Infinity)
38- t.deepEquals(port, expectedState, 'expected')
39- // await hypervisor.graph.tree(port, Infinity)
40- // console.log(JSON.stringify(port, null, 2))
43+ await hypervisor.send(port, message)
44+ await hypervisor.createStateRoot(port, Infinity)
45+
46+ t.deepEquals(port, expectedState, 'expected')
47+ } catch (e) {
48+ console.log(e)
49+ }
4150 t.end()
4251 })
4352
4453 tape('one child contract', async t => {
45- t.end()
4654 const message = new Message()
47- const expectedState = { '/': 'zdpuAwqyF4X1hAHMBcsn7eDJXcLfcyoyEWWR73eeqXXmFkBe3' }
55+ const expectedState = {
56+ '/': 'zdpuAwUPELiXpnd66Wum84VRPEsUGB7cUuxUESDMXmpVj6prc'
57+ }
4858
4959 class testVMContainer2 extends BaseContainer {
5060 run (m) {
51- console.log('here!')
52- t.true(m === message, 'should recive a message')
61+ t.true(m === message, 'should recive a message 2')
62+ return new Promise((resolve, reject) => {
63+ setTimeout(() => {
64+ console.log('resolve!!')
65+ this.kernel.incrementTicks(1)
66+ resolve()
67+ }, 200)
68+ })
5369 }
5470 }
5571
5672 class testVMContainer extends BaseContainer {
57- constructor (kernel) {
58- super()
59- this.kernel = kernel
60- }
61-
6273 async run (m) {
63- console.log('first')
6474 const port = await this.kernel.createPort(this.kernel.ports, 'test2', 'child')
65- return this.kernel.send(port, m)
75+ await this.kernel.send(port, m)
76+ this.kernel.incrementTicks(1)
6677 }
6778 }
6879
69- const hypervisor = new Hypervisor({dag: node.dag})
70- hypervisor.addVM('test', testVMContainer)
71- hypervisor.addVM('test2', testVMContainer2)
72- const port = hypervisor.createPort('test')
80+ try {
81+ const hypervisor = new Hypervisor({dag: node.dag})
82+ hypervisor.addVM('test', testVMContainer)
83+ hypervisor.addVM('test2', testVMContainer2)
84+ const port = hypervisor.createPort('test')
7385
74- await hypervisor.send(port, message)
75- await hypervisor.createStateRoot(port, Infinity)
76- t.deepEquals(port, expectedState, 'expected')
86+ await hypervisor.send(port, message)
87+ await hypervisor.createStateRoot(port, Infinity)
88+ console.log('create state root')
7789
90+ // await hypervisor.graph.tree(port, Infinity)
91+ // console.log(JSON.stringify(port, null, 2))
92+ // t.deepEquals(port, expectedState, 'expected')
93+ } catch (e) {
94+ console.log(e)
95+ }
96+
97+ t.end()
7898 node.stop(() => {
79- process.exit()
99+ // process.exit()
80100 })
81101 })
82102 })

Built with git-ssb-web