git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 5abe6750505a23791da65e54301ec095a9551bb6

Files: 5abe6750505a23791da65e54301ec095a9551bb6 / index.js

4113 bytesRaw
1const Kernel = require('./kernel.js')
2const Scheduler = require('./scheduler.js')
3const DFSchecker = require('./dfsChecker.js')
4const CreationService = require('./creationService.js')
5
6const CREATION_ID = 0
7
8module.exports = class Hypervisor {
9 /**
10 * The Hypervisor manages the container instances by instantiating them and
11 * destorying them when possible. It also facilitates localating Containers
12 * @param {Graph} dag an instance of [ipfs.dag](https://github.com/ipfs/interface-ipfs-core/tree/master/API/dag#dag-api)
13 * @param {object} state - the starting state
14 */
15 constructor (tree) {
16 this.tree = tree
17 this.scheduler = new Scheduler()
18 this._containerTypes = {}
19 this._nodesToCheck = new Set()
20
21 this.creationService = new CreationService({
22 hypervisor: this
23 })
24 this.scheduler.systemServices.set(CREATION_ID, this.creationService)
25 this.pinnedIds = new Set()
26 }
27
28 /**
29 * add a potaintail node in the state graph to check for garbage collection
30 * @param {string} id
31 */
32 addNodeToCheck (id) {
33 this._nodesToCheck.add(id)
34 }
35
36 /**
37 * given a port, this finds the corridsponeding endpoint port of the channel
38 * @param {object} port
39 * @returns {Promise}
40 */
41 async getDestPort (port) {
42 if (port.destPort) {
43 return port.destPort
44 } else {
45 const instance = await this.scheduler.getInstance(port.destId)
46 let containerState
47 if (instance) {
48 containerState = instance.state
49 } else {
50 let {value} = await this.tree.get(port.destId, true)
51 containerState = value
52 }
53 return this.tree.graph.get(containerState, `ports/${port.destName}`)
54 }
55 }
56
57 async send (port, message) {
58 const id = port.destId
59 if (id !== undefined) {
60 const instance = await this.getInstance(id)
61 return instance.queue(port, message)
62 } else {
63 // port is unbound
64 port.destPort.messages.push(message)
65 }
66 }
67
68 // loads an instance of a container from the state
69 async _loadInstance (id, state) {
70 if (!state) {
71 state = await this.tree.get(id, true).then(result => result.value)
72 }
73 const container = this._containerTypes[state.type]
74
75 // create a new kernel instance
76 const kernel = new Kernel({
77 hypervisor: this,
78 state: state,
79 code: state.code,
80 container: container,
81 id: id
82 })
83
84 // save the newly created instance
85 this.scheduler.update(kernel)
86 return kernel
87 }
88
89 /**
90 * gets an existsing container instances
91 * @param {string} id - the containers ID
92 * @returns {Promise}
93 */
94 async getInstance (id) {
95 let instance = this.scheduler.getInstance(id)
96 if (instance) {
97 return instance
98 } else {
99 const resolve = this.scheduler.lock(id)
100 const instance = await this._loadInstance(id)
101 await instance.startup()
102 resolve(instance)
103 return instance
104 }
105 }
106
107 createChannel () {
108 const port1 = {
109 messages: []
110 }
111
112 const port2 = {
113 messages: [],
114 destPort: port1
115 }
116
117 port1.destPort = port2
118 return [port1, port2]
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
130 const unlinked = await DFSchecker(this.tree, this._nodesToCheck, (id) => {
131 return this.pinnedIds.has(id)
132 })
133 for (const id of unlinked) {
134 await this.tree.delete(id)
135 }
136 return this.tree.flush()
137 }
138
139 /**
140 * regirsters a container with the hypervisor
141 * @param {Class} Constructor - a Class for instantiating the container
142 * @param {*} args - any args that the contructor takes
143 * @param {interger} typeId - the container's type identification ID
144 */
145 registerContainer (Constructor, args, typeId = Constructor.typeId) {
146 this._containerTypes[typeId] = {
147 Constructor: Constructor,
148 args: args
149 }
150 }
151
152 pin (instance) {
153 this.pinnedIds.add(instance.id)
154 }
155}
156

Built with git-ssb-web