git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 23e12cd33ecd2ef038fb71cc7b53d43a2dd19637

Files: 23e12cd33ecd2ef038fb71cc7b53d43a2dd19637 / index.js

3510 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 let code = await this.tree.graph.get(state.root, '1')
34 let storage = await this.tree.graph.get(state.root, '2')
35 const [type, nonce] = state.value
36 const Container = this._containerTypes[type]
37
38 // create a new actor instance
39 const actor = new Actor({
40 hypervisor: this,
41 state,
42 Container,
43 id,
44 nonce,
45 type,
46 code,
47 storage: storage || [],
48 cachedb: this.tree.dag._dag,
49 tree: this.tree
50 })
51
52 await actor.startup()
53 return actor
54 }
55
56 /**
57 * creates an instance of an Actor
58 * @param {Integer} type - the type id for the container
59 * @param {Object} message - an intial [message](https://github.com/primea/js-primea-message) to send newly created actor
60 * @param {Object} id - the id for the actor
61 */
62 async createActor (type, code, id = {nonce: this.nonce++, parent: null}) {
63 const Container = this._containerTypes[type]
64 const encoded = encodedID(id)
65 let idHash = await this._getHashFromObj(encoded)
66 idHash = new ID(idHash)
67 const module = await Container.onCreation(code, idHash, this.tree)
68 const metaData = [type, 0]
69
70 // save the container in the state
71 this.tree.set(idHash.id, metaData)
72 if (code) {
73 const node = await this.tree.get(idHash.id)
74 await this.tree.graph.set(node.root, '1', code)
75 }
76 return {
77 id: idHash,
78 module: module
79 }
80 }
81
82 // get a hash from a POJO
83 _getHashFromObj (obj) {
84 return this.tree.constructor.getMerkleLink(obj)
85 }
86
87 /**
88 * creates a state root starting from a given container and a given number of
89 * ticks
90 * @param {Number} ticks the number of ticks at which to create the state root
91 * @returns {Promise}
92 */
93 createStateRoot () {
94 return new Promise((resolve, reject) => {
95 this.scheduler.on('idle', () => {
96 this.tree.flush().then(resolve)
97 })
98 })
99 }
100
101 /**
102 * regirsters a container with the hypervisor
103 * @param {Class} Constructor - a Class for instantiating the container
104 * @param {*} args - any args that the contructor takes
105 * @param {Integer} typeId - the container's type identification ID
106 */
107 registerContainer (Constructor) {
108 this._containerTypes[Constructor.typeId] = Constructor
109 }
110}
111
112function encodedID (id) {
113 const nonce = Buffer.from([id.nonce])
114 if (id.parent) {
115 return Buffer.concat([nonce, id.parent.id])
116 } else {
117 return nonce
118 }
119}
120

Built with git-ssb-web