git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 5013b5ed5b183c9bd021b9b9b20f7df558b0a664

Files: 5013b5ed5b183c9bd021b9b9b20f7df558b0a664 / index.js

3525 bytesRaw
1const Actor = require('./actor.js')
2const Scheduler = require('./scheduler.js')
3const {ID} = require('./systemObjects.js')
4
5module.exports = class Hypervisor {
6 /**
7 * The Hypervisor manages the container instances by instantiating them and
8 * destorying them when possible. It also facilitates localating Containers
9 * @param {Tree} tree - a [radix tree](https://github.com/dfinity/js-dfinity-radix-tree) to store the state
10 */
11 constructor (tree, nonce = 0) {
12 this.tree = tree
13 this.scheduler = new Scheduler(this)
14 this._containerTypes = {}
15 this.nonce = nonce
16 }
17
18 /**
19 * sends a message
20 * @param {Object} cap - the capabilitly used to send the message
21 * @param {Object} message - the [message](https://github.com/primea/js-primea-message) to send
22 * @returns {Promise} a promise that resolves once the receiving container is loaded
23 */
24 send (messages) {
25 if (!Array.isArray(messages)) {
26 messages = [messages]
27 }
28 this.scheduler.queue(messages)
29 }
30
31 async loadActor (id) {
32 const state = await this.tree.get(id.id, true)
33 const [code, storage] = await Promise.all([
34 this.tree.graph.get(state.root, '1'),
35 this.tree.graph.get(state.root, '2')
36 ])
37 const [type, nonce] = state.value
38 const Container = this._containerTypes[type]
39
40 // create a new actor instance
41 const actor = new Actor({
42 hypervisor: this,
43 state,
44 Container,
45 id,
46 nonce,
47 type,
48 code,
49 storage: storage || [],
50 cachedb: this.tree.dag._dag,
51 tree: this.tree
52 })
53
54 await actor.startup()
55 return actor
56 }
57
58 /**
59 * creates an instance of an Actor
60 * @param {Integer} type - the type id for the container
61 * @param {Object} message - an intial [message](https://github.com/primea/js-primea-message) to send newly created actor
62 * @param {Object} id - the id for the actor
63 */
64 async createActor (type, code, id = {nonce: this.nonce++, parent: null}) {
65 const Container = this._containerTypes[type]
66 const encoded = encodedID(id)
67 let idHash = await this._getHashFromObj(encoded)
68 idHash = new ID(idHash)
69 const module = await Container.onCreation(code, idHash, this.tree)
70 const metaData = [type, 0]
71
72 // save the container in the state
73 this.tree.set(idHash.id, metaData)
74 if (code) {
75 const node = await this.tree.get(idHash.id)
76 await this.tree.graph.set(node.root, '1', code)
77 }
78 return {
79 id: idHash,
80 module
81 }
82 }
83
84 // get a hash from a POJO
85 _getHashFromObj (obj) {
86 return this.tree.constructor.getMerkleLink(obj)
87 }
88
89 /**
90 * creates a state root starting from a given container and a given number of
91 * ticks
92 * @param {Number} ticks the number of ticks at which to create the state root
93 * @returns {Promise}
94 */
95 createStateRoot () {
96 return new Promise((resolve, reject) => {
97 this.scheduler.on('idle', () => {
98 this.tree.flush().then(resolve)
99 })
100 })
101 }
102
103 /**
104 * regirsters a container with the hypervisor
105 * @param {Class} Constructor - a Class for instantiating the container
106 * @param {*} args - any args that the contructor takes
107 * @param {Integer} typeId - the container's type identification ID
108 */
109 registerContainer (Constructor) {
110 this._containerTypes[Constructor.typeId] = Constructor
111 }
112}
113
114function encodedID (id) {
115 const nonce = Buffer.from([id.nonce])
116 if (id.parent) {
117 return Buffer.concat([nonce, id.parent.id])
118 } else {
119 return nonce
120 }
121}
122

Built with git-ssb-web