git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: f4727d4ffbe94b91824c9a4dd8f0ac267f806d05

Files: f4727d4ffbe94b91824c9a4dd8f0ac267f806d05 / index.js

4324 bytesRaw
1const Graph = require('ipld-graph-builder')
2const Message = require('primea-message')
3const ExoInterface = require('./exoInterface.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 exoInterface = new ExoInterface({
52 hypervisor: this,
53 state: state,
54 container: container,
55 id: id
56 })
57
58 // save the newly created instance
59 this.scheduler.update(exoInterface)
60 return exoInterface
61 }
62
63 /**
64 * gets an existsing container instances
65 * @param {string} id - the containers ID
66 * @returns {Promise}
67 */
68 async getInstance (id) {
69 let instance = this.scheduler.getInstance(id)
70 if (instance) {
71 return instance
72 } else {
73 const resolve = this.scheduler.getLock(id)
74 const instance = await this._loadInstance(id)
75 resolve(instance)
76 return instance
77 }
78 }
79
80 /**
81 * creates an new container instances and save it in the state
82 * @param {string} type - the type of container to create
83 * @param {*} code
84 * @param {array} entryPorts
85 * @param {object} id
86 * @param {object} id.nonce
87 * @param {object} id.parent
88 * @returns {Promise}
89 */
90 async createInstance (type, code, entryPorts = [], id = {nonce: 0, parent: null}) {
91 // create a lock to prevent the scheduler from reloving waits before the
92 // new container is loaded
93 const resolve = this.scheduler.getLock(id)
94 const idHash = await this.getHashFromObj(id)
95 const state = {
96 nonce: [0],
97 ports: {},
98 type: type,
99 code: code
100 }
101
102 // save the container in the state
103 await this.graph.set(this.state, idHash, state)
104 // create the container instance
105 const exoInterface = await this._loadInstance(idHash)
106
107 resolve(exoInterface)
108 // send the intialization message
109 exoInterface.queue(null, new Message({
110 ports: entryPorts
111 }))
112
113 return exoInterface
114 }
115
116 /**
117 * creates a state root starting from a given container and a given number of
118 * ticks
119 * @param {Number} ticks the number of ticks at which to create the state root
120 * @returns {Promise}
121 */
122 async createStateRoot (ticks) {
123 await this.scheduler.wait(ticks)
124 const unlinked = await DFSchecker(this.graph, this.state, ROOT_ID, this._nodesToCheck)
125 unlinked.forEach(id => {
126 delete this.state[id]
127 })
128 return this.graph.flush(this.state)
129 }
130
131 /**
132 * regirsters a container with the hypervisor
133 * @param {String} type - the name of the type
134 * @param {Class} Constructor - a Class for instantiating the container
135 * @param {*} args - any args that the contructor takes
136 */
137 registerContainer (type, Constructor, args) {
138 this._containerTypes[type] = {
139 Constructor: Constructor,
140 args: args
141 }
142 }
143
144 /**
145 * get a hash from a POJO
146 * @param {object} obj
147 * @return {Promise}
148 */
149 async getHashFromObj (obj) {
150 return (await this.graph.flush(obj))['/']
151 }
152}
153

Built with git-ssb-web