git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 1df41b95ebf09568a8c125df38f2bcedfb9ad8b5

Files: 1df41b95ebf09568a8c125df38f2bcedfb9ad8b5 / index.js

3666 bytesRaw
1const Graph = require('ipld-graph-builder')
2const ExoInterface = require('./exoInterface.js')
3
4module.exports = class Hypervisor {
5 /**
6 * The Hypervisor manages the container instances by instantiating them and
7 * destorying them when possible. It also facilitates localating Containers
8 * @param {Graph} dag an instance of [ipfs.dag](https://github.com/ipfs/interface-ipfs-core/tree/master/API/dag#dag-api)
9 */
10 constructor (dag) {
11 this.graph = new Graph(dag)
12 this._containerInstances = new Map()
13 this._containerTypes = {}
14 }
15
16 /**
17 * get a container by its path
18 * @param {Object} root - the root container to start searching from
19 * @param {String} path - the path to travers
20 */
21 async getInstanceByPath (root, path) {
22 path = path.split('/')
23 for (const name of path) {
24 const portRef = root.ports.get(name)
25 root = await this.getInstanceByPort(portRef, root.entryPort)
26 }
27 return root
28 }
29
30 /**
31 * get a contrainer instance given its entry port and its mounting port
32 * @param {Object} port the entry port for the container
33 * @param {Object} parentPort the entry port of the parent container
34 */
35 async getInstanceByPort (port, parentPort) {
36 let instance = this._containerInstances.get(port)
37 // if there is no container running crceate one
38 if (!instance) {
39 instance = await this.createInstance(port.type, port.link, port, parentPort)
40 instance.on('idle', () => {
41 // once the container is done shut it down
42 this._containerInstances.delete(port)
43 })
44 }
45 return instance
46 }
47
48 /**
49 * given a port, wait untill its source contract has reached the threshold
50 * tick count
51 * @param {Object} port the port to wait on
52 * @param {Number} threshold the number of ticks to wait before resolving
53 * @param {Object} fromPort the entryPort of the container requesting the
54 * wait. Used internally so that waits don't become cyclic
55 */
56 async wait (port, threshold, fromPort) {
57 let instance = this._containerInstances.get(port)
58 if (instance) {
59 return instance.wait(threshold, fromPort)
60 } else {
61 return threshold
62 }
63 }
64
65 /**
66 * creates an instance given the container type, starting state, entry port
67 * and the parentPort
68 * @param {String} the type of VM to load
69 * @param {Object} the starting state of the VM
70 * @param {Object} the entry port
71 * @param {Object} the parent port
72 */
73 async createInstance (type, state, entryPort = null, parentPort) {
74 const Container = this._containerTypes[type]
75
76 if (!state) {
77 state = {
78 '/': Container.createState()
79 }
80 }
81
82 // create a new kernel instance
83 const exoInterface = new ExoInterface({
84 entryPort: entryPort,
85 parentPort: parentPort,
86 hypervisor: this,
87 state: state,
88 Container: Container
89 })
90
91 // save the newly created instance
92 this._containerInstances.set(entryPort, exoInterface)
93 await exoInterface.start()
94 return exoInterface
95 }
96
97 /**
98 * creates a state root starting from a given container and a given number of
99 * ticks
100 * @param {Container} container an container instance
101 * @param {Number} ticks the number of ticks at which to create the state root
102 * @returns {Promise}
103 */
104 async createStateRoot (container, ticks) {
105 await container.wait(ticks)
106 return this.graph.flush(container.state)
107 }
108
109 /**
110 * regirsters a container with the hypervisor
111 * @param {String} the name of the type
112 * @param {Class} a Class for instantiating the container
113 */
114 registerContainer (type, vm) {
115 this._containerTypes[type] = vm
116 }
117}
118

Built with git-ssb-web