git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: e0c13d7ee916e871ad509db7af306b9afcb16160

Files: e0c13d7ee916e871ad509db7af306b9afcb16160 / index.js

4100 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) {
70 const state = await this.tree.get(id, true)
71 const container = this._containerTypes[state.value.type]
72
73 // create a new kernel instance
74 const kernel = new Kernel({
75 hypervisor: this,
76 state: state.value,
77 node: state.node,
78 code: state.value.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
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