flok 0.0.36 → 0.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +1 -0
- data/app/drivers/chrome/build_context.rb +1 -1
- data/app/drivers/chrome/config.yml +10 -0
- data/app/drivers/chrome/pipe.rb +24 -1
- data/app/drivers/chrome/src/persist.js +29 -0
- data/app/drivers/chrome/src/sockio.js +3 -1
- data/app/drivers/chrome/src/vendor/store2.js +3 -0
- data/app/kern/callout.js +55 -0
- data/app/kern/controller.js +3 -0
- data/app/kern/crc32.js +22 -0
- data/app/kern/dispatch.js +16 -0
- data/app/kern/mod/event.js +3 -0
- data/app/kern/mod/persist.js +1 -0
- data/app/kern/mod/timer.js +5 -0
- data/app/kern/pagers/mem_pager.js +2 -0
- data/app/kern/pagers/sockio_pager.js +66 -0
- data/app/kern/pagers/spec0.js +35 -0
- data/app/kern/pagers/spec1.js +24 -0
- data/app/kern/pagers/spec2.js +31 -0
- data/app/kern/services/test.rb +7 -0
- data/app/kern/services/vm.rb +141 -0
- data/app/kern/spec_helper.js +5 -0
- data/bin/flok +27 -5
- data/docs/callout.md +8 -0
- data/docs/client_api.md +1 -1
- data/docs/compilation.md +14 -8
- data/docs/controllers.md +2 -1
- data/docs/datatypes.md +3 -1
- data/docs/environmentals.md +6 -0
- data/docs/interactive.md +6 -1
- data/docs/kernel_api.md +3 -0
- data/docs/mod/event.md +5 -1
- data/docs/mod/persist.md +14 -31
- data/docs/mod/timer.md +4 -2
- data/docs/project.md +16 -5
- data/docs/scheduling.md +1 -0
- data/docs/services.md +141 -56
- data/docs/services/vm.md +128 -0
- data/docs/services/vm/pagers.md +46 -0
- data/lib/flok/build.rb +11 -16
- data/lib/flok/platform.rb +29 -6
- data/lib/flok/project_template/app/scripts/script.js +3 -0
- data/lib/flok/project_template/app/services/service.rb +1 -0
- data/lib/flok/project_template/config/config.yml +1 -0
- data/lib/flok/project_template/config/platforms/chrome/config.yml +1 -0
- data/lib/flok/project_template/config/services.rb +1 -0
- data/lib/flok/service_compiler_templates/services.js.erb +78 -9
- data/lib/flok/services_compiler.rb +117 -20
- data/lib/flok/user_compiler.rb +14 -6
- data/lib/flok/user_compiler_templates/ctable.js.erb +10 -0
- data/lib/flok/version.rb +1 -1
- data/spec/env/etc.rb +1 -1
- data/spec/env/global.rb +2 -0
- data/spec/env/iface.rb +20 -4
- data/spec/env/kern.rb +8 -3
- data/spec/etc/cli_spec.rb +319 -165
- data/spec/etc/lib/assets/config.yml +3 -0
- data/spec/etc/lib/platform_spec.rb +14 -10
- data/spec/etc/lib/project_spec.rb +22 -0
- data/spec/etc/service_compiler/config0.rb +1 -0
- data/spec/etc/service_compiler/config1.rb +1 -0
- data/spec/etc/service_compiler/config2.rb +3 -0
- data/spec/etc/service_compiler/service0.rb +22 -6
- data/spec/etc/service_compiler/service1.rb +26 -0
- data/spec/etc/service_compiler/service_bad_type.rb +20 -0
- data/spec/etc/services_compiler_spec.rb +35 -16
- data/spec/etc/user_compiler/data.js +2 -0
- data/spec/etc/user_compiler_spec.rb +7 -1
- data/spec/iface/driver/persist_spec.rb +106 -0
- data/spec/iface/driver/pipe_spec.rb +5 -0
- data/spec/iface/kern/ping_spec.rb +4 -3
- data/spec/kern/assets/blank.rb +0 -0
- data/spec/kern/assets/service0.rb +24 -0
- data/spec/kern/assets/service1.rb +22 -0
- data/spec/kern/assets/service2.rb +27 -0
- data/spec/kern/assets/service_config0.rb +2 -0
- data/spec/kern/assets/service_config1.rb +2 -0
- data/spec/kern/assets/service_controller0.rb +13 -0
- data/spec/kern/assets/service_controller1.rb +32 -0
- data/spec/kern/assets/service_controller2.rb +38 -0
- data/spec/kern/assets/service_controller3.rb +38 -0
- data/spec/kern/assets/vm/config0.rb +2 -0
- data/spec/kern/assets/vm/config1.rb +12 -0
- data/spec/kern/assets/vm/config2.rb +12 -0
- data/spec/kern/assets/vm/config3.rb +12 -0
- data/spec/kern/assets/vm/controller0.rb +8 -0
- data/spec/kern/assets/vm/controller1.rb +18 -0
- data/spec/kern/assets/vm/controller2.rb +18 -0
- data/spec/kern/assets/vm/controller3.rb +20 -0
- data/spec/kern/assets/vm/controller4.rb +22 -0
- data/spec/kern/assets/vm/controller5.rb +22 -0
- data/spec/kern/assets/vm/controller6.rb +21 -0
- data/spec/kern/assets/vm/service0.rb +24 -0
- data/spec/kern/assets/vm/service_controller0.rb +7 -0
- data/spec/kern/callout_spec.rb +153 -0
- data/spec/kern/functions_spec.rb +29 -0
- data/spec/kern/service_controller_spec.rb +213 -0
- data/spec/kern/vm_service_spec.rb +195 -0
- metadata +98 -12
- data/app/kern/services/rest.rb +0 -310
- data/app/kern/services/timer.rb +0 -30
- data/docs/services/timer.md +0 -21
- data/spec/kern/assets/rest_service.rb +0 -20
- data/spec/kern/assets/timer_service.rb +0 -19
- data/spec/kern/timer_service_spec.rb +0 -40
data/docs/scheduling.md
CHANGED
@@ -14,6 +14,7 @@ The first departure from a traditional operating system scheduler is that *Flok*
|
|
14
14
|
2. `disk` - Transferring things to/from disk
|
15
15
|
3. `cpu` - Tasks that tax the cpu
|
16
16
|
4. `gpu` - Tasks that tax the gpu
|
17
|
+
5. `async` - Tasks that shouldn't run on the main thread, but are not scheduled limited.
|
17
18
|
|
18
19
|
##Flok also has two priority classes (Does not effect `main` queue):
|
19
20
|
* `high` - Things that need to happen soon.
|
data/docs/services.md
CHANGED
@@ -1,74 +1,159 @@
|
|
1
1
|
#Services
|
2
|
-
Services are
|
3
|
-
|
2
|
+
Services are helper hubs that send and receive information typically from other services or directly from interrupts. They are meant
|
3
|
+
to act as a glue between controllers and devices. Services can receive events and can run periodic events on longer intervals. They are
|
4
|
+
very similar to controllers except they do not contain actions and are meant to be used as singletons (although they are instantized, the
|
5
|
+
instances are globally shared).
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
##Datatypes
|
8
|
+
Services maintain the following datatypes per instance:
|
9
|
+
* `instance_name_sessions` - A hash that contains the connection view controllers as keys and 'true' as the values.
|
10
|
+
* `instance_name_n_sessions` - A count of the current number of active sessions
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
##Code
|
13
|
+
All kernel service classes are placed in `./app/kern/services/` and are ruby files. Here is an example:
|
14
|
+
```ruby
|
15
|
+
#A sample service, all services have capital letters because they are like classes and are instantized
|
16
|
+
service :sample do
|
17
|
+
#Global space#######################################################################################################################
|
18
|
+
#In this space, you may define functions that are accessible to anything
|
19
|
+
global %{
|
20
|
+
function <%= @name %>_cache_save(x) {
|
21
|
+
};
|
22
|
+
}
|
23
|
+
####################################################################################################################################
|
13
24
|
|
14
|
-
|
15
|
-
|
16
|
-
|
25
|
+
#Initialization#####################################################################################################################
|
26
|
+
#When a service is woken_up, this function is called. A service instances is guaranteed to never be woken up
|
27
|
+
on_wakeup %{
|
28
|
+
}
|
17
29
|
|
18
|
-
|
19
|
-
|
20
|
-
|
30
|
+
#When an agent (currently all) service is no longer needed by a controller, AND the service has flushed all of it's transaction queues,
|
31
|
+
the service will receive a sleep request. At this point, you should remove all initialized data. If your service is
|
32
|
+
too expensive to destroy all initialized data each time it is woken and slept, then it is too expensive to wakeup at all
|
33
|
+
and you should reconsider your design. After this function calls, this service should act like it never existed and clear
|
34
|
+
all of it's initalized variables.
|
35
|
+
on_sleep %{
|
36
|
+
}
|
37
|
+
####################################################################################################################################
|
21
38
|
|
22
|
-
|
23
|
-
service
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
#
|
28
|
-
#You may use the function respond(info) within here to
|
29
|
-
|
30
|
-
#Store the in-progress requests as a list of hashes
|
31
|
-
#that contain an array in the order of [event_pointer, evenct_name]
|
32
|
-
var service_rest_tp_to_einfo = {}
|
33
|
-
|
34
|
-
function service_rest_callback(tp, success, info) {
|
35
|
-
//Lookup event info
|
36
|
-
var einfo = service_rest_tp_to_einfo[tp];
|
37
|
-
|
38
|
-
//Send info back to service
|
39
|
-
int_event(einfo[0], einfo[1], {:success => success, :info => info});
|
40
|
-
|
41
|
-
//Remove entries in telepointer table and rest service info
|
42
|
-
tel_del(tp);
|
43
|
-
delete service_rest_tp_to_einfo[tp];
|
44
|
-
}
|
39
|
+
#Session management#################################################################################################################
|
40
|
+
#Things 'connect' to a service, which is just a function call that objects, like controllers, make to a service instance
|
41
|
+
#that notify the service that that object is now connected. You may use this to start things like automatically sending
|
42
|
+
#events to controller instances. You have a session list called $NAME_sessions that is an array of currently connected clients.
|
43
|
+
on_connect %{
|
45
44
|
}
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
#When an object is destroyed, this notifies the service that that object no longer wishes to receive things from the service.
|
47
|
+
on_disconnect %{
|
48
|
+
}
|
49
|
+
####################################################################################################################################
|
50
50
|
|
51
|
-
|
52
|
-
|
51
|
+
#Do things##########################################################################################################################
|
52
|
+
#Services are a lot like controllers, they have a mechanism to handle events
|
53
|
+
on :event, %{
|
54
|
+
#Services maintain their own context variables through using <%= @name %> macros to prefix variables, each instance will have a different name
|
55
|
+
<%= @name %>_hello = "hi";
|
53
56
|
|
54
|
-
|
55
|
-
|
57
|
+
#Inside here you receive...
|
58
|
+
bp - The base pointer of the 'thing' that invoked this function.
|
59
|
+
params - The parameters that were 'sent' (i.e. called)
|
60
|
+
}
|
56
61
|
|
57
|
-
|
58
|
-
|
62
|
+
#Do something every 5 seconds if this service (a) has clients and (b) has nothing left in a transaction queue
|
63
|
+
every 5.seconds %{
|
59
64
|
}
|
65
|
+
####################################################################################################################################
|
60
66
|
end
|
61
67
|
```
|
62
68
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
+
###Variables accesible
|
70
|
+
For each service function, these are what you can access
|
71
|
+
* `on_wakeup`
|
72
|
+
* No variables yet
|
73
|
+
* `on_sleep`
|
74
|
+
* No variables left over
|
75
|
+
* `on_connect`
|
76
|
+
* `bp` - The base address of the controller that connected
|
77
|
+
* `sessions` - A hash of currently active sessions where each key is a base pointer
|
78
|
+
* `on_disconnect`
|
79
|
+
* `bp` - The base address of the controller that disconnected
|
80
|
+
* `sessions` - A hash of currently active sessions where each key is a base pointer
|
81
|
+
* `every x.seconds`
|
82
|
+
* `sessions` - A hash of currently active sessions where each key is a base pointer
|
83
|
+
* `on`
|
84
|
+
* `bp` - The base address of the controller that sent event
|
85
|
+
* `params` - The parameters sent with the message
|
86
|
+
* `sessions` - A hash of currently active sessions where each key is a base pointer
|
87
|
+
|
88
|
+
###Service function in controllers
|
89
|
+
When you are inside a controller, you may make as service request through `Request`. **You must have already declared usage of the service through
|
90
|
+
`services`**:
|
91
|
+
* `Request(service_insatnce_name, ename, params)`
|
92
|
+
* `service_instance_name` - The instance name of the service you are making a request from
|
93
|
+
* `ename` - The name of the event to 'send' the service. (`on` handlers for service)
|
94
|
+
* `params` - Any information you'd like to send along with the service.
|
95
|
+
|
96
|
+
###Example controller
|
97
|
+
```ruby
|
98
|
+
controller :controller do
|
99
|
+
spots "content"
|
100
|
+
services :my_service
|
101
|
+
|
102
|
+
action :index do
|
103
|
+
on_entry %{
|
104
|
+
//Request can be placed anywhere in the controller
|
105
|
+
Request("my_service", "hello", {});
|
106
|
+
}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
###Services when compiled
|
112
|
+
Services get compiled through the `services_compiler` which generates the following functions
|
113
|
+
```
|
114
|
+
$INAME_on_wakeup() {
|
115
|
+
}
|
116
|
+
|
117
|
+
$INAME_on_sleep() {
|
118
|
+
}
|
119
|
+
|
120
|
+
$INAME_on_connect(bp) {
|
121
|
+
}
|
122
|
+
|
123
|
+
$INAME_on_disconnect(bp) {
|
124
|
+
}
|
69
125
|
|
70
|
-
//
|
71
|
-
|
72
|
-
//on_request code
|
126
|
+
//For each 'on' function
|
127
|
+
$INAME_on_XXXXX(bp, params) = {
|
73
128
|
}
|
129
|
+
|
130
|
+
//Event handler
|
131
|
+
$INAME_event_handler(ep, event_name, info) {
|
132
|
+
}
|
133
|
+
```
|
134
|
+
|
135
|
+
###Services config for projects
|
136
|
+
Inside a project, `./config/services.rb` holds the services configuration. This configuration file tells flok exactly what services it should
|
137
|
+
instantize based on which class. The file contains a list of `service_instance` commands with the following format:
|
138
|
+
```ruby
|
139
|
+
service_instance :instance_name, :service_class
|
74
140
|
```
|
141
|
+
|
142
|
+
Additionally, you may pass in a hash at the end of `service_instance` that will be available as `@options` inside the service definition `rb` file.
|
143
|
+
|
144
|
+
###Spec service
|
145
|
+
By default, there is a spec service class available called 'test' when compiled with debug. This service contains a function named `$iname_function(x)` that
|
146
|
+
sets `$iname_function_args` to the input of that function.
|
147
|
+
|
148
|
+
###Roughly how the services system works
|
149
|
+
The services are all hard-coded function calls that are initialized with names like `my_instance_on_wakeup`. You have a service *class* defined in
|
150
|
+
either the kernel `./app/kern/services` or `./app/services` in a project. These files are then used as a template when you define a service in
|
151
|
+
`./config/services.rb` in your project. The flok library `ServicesCompiler` then takes the config and services file and generates the output
|
152
|
+
javascript code to support a service. Services are talked to through the simple function naming scheme above with the exception of timers which open
|
153
|
+
a new `evt` record every time in wakes up and stops the `evt` when it goes to sleep with a new base pointer. This means, a timer will not fire against
|
154
|
+
a service if the `evt` is no longer active. Regular `on` requests are not events because there would be way to much overhead.
|
155
|
+
|
156
|
+
The controller compiler, `UserCompiler`, mentioned in [Project](./project.md) provides the `services` method when defining a controller. This
|
157
|
+
`services` method is used in the `UserCompiler` to inject service functions directly into the controller's `ctable` definition. `_embed` and `Goto
|
158
|
+
macro` of the controllers then call `__init__` and `__dealloc__` of the `ctable` which is augmented with the necessary `services` like calling
|
159
|
+
`connect` and `disconnect`.
|
data/docs/services/vm.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
#Virtual Memory (vm.js)
|
2
|
+
Virtual memory provides something akin to operating system virtual memory systems with an emphasis on the paging infrastructure. Unlike an operating system, flok has the concept of a grand-unified namespaced address space that extends the concepts of caching and semantics across asynchronous and even networked systems. This vm systems is increadibly powerful because it allows you to create custom paging devices; this allows you to use one set of semantics to perform very complicated activities like pulling a news feed or list; having that news feed cached to disk automatically; etc.
|
3
|
+
|
4
|
+
Additionally, flok introduces a notification system that works with the demand paging schemes and caching schemes that allow you to grab data *now* and then be notified whenever a fresh copy is available from the server.
|
5
|
+
|
6
|
+
Each pager belongs to a *namespace*; page faults hit a namespace and then the pager takes over. The pager can choose to service a request; or even throw an exception if a certain semantic is not supported in it's namespace; for example, you may want to disable write semantics for a network pager you called `net` because you expect people to make ordinary network requests.
|
7
|
+
|
8
|
+
Fun aside; Because of the hashing schemantics; this paging system solves the age old problem of ... how do you show that data has changed *now* when to be assured that you have perferctly synchronized data with the server?;... you need to do a 3-way handshake with the updates. You could have a network server pager that supports writes but dosen't forward those to the network. That way, you can locally modify the page and then if the modifications were guessed correctly, the server would not even send back a page modification update! (Locally, the page would have been propogated as well). In the meantime, after modifying the local page, you would send a real network request to the server which would in turn update it's own paging system but at that point, the server would check in with you about your pages, but miraculously, because you gussed the updated page correctly, no modifications will need to be made. You could even purposefully put a 'not_synced' key in and actually show the user when the page was correctly synchronized.
|
9
|
+
|
10
|
+
##Pages
|
11
|
+
Each page is a dictionary containing a list of entries.
|
12
|
+
```ruby
|
13
|
+
page_example = {
|
14
|
+
_head: <<uuid STR>>,
|
15
|
+
_next: <<uuid STR>,
|
16
|
+
_id: <<uuid STR>,
|
17
|
+
entries: [
|
18
|
+
{_id: <<uuid STR>>, _timestmap: <<epoch_milliseconds STR>>},
|
19
|
+
...
|
20
|
+
],
|
21
|
+
_hash: <<CRC32 >
|
22
|
+
}
|
23
|
+
```
|
24
|
+
|
25
|
+
* `_head (optional)` - An optional pointer that indicates a *head* page. The head pages are special pages that contain 0 elements in the entries array, no `_head` key, and `_next` points to the *head* of the list. A head page might be used to pull down the latest news where the head will tell you whether or not there is anything left for you to receive.
|
26
|
+
* `_next (optional)` - The next element on this list. If `_next` is non-existant, then this page is the endpoint of the list.
|
27
|
+
* `_id` - The name of this page. Even if every key changed, the `_id` will not change. This is supposed to indicate, semantically, that this page still *means* the same thing. For example, imagine a page. If all entries were to be **removed** from this page and new entries were **inserted** on this page, then it would be semantically sound to say that the entries were **changed**.
|
28
|
+
* `entries` - An array of dictionaries. Each element contains a `_id` that is analogous to the page `_id`. (These are not the same, but carry the same semantics). Entries also have a `_timestamp` based on their creation or edit time from the unix epoch milliseconds.
|
29
|
+
* `_hash` - All entry `_id's`, `_next`, the page `_id`, and `head` are hashed togeather. Any changes to this page will cause this `_hash` to change which makes it a useful way to check if a page is modified and needs to be updated. The hash function is an ordered CRC32 function run in the following order. See [Calculating Page Hash](#calculating_page_hash).
|
30
|
+
|
31
|
+
------
|
32
|
+
|
33
|
+
## <a name='calculating_page_hash'></a>Calculating Page Hash
|
34
|
+
The `_hash` value of a page is calculated in the following way:
|
35
|
+
1. `z = crc32(0, _head)`
|
36
|
+
2. `z = crc32(z, _next)`
|
37
|
+
3. `z = crc32(z, _id)`
|
38
|
+
4. `z = crc32(z, entriesN._timestamp)` where N goes through all entries in order.
|
39
|
+
|
40
|
+
Assuming a crc function of `crc32(seed, string)`
|
41
|
+
|
42
|
+
------
|
43
|
+
|
44
|
+
##Configuration
|
45
|
+
The paging service may be configured in your `./config/services.rb`. You must set an array of pagers where each pager is responsible for a particular
|
46
|
+
namespace. See [VM Pagers](./vm/pagers.md) for more info.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
service_instance :vm, :vm, {
|
50
|
+
:pagers => [
|
51
|
+
{
|
52
|
+
:name => "spec0",
|
53
|
+
:namespace => "user",
|
54
|
+
:options => { //Passed to pager init function
|
55
|
+
}
|
56
|
+
}
|
57
|
+
]
|
58
|
+
}
|
59
|
+
```
|
60
|
+
Each pager can only be used once. In the future, using multiple copies of pagers would be a welcome addition. If you need to duplicate functionality of a pager,
|
61
|
+
you will want to copy your pager into a seperate piece of code and rename it so that it contains unique function names and variables, e.g. `my_pager0_read()` -> `my_pager1_read()`
|
62
|
+
|
63
|
+
* Pager options
|
64
|
+
* `name` - The name of the pager, this is used to create functions to each pager like `$NAME_read_sync`
|
65
|
+
* `namespace` - The namespace of the pager, this is used during requests to the pager, each pager is bound to a namespace
|
66
|
+
* `options` - A hash that is given to the pager's init function.
|
67
|
+
|
68
|
+
|
69
|
+
##Requests
|
70
|
+
|
71
|
+
###`watch`
|
72
|
+
This is how you asynchronously **read a page** and request notifications for any updates to a page. When you first watch a page, you will receive a local cached copy if it is available. For the first watch of a page, pagers will typically update that page so you will get another read as soon as it is available. For pages that are not locally cached, you will have to wait for a response.
|
73
|
+
|
74
|
+
**To re-iterate, flok has a different concept of what constitutes a read. Flok does not distinguish between a read and the want to know about changes to a page. Flok considers controllers that have just watched a page to have an invalid copy of that page, and thus need to be notified that the page has changed for first read**
|
75
|
+
* Parameters
|
76
|
+
* `ns` - The namespace of the page, e.g. 'user'
|
77
|
+
* `id` - Watching the page that contains this in the `_id` field
|
78
|
+
* Event Responses
|
79
|
+
* `read_res` - Whenever a change occurs to a page or the first read.
|
80
|
+
* `ns` - Namespace of the fault
|
81
|
+
* `first` - A boolean that indicates whether this page was ever received on `page_update` before. i.e. is it a change after we were already given this page previously in a `page_update` for this receiver?
|
82
|
+
* `page` - A dictionary object that is a reference to the page. This should be treated as immutable as it is a shared resource.
|
83
|
+
|
84
|
+
###`read_sync`
|
85
|
+
Request a page of memory synchronously. This will only trigger one `read_res`. If a page does not exist, that should be considered an error. You would normally use this with a blank pager that relies on the cache system to recover data that is either resident in RAM or load it from disk. For example, maybe you would like to display the user's name when they first login without waiting.
|
86
|
+
* Parameters
|
87
|
+
* `ns` - The namespace of the page, e.g. 'user'
|
88
|
+
* `id` - Watching the page that contains this in the `_id` field
|
89
|
+
* Event Responses
|
90
|
+
* `read_res` - Whenever a change occurs to a page or the first read.
|
91
|
+
* `ns` - Namespace of the fault
|
92
|
+
* `first` - A boolean that indicates whether this page was ever received on `page_update` before. i.e. is it a change after we were already given this page previously in a `page_update` for this receiver?
|
93
|
+
* `page` - A dictionary object that is a reference to the page. This should be treated as immutable as it is a shared resource.
|
94
|
+
* Debug quirks
|
95
|
+
* Sets `vm_read_sync_called` to true when called
|
96
|
+
|
97
|
+
###`create`
|
98
|
+
Creates a new page or overrides an existing one. Will automatically add timestamps to entries. If you need to modify an existing page, see [User page modification helpers](#user_page_modification_helpers)
|
99
|
+
* Parameters
|
100
|
+
* `ns` - The namespace of the page, e.g. 'user'
|
101
|
+
* `id` - Watching the page that contains this in the `_id` field
|
102
|
+
* `next` - The next pointer of the page
|
103
|
+
* `head` - The head pointer of the page
|
104
|
+
* `entries` - An array of dictionary entries for the array
|
105
|
+
|
106
|
+
##Helper Methods
|
107
|
+
###Pager specific
|
108
|
+
* `vm_cache_write(ns, key, page)` - Save a page to cache memory. This will not recalculate the page hash.
|
109
|
+
|
110
|
+
###Page modification
|
111
|
+
* `vm_rehash_page(page)` - Calculates the hash for a page and modifies that page with the new `_hash` field.
|
112
|
+
|
113
|
+
### <a name='user_page_modification_helpers'></a>User page modification helpers
|
114
|
+
You should never directly edit a page in user land; if you do; the pager has no way of knowing that you made modifications. Additionally, if you have multiple controllers watching a page, and it is modified in one controller, those other controllers
|
115
|
+
will not receive the notifications of the page modifications.
|
116
|
+
|
117
|
+
**These are only for existing pages; that is, pages that have been received through `read_res`. If you need to create a new page, do so through `create`**
|
118
|
+
####Per entry
|
119
|
+
* `entry_del(page, eindex)` - Remove a single entry from a page.
|
120
|
+
* `entry_insert(page, eindex, entry)` - Insert an entry, entry should be a dictionary value. It will automatically have the timestamp added.
|
121
|
+
* `entry_dma(page, eindex)` - Returns a mutable entry at a specific index. In addition, it updates the entries `_timestamp` of the entry.
|
122
|
+
|
123
|
+
####Page attributes
|
124
|
+
* `set_page_next(page, hash)` - Sets the `_next` hash for the page
|
125
|
+
* `set_page_head(page, hash)` - Sets the `_head` hash for the page
|
126
|
+
|
127
|
+
##Spec helpers
|
128
|
+
The variable `vm_did_wakeup` is set to true in the wakeup part of the vm service.
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#VM Pagers
|
2
|
+
Here is a list of default pagers for the vm system.
|
3
|
+
|
4
|
+
=======
|
5
|
+
|
6
|
+
##How to make your own pager
|
7
|
+
A new pager can be created by adding the pager to the `./app/kern/services` folder or `./app/services/pagers` if you are in a project.
|
8
|
+
|
9
|
+
**For all operations that are cacheable, you must write to vm_cache[ns][key]**
|
10
|
+
|
11
|
+
Each pager must implement the following functions:
|
12
|
+
* `init(options)` - Initialize a pager structure, passes options given in vm options hash for this pager in `./config/services.rb`
|
13
|
+
* `read(bp, key)`
|
14
|
+
* `read_sync(bp, key)`
|
15
|
+
* `write(key, page)`
|
16
|
+
|
17
|
+
##Caching
|
18
|
+
For pagers that wish to have their pages cached, they must set their `read` and `read_sync` to write to vm_cache.
|
19
|
+
```js
|
20
|
+
vm_cache_write(ns, key, spec0_data[key])
|
21
|
+
```
|
22
|
+
|
23
|
+
##Default pagers
|
24
|
+
###`mem` - Default memory pager
|
25
|
+
This pager dosen't do anything beyond allow you to set pages, write to them, and delete them.
|
26
|
+
* Supported operations
|
27
|
+
* `read`
|
28
|
+
* `read_sync`
|
29
|
+
* `write`
|
30
|
+
|
31
|
+
###`sockio` - Network pager
|
32
|
+
* Supported operations
|
33
|
+
* `read`
|
34
|
+
|
35
|
+
###Spec pagers
|
36
|
+
###`spec0`
|
37
|
+
This pager assists with specs in ./spec/kern/vm_service_spec.js
|
38
|
+
* Supported operations
|
39
|
+
* `init(options)` - Will set the `spec0_init_options` to be what ever options it got.
|
40
|
+
* `read` - Will set the `spec0_read_sync_called` to be true.
|
41
|
+
* `read_sync` - Will set the `spec0_read_sync_called` to be true.
|
42
|
+
###`spec1`
|
43
|
+
This pager is designed to test the read-sync-notify notification system. When this function is first called,
|
44
|
+
it will return 'a' for any value. The second call to read will return `b`.
|
45
|
+
* Supported operations
|
46
|
+
* `init(options)`
|
data/lib/flok/build.rb
CHANGED
@@ -62,24 +62,18 @@ module Flok
|
|
62
62
|
#3. All js files in `./app/kern/*.js` are globbed togeather and sent to `./products/$platform/glob/2kern.pre_macro.js`
|
63
63
|
Flok.src_glob("js", './app/kern', "#{build_path}/glob/2kern.pre_macro.js")
|
64
64
|
|
65
|
+
#4. All js files in `./app/kern/pagers/*.js` are appended to `./products/$PLATFORM/glob/3kern.pre_macro.js`
|
66
|
+
Flok.src_glob("js", './app/kern/pagers/', "#{build_path}/glob/3kern.pre_macro.js")
|
65
67
|
|
66
|
-
#
|
67
|
-
Flok.src_glob("rb", './app/kern/services/', "#{build_path}/glob/kern_services.rb")
|
68
|
-
|
69
|
-
#5. `./products/$PLATFORM/glob/kern_serivces.rb` is processed via `Flok::Services` and then exported as `./products/$PLATFORM/glob/kern_services.pre_macro.js`
|
70
|
-
File.write("#{build_path}/glob/kern_services.pre_macro.js", Flok::ServicesCompiler.compile(File.read("#{build_path}/glob/kern_services.rb")))
|
71
|
-
|
72
|
-
#6. All js files in `./products/$PLATFORM/glob/2kern.pre_macro.js` are run through `./app/kern/macro.rb's macro_process` and then sent to ./products/$PLATFORM/glob/2kern.js
|
68
|
+
#5. All js files in `./products/$PLATFORM/glob/{2,3}kern.pre_macro.js` are run through `./app/kern/macro.rb's macro_process` and then sent to ./products/$PLATFORM/glob/{2,3}kern.js
|
73
69
|
require './app/kern/macro.rb'
|
74
70
|
File.write("#{build_path}/glob/2kern.pre_macro.js", macro_process(File.read("#{build_path}/glob/2kern.pre_macro.js")))
|
71
|
+
File.write("#{build_path}/glob/3kern.pre_macro.js", macro_process(File.read("#{build_path}/glob/3kern.pre_macro.js")))
|
75
72
|
|
76
|
-
#
|
77
|
-
File.write("#{build_path}/glob/kern_services.pre_macro.js", macro_process(File.read("#{build_path}/glob/kern_services.pre_macro.js")))
|
78
|
-
|
79
|
-
#8. All js files are globbed from `./products/$platform/glob` and combined into `./products/$platform/glob/application.js.erb`
|
73
|
+
#6. All js files are globbed from `./products/$platform/glob` and combined into `./products/$platform/glob/application.js.erb`
|
80
74
|
Flok.src_glob("js", "#{build_path}/glob", "#{build_path}/glob/application.js.erb")
|
81
75
|
|
82
|
-
#
|
76
|
+
#7. Add custom commands
|
83
77
|
################################################################################################################
|
84
78
|
#MODS - List mods listed in config.yml
|
85
79
|
#---------------------------------------------------------------------------------------
|
@@ -88,7 +82,7 @@ module Flok
|
|
88
82
|
raise "No config.yml found in your 'platform: #{platform}' driver" unless driver_config
|
89
83
|
|
90
84
|
#Create array that looks like a javascript array with single quotes
|
91
|
-
mods = Flok::Platform.mods(
|
85
|
+
mods = Flok::Platform.mods(environment)
|
92
86
|
mods_js_arr = "[" + mods.map{|e| "'#{e}'"}.join(", ") + "]"
|
93
87
|
|
94
88
|
#Append this to our output file
|
@@ -97,7 +91,7 @@ module Flok
|
|
97
91
|
#---------------------------------------------------------------------------------------
|
98
92
|
################################################################################################################
|
99
93
|
|
100
|
-
#
|
94
|
+
#8. Append relavent mods code in kernel with macros
|
101
95
|
mods.each do |mod|
|
102
96
|
s = File.read("./app/kern/mod/#{mod}.js")
|
103
97
|
open("#{build_path}/glob/application.js.erb", "a") do |f|
|
@@ -105,7 +99,7 @@ module Flok
|
|
105
99
|
end
|
106
100
|
end
|
107
101
|
|
108
|
-
#
|
102
|
+
#9. The compiled `glob/application.js.erb` file is run through the ERB compiler and formed into `application.js`
|
109
103
|
erb_src = File.read "#{build_path}/glob/application.js.erb"
|
110
104
|
renderr = ERB.new(erb_src)
|
111
105
|
context = ApplicationJSERBContext.new()
|
@@ -122,7 +116,8 @@ module Flok
|
|
122
116
|
#Debug / Release
|
123
117
|
@debug = (ENV['FLOK_ENV'] == "DEBUG")
|
124
118
|
@release = (ENV['FLOK_ENV'] == "RELEASE")
|
125
|
-
@mods = Flok::Platform.mods(ENV['
|
119
|
+
@mods = Flok::Platform.mods(ENV['FLOK_ENV'])
|
120
|
+
@defines = Flok::Platform.defines(ENV['FLOK_ENV'])
|
126
121
|
end
|
127
122
|
end
|
128
123
|
end
|