git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 0b60f6ffa1bef52d1491a87e1d7aa604092d0af2

Files: 0b60f6ffa1bef52d1491a87e1d7aa604092d0af2 / index.js

3370 bytesRaw
1const Kernel = require('./actor.js')
2const Scheduler = require('./scheduler.js')
3
4module.exports = class Hypervisor {
5 /**
6 * The Hypervisor manages the container instances by instantiating them and
7 * destorying them when possible. It also facilitates localating Containers
8 * @param {Graph} dag an instance of [ipfs.dag](https://github.com/ipfs/interface-ipfs-core/tree/master/API/dag#dag-api)
9 * @param {object} state - the starting state
10 */
11 constructor (tree) {
12 this.tree = tree
13 this.scheduler = new Scheduler()
14 this._containerTypes = {}
15 this.nonce = 0
16 }
17
18 async send (cap, message) {
19 cap = await Promise.resolve(cap)
20 const id = cap.destId
21 const instance = await this.getInstance(id)
22 return instance.queue(message)
23 }
24
25 // loads an instance of a container from the state
26 async _loadInstance (id) {
27 const state = await this.tree.get(id, true)
28 const container = this._containerTypes[state.value.type]
29
30 // create a new kernel instance
31 const kernel = new Kernel({
32 hypervisor: this,
33 state: state.value,
34 node: state.node,
35 code: state.value.code,
36 container: container,
37 id: id
38 })
39
40 // save the newly created instance
41 this.scheduler.update(kernel)
42 return kernel
43 }
44
45 /**
46 * gets an existsing container instances
47 * @param {string} id - the containers ID
48 * @returns {Promise}
49 */
50 async getInstance (id) {
51 let instance = this.scheduler.getInstance(id)
52 if (instance) {
53 return instance
54 } else {
55 const resolve = this.scheduler.lock(id)
56 const instance = await this._loadInstance(id)
57 await instance.startup()
58 resolve(instance)
59 return instance
60 }
61 }
62
63 async createInstance (type, message, id = {nonce: this.nonce, parent: null}) {
64 const encoded = encodedID(id)
65 this.nonce++
66 const idHash = await this._getHashFromObj(encoded)
67 const state = {
68 nonce: 0,
69 caps: {},
70 type: type
71 }
72
73 const code = message.data
74 if (code.length) {
75 state.code = code
76 }
77
78 // save the container in the state
79 await this.tree.set(idHash, state)
80
81 // create the container instance
82 const instance = await this._loadInstance(idHash)
83
84 // send the intialization message
85 await instance.create(message)
86 return instance.mintCap()
87 }
88
89 // get a hash from a POJO
90 _getHashFromObj (obj) {
91 return this.tree.constructor.getMerkleLink(obj)
92 }
93
94 /**
95 * creates a state root starting from a given container and a given number of
96 * ticks
97 * @param {Number} ticks the number of ticks at which to create the state root
98 * @returns {Promise}
99 */
100 async createStateRoot (ticks) {
101 await this.scheduler.wait(ticks)
102 return this.tree.flush()
103 }
104
105 /**
106 * regirsters a container with the hypervisor
107 * @param {Class} Constructor - a Class for instantiating the container
108 * @param {*} args - any args that the contructor takes
109 * @param {interger} typeId - the container's type identification ID
110 */
111 registerContainer (Constructor, args, typeId = Constructor.typeId) {
112 this._containerTypes[typeId] = {
113 Constructor: Constructor,
114 args: args
115 }
116 }
117}
118
119function encodedID (id) {
120 const nonce = Buffer.from([id.nonce])
121 if (id.parent) {
122 return Buffer.concat([nonce, id.parent])
123 } else {
124 return nonce
125 }
126}
127

Built with git-ssb-web