git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 1cfa89100b6932dc2f692d9f806822895ada81ad

Files: 1cfa89100b6932dc2f692d9f806822895ada81ad / index.js

4246 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, message = new Message(), 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 code = message.data.byteLength ? message.data : undefined
101 const state = {
102 nonce: [0],
103 ports: {},
104 type: type,
105 code: code
106 }
107
108 // save the container in the state
109 await this.graph.set(this.state, idHash, state)
110 // create the container instance
111 const instance = await this._loadInstance(idHash)
112
113 resolve(instance)
114 // send the intialization message
115 instance.initialize(message)
116
117 return instance
118 }
119
120 /**
121 * creates a state root starting from a given container and a given number of
122 * ticks
123 * @param {Number} ticks the number of ticks at which to create the state root
124 * @returns {Promise}
125 */
126 async createStateRoot (ticks) {
127 await this.scheduler.wait(ticks)
128 const unlinked = await DFSchecker(this.graph, this.state, ROOT_ID, this._nodesToCheck)
129 unlinked.forEach(id => {
130 delete this.state[id]
131 })
132 return this.graph.flush(this.state)
133 }
134
135 /**
136 * regirsters a container with the hypervisor
137 * @param {String} type - the name of the type
138 * @param {Class} Constructor - a Class for instantiating the container
139 * @param {*} args - any args that the contructor takes
140 */
141 registerContainer (type, Constructor, args) {
142 this._containerTypes[type] = {
143 Constructor: Constructor,
144 args: args
145 }
146 }
147}
148

Built with git-ssb-web