git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 92d7c78382c4c1263d34dc2eced70feb25a04d85

Files: 92d7c78382c4c1263d34dc2eced70feb25a04d85 / index.js

4056 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 containerState = await this.tree.get(port.destId, true)
51 }
52 return this.tree.graph.get(containerState, `ports/${port.destName}`)
53 }
54 }
55
56 async send (port, message) {
57 const id = port.destId
58 if (id !== undefined) {
59 const instance = await this.getInstance(id)
60 return instance.queue(port, message)
61 } else {
62 // port is unbound
63 port.destPort.messages.push(message)
64 }
65 }
66
67 // loads an instance of a container from the state
68 async _loadInstance (id, state) {
69 if (!state) {
70 state = await this.tree.get(id, true)
71 }
72 const container = this._containerTypes[state.type]
73
74 // create a new kernel instance
75 const kernel = new Kernel({
76 hypervisor: this,
77 state: state,
78 code: state.code,
79 container: container,
80 id: id
81 })
82
83 // save the newly created instance
84 this.scheduler.update(kernel)
85 return kernel
86 }
87
88 /**
89 * gets an existsing container instances
90 * @param {string} id - the containers ID
91 * @returns {Promise}
92 */
93 async getInstance (id) {
94 let instance = this.scheduler.getInstance(id)
95 if (instance) {
96 return instance
97 } else {
98 const resolve = this.scheduler.lock(id)
99 const instance = await this._loadInstance(id)
100 await instance.startup()
101 resolve(instance)
102 return instance
103 }
104 }
105
106 createChannel () {
107 const port1 = {
108 messages: []
109 }
110
111 const port2 = {
112 messages: [],
113 destPort: port1
114 }
115
116 port1.destPort = port2
117 return [port1, port2]
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
129 const unlinked = await DFSchecker(this.tree, this._nodesToCheck, (id) => {
130 return this.pinnedIds.has(id)
131 })
132 for (const id of unlinked) {
133 await this.tree.delete(id)
134 }
135 return this.tree.flush()
136 }
137
138 /**
139 * regirsters a container with the hypervisor
140 * @param {Class} Constructor - a Class for instantiating the container
141 * @param {*} args - any args that the contructor takes
142 * @param {interger} typeId - the container's type identification ID
143 */
144 registerContainer (Constructor, args, typeId = Constructor.typeId) {
145 this._containerTypes[typeId] = {
146 Constructor: Constructor,
147 args: args
148 }
149 }
150
151 pin (instance) {
152 this.pinnedIds.add(instance.id)
153 }
154}
155

Built with git-ssb-web