Files: eb936c252664b13565410d09b4facc45b738e249 / index.js
3239 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._runningContainers = new Map() |
13 | this._containerTypes = {} |
14 | } |
15 | |
16 | /** |
17 | * get a contrainer instance given its entry port and its mounting port |
18 | * @param {Object} port the entry port for the container |
19 | * @param {Object} parentPort the entry port of the parent container |
20 | */ |
21 | async getOrCreateInstance (port, parentPort) { |
22 | let instance = this._runningContainers.get(port) |
23 | // if there is no container running crceate one |
24 | if (!instance) { |
25 | instance = await this.createInstance(port.type, port.link, port, parentPort) |
26 | instance.on('idle', () => { |
27 | // once the container is done shut it down |
28 | this._runningContainers.delete(port) |
29 | }) |
30 | } |
31 | return instance |
32 | } |
33 | |
34 | /** |
35 | * given a port, wait untill its source contract has reached the threshold |
36 | * tick count |
37 | * @param {Object} port the port to wait on |
38 | * @param {Number} threshold the number of ticks to wait before resolving |
39 | * @param {Object} fromPort the entryPort of the container requesting the |
40 | * wait. Used internally so that waits don't become cyclic |
41 | */ |
42 | async wait (port, threshold, fromPort) { |
43 | let instance = this._runningContainers.get(port) |
44 | if (instance) { |
45 | return instance.wait(threshold, fromPort) |
46 | } else { |
47 | return threshold |
48 | } |
49 | } |
50 | |
51 | /** |
52 | * creates an instance given the container type, starting state, entry port |
53 | * and the parentPort |
54 | * @param {String} the type of VM to load |
55 | * @param {Object} the starting state of the VM |
56 | * @param {Object} the entry port |
57 | * @param {Object} the parent port |
58 | */ |
59 | async createInstance (type, state, entryPort = null, parentPort) { |
60 | const Container = this._containerTypes[type] |
61 | |
62 | if (!state) { |
63 | state = { |
64 | '/': Container.createState() |
65 | } |
66 | } |
67 | |
68 | // create a new kernel instance |
69 | const exoInterface = new ExoInterface({ |
70 | entryPort: entryPort, |
71 | parentPort: parentPort, |
72 | hypervisor: this, |
73 | state: state, |
74 | Container: Container |
75 | }) |
76 | |
77 | // save the newly created instance |
78 | this._runningContainers.set(entryPort, exoInterface) |
79 | await exoInterface.start() |
80 | return exoInterface |
81 | } |
82 | |
83 | /** |
84 | * creates a state root starting from a given container and a given number of |
85 | * ticks |
86 | * @param {Container} container an container instance |
87 | * @param {Number} ticks the number of ticks at which to create the state root |
88 | */ |
89 | async createStateRoot (container, ticks) { |
90 | await container.wait(ticks) |
91 | return this.graph.flush(container.state) |
92 | } |
93 | |
94 | /** |
95 | * regirsters a container with the hypervisor |
96 | * @param {String} the name of the type |
97 | * @param {Class} a Class for instantiating the container |
98 | */ |
99 | registerContainer (type, vm) { |
100 | this._containerTypes[type] = vm |
101 | } |
102 | } |
103 |
Built with git-ssb-web