Files: 42bb5a2f36de56726c4bd6ede09c95352d5b545d / index.js
3666 bytesRaw
1 | const Graph = require('ipld-graph-builder') |
2 | const ExoInterface = require('./exoInterface.js') |
3 | |
4 | module.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