git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 317d79e49cb56dd81cb9c94072cd24ad6a825757

Files: 317d79e49cb56dd81cb9c94072cd24ad6a825757 / index.js

4230 bytesRaw
1const Graph = require('ipld-graph-builder')
2const Message = require('primea-message')
3const Kernel = require('./kernel.js')
4const Scheduler = require('./scheduler.js')
5const DFSchecker = require('./dfsChecker.js')
6
7const ROOT_ID = 'zdpuAm6aTdLVMUuiZypxkwtA7sKm7BWERy8MPbaCrFsmiyzxr'
8
9module.exports = class Hypervisor {
10 /**
11 * The Hypervisor manages the container instances by instantiating them and
12 * destorying them when possible. It also facilitates localating Containers
13 * @param {Graph} dag an instance of [ipfs.dag](https://github.com/ipfs/interface-ipfs-core/tree/master/API/dag#dag-api)
14 * @param {object} state - the starting state
15 */
16 constructor (dag, state = {}) {
17 this.graph = new Graph(dag)
18 this.scheduler = new Scheduler()
19 this.state = state
20 this._containerTypes = {}
21 this._nodesToCheck = new Set()
22 }
23
24 /**
25 * add a potaintail node in the state graph to check for garbage collection
26 * @param {string} id
27 */
28 addNodeToCheck (id) {
29 this._nodesToCheck.add(id)
30 }
31
32 /**
33 * given a port, this finds the corridsponeding endpoint port of the channel
34 * @param {object} port
35 * @returns {Promise}
36 */
37 getDestPort (port) {
38 if (port.destPort) {
39 return port.destPort
40 } else {
41 return this.graph.get(this.state, `${port.destId}/ports/${port.destName}`)
42 }
43 }
44
45 // loads an instance of a container from the state
46 async _loadInstance (id) {
47 const state = await this.graph.get(this.state, id)
48 const container = this._containerTypes[state.type]
49
50 // create a new kernel instance
51 const kernel = new Kernel({
52 hypervisor: this,
53 state: state,
54 container: container,
55 id: id
56 })
57
58 // save the newly created instance
59 this.scheduler.update(kernel)
60 return kernel
61 }
62
63 // get a hash from a POJO
64 async _getHashFromObj (obj) {
65 return (await this.graph.flush(obj))['/']
66 }
67
68 /**
69 * gets an existsing container instances
70 * @param {string} id - the containers ID
71 * @returns {Promise}
72 */
73 async getInstance (id) {
74 let instance = this.scheduler.getInstance(id)
75 if (instance) {
76 return instance
77 } else {
78 const resolve = this.scheduler.getLock(id)
79 const instance = await this._loadInstance(id)
80 resolve(instance)
81 return instance
82 }
83 }
84
85 /**
86 * creates an new container instances and save it in the state
87 * @param {string} type - the type of container to create
88 * @param {*} code
89 * @param {array} entryPorts
90 * @param {object} id
91 * @param {object} id.nonce
92 * @param {object} id.parent
93 * @returns {Promise}
94 */
95 async createInstance (type, code, entryPorts = [], id = {nonce: 0, parent: null}) {
96 // create a lock to prevent the scheduler from reloving waits before the
97 // new container is loaded
98 const resolve = this.scheduler.getLock(id)
99 const idHash = await this._getHashFromObj(id)
100 const state = {
101 nonce: [0],
102 ports: {},
103 type: type,
104 code: code
105 }
106
107 // save the container in the state
108 await this.graph.set(this.state, idHash, state)
109 // create the container instance
110 const exoInterface = await this._loadInstance(idHash)
111
112 resolve(exoInterface)
113 // send the intialization message
114 exoInterface.queue(null, new Message({
115 ports: entryPorts
116 }))
117
118 return exoInterface
119 }
120
121 /**
122 * creates a state root starting from a given container and a given number of
123 * ticks
124 * @param {Number} ticks the number of ticks at which to create the state root
125 * @returns {Promise}
126 */
127 async createStateRoot (ticks) {
128 await this.scheduler.wait(ticks)
129 const unlinked = await DFSchecker(this.graph, this.state, ROOT_ID, this._nodesToCheck)
130 unlinked.forEach(id => {
131 delete this.state[id]
132 })
133 return this.graph.flush(this.state)
134 }
135
136 /**
137 * regirsters a container with the hypervisor
138 * @param {String} type - the name of the type
139 * @param {Class} Constructor - a Class for instantiating the container
140 * @param {*} args - any args that the contructor takes
141 */
142 registerContainer (type, Constructor, args) {
143 this._containerTypes[type] = {
144 Constructor: Constructor,
145 args: args
146 }
147 }
148}
149

Built with git-ssb-web