flok 0.0.36 → 0.0.38

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -0
  3. data/app/drivers/chrome/build_context.rb +1 -1
  4. data/app/drivers/chrome/config.yml +10 -0
  5. data/app/drivers/chrome/pipe.rb +24 -1
  6. data/app/drivers/chrome/src/persist.js +29 -0
  7. data/app/drivers/chrome/src/sockio.js +3 -1
  8. data/app/drivers/chrome/src/vendor/store2.js +3 -0
  9. data/app/kern/callout.js +55 -0
  10. data/app/kern/controller.js +3 -0
  11. data/app/kern/crc32.js +22 -0
  12. data/app/kern/dispatch.js +16 -0
  13. data/app/kern/mod/event.js +3 -0
  14. data/app/kern/mod/persist.js +1 -0
  15. data/app/kern/mod/timer.js +5 -0
  16. data/app/kern/pagers/mem_pager.js +2 -0
  17. data/app/kern/pagers/sockio_pager.js +66 -0
  18. data/app/kern/pagers/spec0.js +35 -0
  19. data/app/kern/pagers/spec1.js +24 -0
  20. data/app/kern/pagers/spec2.js +31 -0
  21. data/app/kern/services/test.rb +7 -0
  22. data/app/kern/services/vm.rb +141 -0
  23. data/app/kern/spec_helper.js +5 -0
  24. data/bin/flok +27 -5
  25. data/docs/callout.md +8 -0
  26. data/docs/client_api.md +1 -1
  27. data/docs/compilation.md +14 -8
  28. data/docs/controllers.md +2 -1
  29. data/docs/datatypes.md +3 -1
  30. data/docs/environmentals.md +6 -0
  31. data/docs/interactive.md +6 -1
  32. data/docs/kernel_api.md +3 -0
  33. data/docs/mod/event.md +5 -1
  34. data/docs/mod/persist.md +14 -31
  35. data/docs/mod/timer.md +4 -2
  36. data/docs/project.md +16 -5
  37. data/docs/scheduling.md +1 -0
  38. data/docs/services.md +141 -56
  39. data/docs/services/vm.md +128 -0
  40. data/docs/services/vm/pagers.md +46 -0
  41. data/lib/flok/build.rb +11 -16
  42. data/lib/flok/platform.rb +29 -6
  43. data/lib/flok/project_template/app/scripts/script.js +3 -0
  44. data/lib/flok/project_template/app/services/service.rb +1 -0
  45. data/lib/flok/project_template/config/config.yml +1 -0
  46. data/lib/flok/project_template/config/platforms/chrome/config.yml +1 -0
  47. data/lib/flok/project_template/config/services.rb +1 -0
  48. data/lib/flok/service_compiler_templates/services.js.erb +78 -9
  49. data/lib/flok/services_compiler.rb +117 -20
  50. data/lib/flok/user_compiler.rb +14 -6
  51. data/lib/flok/user_compiler_templates/ctable.js.erb +10 -0
  52. data/lib/flok/version.rb +1 -1
  53. data/spec/env/etc.rb +1 -1
  54. data/spec/env/global.rb +2 -0
  55. data/spec/env/iface.rb +20 -4
  56. data/spec/env/kern.rb +8 -3
  57. data/spec/etc/cli_spec.rb +319 -165
  58. data/spec/etc/lib/assets/config.yml +3 -0
  59. data/spec/etc/lib/platform_spec.rb +14 -10
  60. data/spec/etc/lib/project_spec.rb +22 -0
  61. data/spec/etc/service_compiler/config0.rb +1 -0
  62. data/spec/etc/service_compiler/config1.rb +1 -0
  63. data/spec/etc/service_compiler/config2.rb +3 -0
  64. data/spec/etc/service_compiler/service0.rb +22 -6
  65. data/spec/etc/service_compiler/service1.rb +26 -0
  66. data/spec/etc/service_compiler/service_bad_type.rb +20 -0
  67. data/spec/etc/services_compiler_spec.rb +35 -16
  68. data/spec/etc/user_compiler/data.js +2 -0
  69. data/spec/etc/user_compiler_spec.rb +7 -1
  70. data/spec/iface/driver/persist_spec.rb +106 -0
  71. data/spec/iface/driver/pipe_spec.rb +5 -0
  72. data/spec/iface/kern/ping_spec.rb +4 -3
  73. data/spec/kern/assets/blank.rb +0 -0
  74. data/spec/kern/assets/service0.rb +24 -0
  75. data/spec/kern/assets/service1.rb +22 -0
  76. data/spec/kern/assets/service2.rb +27 -0
  77. data/spec/kern/assets/service_config0.rb +2 -0
  78. data/spec/kern/assets/service_config1.rb +2 -0
  79. data/spec/kern/assets/service_controller0.rb +13 -0
  80. data/spec/kern/assets/service_controller1.rb +32 -0
  81. data/spec/kern/assets/service_controller2.rb +38 -0
  82. data/spec/kern/assets/service_controller3.rb +38 -0
  83. data/spec/kern/assets/vm/config0.rb +2 -0
  84. data/spec/kern/assets/vm/config1.rb +12 -0
  85. data/spec/kern/assets/vm/config2.rb +12 -0
  86. data/spec/kern/assets/vm/config3.rb +12 -0
  87. data/spec/kern/assets/vm/controller0.rb +8 -0
  88. data/spec/kern/assets/vm/controller1.rb +18 -0
  89. data/spec/kern/assets/vm/controller2.rb +18 -0
  90. data/spec/kern/assets/vm/controller3.rb +20 -0
  91. data/spec/kern/assets/vm/controller4.rb +22 -0
  92. data/spec/kern/assets/vm/controller5.rb +22 -0
  93. data/spec/kern/assets/vm/controller6.rb +21 -0
  94. data/spec/kern/assets/vm/service0.rb +24 -0
  95. data/spec/kern/assets/vm/service_controller0.rb +7 -0
  96. data/spec/kern/callout_spec.rb +153 -0
  97. data/spec/kern/functions_spec.rb +29 -0
  98. data/spec/kern/service_controller_spec.rb +213 -0
  99. data/spec/kern/vm_service_spec.rb +195 -0
  100. metadata +98 -12
  101. data/app/kern/services/rest.rb +0 -310
  102. data/app/kern/services/timer.rb +0 -30
  103. data/docs/services/timer.md +0 -21
  104. data/spec/kern/assets/rest_service.rb +0 -20
  105. data/spec/kern/assets/timer_service.rb +0 -19
  106. 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 entirely built into the Flok kernel. If you need custom actions for your services, they must be created as a driver and then
3
- you must adhere to the services API.
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
- ###Request
6
- You initiate a service request via `Request`. This may be called only in the controller at this time. This macro takes several parameters
7
- parameters, all of which must either be strict variable names or double quoted strings:
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
- * `Request(name, info, event_name)`
10
- * `name` - The name of the service you are making a request from
11
- * `info` - The information to give the service
12
- * `event_name` - The name of the event when a callback occurs
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
- Callbacks are handled by redirecting them through the [event](./mod/event.md) interface `int_event`. You should register with `reg_evt` to receive
15
- events back from a service. The request itself is not made via the event system, only the response is. This may seem a little odd because normally
16
- events come in from the outside while this is an internally generated event.
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
- ###Request API
19
- Registering a service involves adding files to the `./app/kern/services` folder. All *ruby* files in this folder are used in the compilation of
20
- services. You declare services in the following format. Your service should not depend on anything except particular module functions.
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("rest") do
24
- on_init %{
25
- #Code inserted here is put into the global space, add initialization
26
- #procedures, functions that need to be called, etc.
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
- on_request %{
48
- #Code that handles a payload goes here.
49
- #You have access to `info`, `ep`, and `ename` which was given in the Request macro
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
- //Create a GET request that will respond to the telepointer
52
- var tp = tel_reg(service_rest_callback);
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
- //Now register the event information to respond to when a callback is received
55
- service_rest_tp_to_einfo[tp] = [ep, ename]
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
- //Start the request
58
- SEND("net", "if_net_req", "GET", info.url, info.params, tp)
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
- This is then compiled down to
64
- ```js
65
- //***************************************
66
- //on_init code is appended to the outside
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
- //Your request code is put inside a function
71
- function service_rest_req(info, ep, ename) {
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`.
@@ -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
- #4. All rb files inside `./app/kern/services/` are globbed into `./products/$PLATFORM/glob/kern_services.rb`
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
- #7. All js files in `./products/$PLATFORM/glob/kern_services.pre_macro.js` are run through `./app/kern/macro.rb's macro_process` and then sent to ./products/$PLATFORM/glob/kern_services.pre_macro.js
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
- #9. Add custom commands
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(platform, environment)
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
- #10. Append relavent mods code in kernel with macros
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
- #11. The compiled `glob/application.js.erb` file is run through the ERB compiler and formed into `application.js`
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['PLATFORM'], ENV['FLOK_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