flok 0.0.66 → 0.0.67

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a14b04d730ef3b9aacd8c74e5e4d4aaefe985fa0
4
- data.tar.gz: 9b938591a91b898de270c24a5cbea1b7f83ffd3a
3
+ metadata.gz: 33ebc378b4d4226cb152de93d0d3c6ff42936bad
4
+ data.tar.gz: eb5bce9429dd9499b956d88b2400315fcf565299
5
5
  SHA512:
6
- metadata.gz: aeaa0959cfa1e56fff2003ce9e0925c6c5384886a0f82da48269bc9e71b14b3684199b5c72e75bfb5793d2edf33860dd3484749307070b4287574ae413dafee9
7
- data.tar.gz: 229329809c8dc148b1a01223d8e3a340ada05bb4d169736aba82578c06614f6f1446c3900a2bf9101ea65410642357698ac89f7f71ac732cd6cfbeaff5881428
6
+ metadata.gz: f85617167569178963488188a1eb824e656aa0dec2fc6c6d1b719d21df16a71c651688c8f643155ead9c30a56d5c86b2e093df3a33abf40e3d3fb791da70d209
7
+ data.tar.gz: 5e36c86d1cc67d367d3d052a18966b545cfb0277b4db601a9dcfa6db9b5bdc3bfd735989647f0d0b0df68fe0bbacda590bae6b51348922261cad7b7a64861c33
@@ -16,5 +16,5 @@ function if_per_del_ns(ns) {
16
16
  function if_per_get(s, ns, key) {
17
17
  var _ns = store.namespace(ns);
18
18
  var res = _ns.get(key);
19
- int_dispatch([3, "int_per_get_res", s, ns, res]);
19
+ int_dispatch([3, "int_per_get_res", s, ns, key, res]);
20
20
  }
@@ -15,8 +15,6 @@ service :vm do
15
15
 
16
16
  vm_bp_to_nmap = {};
17
17
 
18
- vm_read_sync_in_progress = [];
19
-
20
18
  //Notification listeners, converts ns+key to an array of base pointers
21
19
  vm_notify_map = {
22
20
  <% @options[:pagers].each do |p| %>
@@ -24,6 +22,8 @@ service :vm do
24
22
  <% end %>
25
23
  };
26
24
 
25
+ vm_cache_write_sync_pending = {};
26
+
27
27
  //Cache
28
28
  function vm_cache_write(ns, page) {
29
29
  <% if @debug %>
@@ -49,13 +49,41 @@ service :vm do
49
49
  vm_dirty[ns][page._id] = page;
50
50
  vm_cache[ns][page._id] = page;
51
51
 
52
+ //List of controllers to notify synchronously
53
+ var sync_waiting_controllers = vm_cache_write_sync_pending[page._id];
54
+
55
+ if (sync_waiting_controllers !== undefined) {
56
+ //Map that holds all controllers synchronously sent (used to avoid sending
57
+ //those controllers that are also on vm_notify_map a second message)
58
+ var sync_sent_map = {};
59
+
60
+ for (var i = 0; i < sync_waiting_controllers.length; ++i) {
61
+ var c = sync_waiting_controllers[i];
62
+
63
+ //Save so we don't send the same controller during the async part if the controller
64
+ //also happends to be part of vm_notify_map (it watched)
65
+ sync_sent_map[c] = true;
66
+
67
+ //Notify controller synchronously
68
+ int_event(c, "read_res", page);
69
+ }
70
+ }
71
+
52
72
  //Try to lookup view controller(s) to notify
53
73
  var nbp = vm_notify_map[ns][page._id];
54
74
  if (nbp) {
55
75
  for (var i = 0; i < nbp.length; ++i) {
56
- int_event_defer(nbp[i], "read_res", page);
76
+ var cbp = nbp[i];
77
+ //Only send if we didn't just send it above in the previous
78
+ //block synchronously
79
+ if (sync_sent_map[cbp] === undefined) {
80
+ int_event_defer(cbp, "read_res", page);
81
+ }
57
82
  }
58
83
  }
84
+
85
+ //Clear the sync_waiting_controllers
86
+ delete vm_cache_write_sync_pending[page._id];
59
87
  }
60
88
 
61
89
  function vm_pageout() {
@@ -82,23 +110,27 @@ service :vm do
82
110
 
83
111
  //Part of the persist module
84
112
  //res is page
85
- function int_per_get_res(s, ns, res) {
86
- //Controller made a read_sync request, fulfull it
87
- if (vm_read_sync_in_progress.length > 0) {
88
- int_event(vm_read_sync_in_progress.pop(), "read_sync_res", {page: res, ns: ns});
89
- }
90
-
91
- //If the key didn't exist, ignore it
92
- if (res === null) { return; }
93
-
94
- //If there is already a cached entry, a pager beat us to it
95
- //ignore this for now because the pager should be more up to
96
- //date
97
- if (vm_cache[ns][res._id]) { return };
113
+ function int_per_get_res(s, ns, id, res) {
114
+ if (res !== null) {
115
+ //Write out to the cache
116
+ vm_transaction_begin();
117
+ vm_cache_write(ns, res);
118
+ vm_transaction_end();
119
+ } else {
120
+ //Result was blank, signal all controllers that read synchronously
121
+ var sync_waiting_controllers = vm_cache_write_sync_pending[id];
122
+ if (sync_waiting_controllers !== undefined) {
123
+ for (var i = 0; i < sync_waiting_controllers.length; ++i) {
124
+ var c = sync_waiting_controllers[i];
125
+
126
+ //Notify controller synchronously
127
+ int_event(c, "read_res", {});
128
+ }
129
+ }
98
130
 
99
- vm_transaction_begin();
100
- vm_cache_write(ns, res);
101
- vm_transaction_end();
131
+ //Remove all controllers from notification list
132
+ delete vm_cache_write_sync_pending[id];
133
+ }
102
134
  }
103
135
 
104
136
  <% if @debug %>
@@ -561,8 +593,18 @@ service :vm do
561
593
  }
562
594
 
563
595
  //Send a request now for disk read for sync
564
- if (!cache_entry && params.sync) {
565
- SEND("main", "if_per_get", "vm", params.ns, params.id);
596
+ if (!cache_entry) {
597
+ if (params.sync !== undefined && params.sync === true) {
598
+ //Add ourselves to synchronous read list so the next disk read will
599
+ //send a synchronous event to us (and then clear). We will not get the
600
+ //normal asynhronous read. Additionally, we may also get a `{}` page indicating
601
+ //that the page is blank
602
+ vm_cache_write_sync_pending[params.id] = vm_cache_write_sync_pending[params.id] || [];
603
+ vm_cache_write_sync_pending[params.id].push(bp);
604
+ SEND("main", "if_per_get", "vm", params.ns, params.id);
605
+ } else {
606
+ SEND("disk", "if_per_get", "vm", params.ns, params.id);
607
+ }
566
608
  }
567
609
 
568
610
  //Do not signal pager if there is a watch request already in place
@@ -570,14 +612,6 @@ service :vm do
570
612
  //watch to go through as we have no info on it but just added it
571
613
  if (vm_notify_map[params.ns][params.id].length > 1) { return; }
572
614
 
573
- //While we're waiting for the pager try loading from disk, if this
574
- //disk request is slower than the pager response, that's ok...
575
- //the disk response will double check to see if the cache got set
576
- //somewhere and not set it itself.
577
- if (!cache_entry && !params.sync) {
578
- SEND("disk", "if_per_get", "vm", params.ns, params.id);
579
- }
580
-
581
615
  //Now load the appropriate pager
582
616
  <% @options[:pagers].each do |p| %>
583
617
  if (params.ns === "<%= p[:namespace] %>") {
@@ -599,9 +633,11 @@ service :vm do
599
633
 
600
634
  var cache_entry = vm_cache[params.ns][params.id];
601
635
  if (cache_entry !== undefined) {
602
- int_event(bp, "read_sync_res", {ns: params.ns, page: cache_entry});
636
+ int_event(bp, "read_res", cache_entry);
603
637
  } else {
604
- vm_read_sync_in_progress.unshift(bp);
638
+ //Set this controller as awaiting as synchronous response
639
+ vm_cache_write_sync_pending[params.id] = vm_cache_write_sync_pending[params.id] || [];
640
+ vm_cache_write_sync_pending[params.id].push(bp);
605
641
  SEND("main", "if_per_get", "vm", params.ns, params.id);
606
642
  }
607
643
  }
@@ -15,6 +15,6 @@ It is expected that the kernel should manage the write-back cache and that the d
15
15
  it is convenient to do so.
16
16
 
17
17
  ###Kernel interrupts
18
- `int_per_get_res(s, ns, res)` - A response retrieved from `if_per_get` that contains the session key and result dictionary. Currently,
18
+ `int_per_get_res(s, ns, id, res)` - A response retrieved from `if_per_get` that contains the session key and result dictionary. Currently,
19
19
  the service `vm` owns this function; so session does not have an effect on the outcome; but the string `"vm"` should be used for now for any
20
20
  session keys involving persist.
@@ -97,39 +97,17 @@ you will want to copy your pager into a seperate piece of code and rename it so
97
97
  ##Requests
98
98
 
99
99
  ###`watch`
100
- This is how you **read a page** and request notifications for any updates to a page. The following happens when you watch a page:
101
- ```js
102
- if (page is resident in memory from previous cache write)
103
- send the caller a read_res event *now*
104
-
105
- increment_page_ref()
106
-
107
- //Synchronously request disk load from cache; this will block
108
- //Even if we have a request in progress; the synchronous
109
- //may pre-empt that event because the disk queue might be loaded;
110
- //so we need to send this anyway
111
- if (page is not redisent in memory and synchronous) {
112
- try_sync_load_from_disk_and_update_cache()
113
- }
114
-
115
- //Only notify if this is the first reference, other controllers who attempt a watch will not signal the pager because the pager already knows
116
- //about this page
117
- if first_reference {
118
- pager_watch()
119
- }
120
-
121
- //Again, only attempt this if the page is not requested by anyone else and is not synchronous (because we would have already tried). The pager will be notified in the meantime, if the disk
122
- //comes after the pager notification; then the disk will not do anything.
123
- if (page is not resident in memory && not_synchronous) {
124
- //This is an asynchronous request
125
- try_load_from_disk_and_update_cache()
126
- }
127
- ```
100
+ This is how you **read a page** and **request notifications for any updates to a page**.
128
101
  * Parameters
129
102
  * `ns` - The namespace of the page, e.g. 'user'
130
103
  * `id` - Watching the page that contains this in the `_id` field
131
- * `sync (optional)` - If set to `true` then the cache read will be performed synchronously; however, the disk read will still be performed
132
- asynchronously. Additionally, all future cache reads / updates will be performed synchronously.
104
+ * `sync (optional)` - If set to `true` then the cache read will be performed synchronously and if the cache misses, the disk will be read
105
+ synchronously. If the disk read fails, there will be no warning but this is an untested state and most likely, the next pager read will
106
+ dispatch asynchronously. This isn't awful but you should never set the `sync` flag to be true on data that you have not already cached at
107
+ some point. This is useful for profile loading, etc. so you don't have to delay on startup to display user name, etc. Multiple `watch`
108
+ requests dispatched with `sync` flag within the same frame will incur no performance penalty, they will be coalesced into one disk read.
109
+ Likewise, a `sync` watch request is perfectly acceptible to be called many times for a new controller needing the information. There is little
110
+ performance benefit in locally caching the data and many drawbacks like not getting updates of changes.
133
111
  * Event Responses
134
112
  * `read_res` - Whenever a change occurs to a page or the first read.
135
113
  * Returns an immutable page in params
@@ -151,16 +129,15 @@ use the modification helpers. These modification helpers implement copy on write
151
129
  * If in `@debug` mode, the variable `vm_write_list` contains an array dictionary of the last page passed to the pager (tail is latest).
152
130
 
153
131
  ###`read_sync`
154
- Read from the disk synchronously, or memory if it exists, and return the value in `read_sync_res`. This will not watch the page. Multiple read_syncs
132
+ Read from the disk synchronously, or memory if it exists, and return the value in `read_res`. This will not watch the page. Multiple read_syncs
155
133
  in the same frame are allowed but discouraged as the order that pages are received back may not necessarily be the order they were synhronously
156
134
  requested. This is because a cached page will be returned by the call stack while a synchronous read has to go through the event queue.
157
135
  * Parameters
158
136
  * `ns` - Namespace of the page
159
137
  * `id` - id of the page
160
138
  * Event Responses
161
- * `read_sync_res`
162
- * `ns` - The namespace of the page, e.g. 'user'
163
- * `page` - The page that was retrieved (or null if it dosen't exist)
139
+ * `read_res`
140
+ * `entire params` - The page that was retrieved (or null if it dosen't exist)
164
141
 
165
142
  ##Cache
166
143
  See below with `vm_cache_write` for how to write to the cache. Each pager can choose whether or not to cache; some pagers may cache only reads while others will cache writes. Failure to write to the cache at all will cause `watch` to never trigger. Some pagers may use a trick where writes are allowed, and go directly to the cache but nowhere else. This is to allow things like *pending* transactions where you can locally fake data until a server response is received which will both wipe the fake write and insert the new one. Cache writes will trigger `watch`; if you write to cache with `vm_cache_write` with a page that has the same `_hash` as a page that already exists in cache, no `watch` events will be triggered. Additionally, calling `vm_cache_write` with a non-modified page will result in no performance penalty. `vm_cache_write` notifies controllers asynchronously and is not effected by the `watch` flag on controllers.
@@ -176,12 +153,9 @@ Pageout is embodied in the function named `vm_pageout()`. This will asynchronous
176
153
  * `vm_notify_map` - The dictionary used to lookup what controllers need to be notified about changes. Stored in `vm_notify_map[ns][id]` which yields an array of controller base pointers.
177
154
  * `vm_bp_to_nmap` - A dictionary that maps a `bp` key (usually from a controller) to a dictionary. This dictionary contains a mapping of `bp => ns => id` to an array that contains `[node, index]` where `node` is a reference to `vm_notify_map[ns][id]`. This inverted map must (a) provide a way for `unwatch` to quickly remove entries from itself and (b) provide a way for all entries in `vm_notify_map` to be removed when something (usually a controller) disconrnects.
178
155
  must support `unwatch` removal which we only receive the `bp`, `ns`, and `key`.
179
- * `vm_read_sync_in_progress` - A queue of controller base pointers that are awaiting a response from `read_sync`. This may contain multiple
180
- controllers if one controller makes multiple `read_sync` requests within one *frame* as `int_event` only queues the outbounds events
181
- and dosen't immediately send them. Not that this makes it not synchronous, just the order of execution is not like a call stack and more
182
- like a synchronous high priority deferred queue. The *frontmost* of the array is the lowest index, and the *backmost* is the highest index. In
183
- javascript, this means that new requests are placed via `vm_read_sync_in_progress.unshift(new_bp)` and when requests are serviced, they are
184
- serviced via the `var bp = vm_read_sync_in_progress.pop()`.
156
+ * `vm_cache_write_sync_pending` - A hash mapping page_ids to controllers awaiting synchronous responeses, e.g.
157
+ `vm_cache_write_sync_pending[page_id][0..N] := bp`. Usually set via the `watch` request
158
+ during a sync call for disk reads or the synchronous `read_sync` request. The format for each element in the array is `{"page_id": [bp1, bp2], ...}`
185
159
 
186
160
  ##Helper Methods
187
161
 
@@ -1,3 +1,3 @@
1
1
  module Flok
2
- VERSION = "0.0.66"
2
+ VERSION = "0.0.67"
3
3
  end
@@ -19,7 +19,7 @@ RSpec.describe "iface:driver:persist" do
19
19
  @pipe.readline_timeout
20
20
 
21
21
  @pipe.puts [[0, 0, "ping"]].to_json;
22
- expect(@pipe).to readline_and_equal_json_x_within_y_seconds([0, "pong"], 5.seconds)
22
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds([0, "pong"], 8.seconds)
23
23
  end
24
24
 
25
25
  it "retuns null when calling get on a blank key" do
@@ -29,8 +29,8 @@ RSpec.describe "iface:driver:persist" do
29
29
  @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key]].to_json
30
30
 
31
31
  #Expect a response
32
- res = [3, "int_per_get_res", "session", "my_ns", nil]
33
- expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
32
+ res = [3, "int_per_get_res", "session", "my_ns", key, nil]
33
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 7.seconds)
34
34
  end
35
35
 
36
36
  it "Can set a persist, and then get" do
@@ -43,8 +43,8 @@ RSpec.describe "iface:driver:persist" do
43
43
  @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key]].to_json
44
44
 
45
45
  #Expect a response
46
- res = [3, "int_per_get_res", "session", "my_ns", value]
47
- expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
46
+ res = [3, "int_per_get_res", "session", "my_ns", key, value]
47
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 8.seconds)
48
48
  end
49
49
 
50
50
  it "Can set a persist, delete the key, and then get" do
@@ -58,8 +58,8 @@ RSpec.describe "iface:driver:persist" do
58
58
  @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key]].to_json
59
59
 
60
60
  #Expect a response
61
- res = [3, "int_per_get_res", "session", "my_ns", nil]
62
- expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
61
+ res = [3, "int_per_get_res", "session", "my_ns", key, nil]
62
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 8.seconds)
63
63
  end
64
64
 
65
65
  it "Can set two persists, delete one key, and then get" do
@@ -77,12 +77,12 @@ RSpec.describe "iface:driver:persist" do
77
77
  @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key2]].to_json
78
78
 
79
79
  #Results for first key
80
- res = [3, "int_per_get_res", "session", "my_ns", nil]
81
- expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
80
+ res = [3, "int_per_get_res", "session", "my_ns", key, nil]
81
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 8.seconds)
82
82
 
83
83
  #Expect a response
84
- res = [3, "int_per_get_res", "session", "my_ns", value2]
85
- expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
84
+ res = [3, "int_per_get_res", "session", "my_ns", key2, value2]
85
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 8.seconds)
86
86
  end
87
87
 
88
88
  it "Can set a persist, delete the key via ns, and then get" do
@@ -96,7 +96,7 @@ RSpec.describe "iface:driver:persist" do
96
96
  @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key]].to_json
97
97
 
98
98
  #Expect a response
99
- res = [3, "int_per_get_res", "session", "my_ns", nil]
100
- expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
99
+ res = [3, "int_per_get_res", "session", "my_ns", key, nil]
100
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 8.seconds)
101
101
  end
102
102
  end
@@ -22,7 +22,7 @@ controller :my_controller do
22
22
  Request("vm", "read_sync", info2);
23
23
  }
24
24
 
25
- on "read_sync_res", %{
25
+ on "read_res", %{
26
26
  read_sync_res_params.push(params);
27
27
  }
28
28
  end
@@ -21,7 +21,7 @@ controller :my_controller do
21
21
  Embed("my_other_controller", "content", {});
22
22
  }
23
23
 
24
- on "read_sync_res", %{
24
+ on "read_res", %{
25
25
  my_controller_read_sync_res = params;
26
26
  }
27
27
  end
@@ -44,7 +44,7 @@ controller :my_other_controller do
44
44
  Request("vm", "read_sync", info);
45
45
  }
46
46
 
47
- on "read_sync_res", %{
47
+ on "read_res", %{
48
48
  my_other_controller_read_sync_res = params;
49
49
  }
50
50
  end
@@ -17,7 +17,7 @@ controller :controller0 do
17
17
  Embed("controller2", "second", {});
18
18
  }
19
19
 
20
- on "read_sync_res", %{
20
+ on "read_res", %{
21
21
  controller0_read_sync_res = params;
22
22
  }
23
23
  end
@@ -40,10 +40,13 @@ controller :controller1 do
40
40
  }
41
41
  //get page A (again, read from cache)
42
42
  Request("vm", "read_sync", info);
43
+ throw "shit";
43
44
  }
44
45
 
45
- on "read_sync_res", %{
46
+ on modifyread_res", %{
46
47
  controller1_read_sync_res = params;
48
+
49
+ expect()
47
50
  }
48
51
  end
49
52
  end
@@ -68,7 +71,7 @@ controller :controller2 do
68
71
  Request("vm", "read_sync", info);
69
72
  }
70
73
 
71
- on "read_sync_res", %{
74
+ on "read_res", %{
72
75
  controller2_read_sync_res = params;
73
76
  }
74
77
  end
@@ -17,7 +17,7 @@ controller :controller0 do
17
17
  Embed("controller2", "second", {});
18
18
  }
19
19
 
20
- on "read_sync_res", %{
20
+ on "read_res", %{
21
21
  controller0_read_sync_res = params;
22
22
  }
23
23
  end
@@ -42,7 +42,7 @@ controller :controller1 do
42
42
  Request("vm", "read_sync", info);
43
43
  }
44
44
 
45
- on "read_sync_res", %{
45
+ on "read_res", %{
46
46
  controller1_read_sync_res = params;
47
47
  }
48
48
  end
@@ -68,7 +68,7 @@ controller :controller2 do
68
68
  Request("vm", "read_sync", info);
69
69
  }
70
70
 
71
- on "read_sync_res", %{
71
+ on "read_res", %{
72
72
  controller2_read_sync_res = params;
73
73
  }
74
74
  end
@@ -0,0 +1,23 @@
1
+ controller :my_controller do
2
+ services :vm
3
+
4
+ on_entry %{
5
+ read_sync_res_params = [];
6
+ }
7
+
8
+ action :my_action do
9
+ on_entry %{
10
+ var info = {
11
+ ns: "spec",
12
+ id: "test"
13
+ }
14
+
15
+ Request("vm", "read_sync", info);
16
+ }
17
+
18
+ on "read_res", %{
19
+ read_sync_res_params.push(params);
20
+ }
21
+ end
22
+ end
23
+
@@ -0,0 +1,21 @@
1
+ controller :my_controller do
2
+ spots "content"
3
+ services :vm
4
+
5
+ action :my_action do
6
+ on_entry %{
7
+ page0 = {
8
+ ns: "spec",
9
+ id: "my_key",
10
+ sync: true
11
+ };
12
+
13
+ Request("vm", "watch", page0);
14
+ }
15
+
16
+ on "read_res", %{
17
+ read_res_params = params;
18
+ }
19
+ end
20
+ end
21
+
@@ -671,8 +671,8 @@ RSpec.describe "kern:vm_service" do
671
671
  @driver.ignore_up_to "if_per_get", 0
672
672
  @driver.mexpect("if_per_get", ["vm", "spec", "test"], 0)
673
673
 
674
- @driver.int "int_per_get_res", ["vm", "spec", {
675
- "_id" => "default",
674
+ @driver.int "int_per_get_res", ["vm", "spec", "test", {
675
+ "_id" => "test",
676
676
  "_hash" => nil,
677
677
  "_next" => nil,
678
678
  "entries" => [],
@@ -680,24 +680,48 @@ RSpec.describe "kern:vm_service" do
680
680
 
681
681
  @driver.mexpect("if_per_get", ["vm", "spec", "test2"], 0)
682
682
 
683
- @driver.int "int_per_get_res", ["vm", "spec", {
684
- "_id" => "default",
683
+ @driver.int "int_per_get_res", ["vm", "spec", "test2", {
684
+ "_id" => "test2",
685
685
  "_hash" => nil,
686
686
  "_next" => nil,
687
687
  "entries" => [],
688
688
  }]
689
689
 
690
690
  dump = ctx.evald %{
691
- dump.vm_read_sync_in_progress = vm_read_sync_in_progress;
692
691
  dump.read_sync_res_params = read_sync_res_params;
693
692
  }
694
693
 
695
- expect(dump["vm_read_sync_in_progress"]).to eq([])
696
694
  expect(dump["read_sync_res_params"].length).to eq(2)
697
- expect(dump["read_sync_res_params"][0]["ns"]).to eq("spec")
698
- expect(dump["read_sync_res_params"][0]["page"]["_id"]).to eq("default")
699
- expect(dump["read_sync_res_params"][1]["ns"]).to eq("spec")
700
- expect(dump["read_sync_res_params"][1]["page"]["_id"]).to eq("default")
695
+ expect(dump["read_sync_res_params"][0]["_id"]).to eq("test")
696
+ expect(dump["read_sync_res_params"][1]["_id"]).to eq("test2")
697
+ end
698
+
699
+ it "Does send a read request from disk cache when synchronously reading a key for the first time via read_sync, and returns a blank hash if the page does not exist" do
700
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller19h.rb'), File.read("./spec/kern/assets/vm/config4.rb")
701
+
702
+ ctx.eval %{
703
+ base = _embed("my_controller", 1, {}, null);
704
+
705
+ //Call pageout *now*
706
+ vm_pageout();
707
+
708
+ //Drain queue
709
+ int_dispatch([]);
710
+ }
711
+
712
+ @driver.ignore_up_to "if_per_get", 0
713
+ @driver.mexpect("if_per_get", ["vm", "spec", "test"], 0)
714
+
715
+ #Send back blank result (Send two to make sure we only get one result back)
716
+ @driver.int "int_per_get_res", ["vm", "spec", "test", nil]
717
+ @driver.int "int_per_get_res", ["vm", "spec", "test", nil]
718
+
719
+ dump = ctx.evald %{
720
+ dump.read_sync_res_params = read_sync_res_params;
721
+ }
722
+
723
+ expect(dump["read_sync_res_params"].length).to eq(1)
724
+ expect(dump["read_sync_res_params"][0]).to eq({})
701
725
  end
702
726
 
703
727
  it "Calling read_sync on an entry that already exists in cache will not trigger a disk read" do
@@ -718,7 +742,7 @@ RSpec.describe "kern:vm_service" do
718
742
  @driver.mexpect("if_per_get", ["vm", "spec", "test"], 0)
719
743
 
720
744
  #Send the disk read response back controller19d:14
721
- @driver.int "int_per_get_res", ["vm", "spec", {
745
+ @driver.int "int_per_get_res", ["vm", "spec", "test", {
722
746
  "_id" => "test",
723
747
  "_hash" => nil,
724
748
  "_next" => nil,
@@ -754,7 +778,7 @@ RSpec.describe "kern:vm_service" do
754
778
  @driver.mexpect("if_per_get", ["vm", "spec", "test2"], 0)
755
779
 
756
780
  #Send the disk read response back for the first controller (my_controller)
757
- @driver.int "int_per_get_res", ["vm", "spec", {
781
+ @driver.int "int_per_get_res", ["vm", "spec", "test1", {
758
782
  "_id" => "test1",
759
783
  "_hash" => nil,
760
784
  "_next" => nil,
@@ -762,7 +786,7 @@ RSpec.describe "kern:vm_service" do
762
786
  }]
763
787
 
764
788
  #Send the disk read response back for the second controller (my_other_controller)
765
- @driver.int "int_per_get_res", ["vm", "spec", {
789
+ @driver.int "int_per_get_res", ["vm", "spec", "test2", {
766
790
  "_id" => "test2",
767
791
  "_hash" => nil,
768
792
  "_next" => nil,
@@ -775,8 +799,8 @@ RSpec.describe "kern:vm_service" do
775
799
  dump.my_other_controller_read_sync_res = my_other_controller_read_sync_res;
776
800
  }
777
801
 
778
- expect(dump["my_controller_read_sync_res"]["page"]["_id"]).to eq("test1")
779
- expect(dump["my_other_controller_read_sync_res"]["page"]["_id"]).to eq("test2")
802
+ expect(dump["my_controller_read_sync_res"]["_id"]).to eq("test1")
803
+ expect(dump["my_other_controller_read_sync_res"]["_id"]).to eq("test2")
780
804
  end
781
805
 
782
806
  it "Calling read_sync on frame0 for page 'A' on controller0 and then on frame1 for page 'A' on controller1 and page 'B' on controller2 will result in all controllers receiving the correct pages" do
@@ -796,7 +820,7 @@ RSpec.describe "kern:vm_service" do
796
820
  @driver.mexpect("if_per_get", ["vm", "spec", "A"], 0)
797
821
 
798
822
  #Send the disk read response back for controller0 pageA
799
- @driver.int "int_per_get_res", ["vm", "spec", {
823
+ @driver.int "int_per_get_res", ["vm", "spec", "A", {
800
824
  "_id" => "A",
801
825
  "_hash" => nil,
802
826
  "_next" => nil,
@@ -812,7 +836,7 @@ RSpec.describe "kern:vm_service" do
812
836
  @driver.mexpect("if_per_get", ["vm", "spec", "B"], 0)
813
837
 
814
838
  #Send the disk read response back for frame1 'B' for controller2
815
- @driver.int "int_per_get_res", ["vm", "spec", {
839
+ @driver.int "int_per_get_res", ["vm", "spec", "B", {
816
840
  "_id" => "B",
817
841
  "_hash" => nil,
818
842
  "_next" => nil,
@@ -825,8 +849,8 @@ RSpec.describe "kern:vm_service" do
825
849
  dump.controller2_read_sync_res = controller2_read_sync_res;
826
850
  }
827
851
 
828
- expect(dump["controller1_read_sync_res"]["page"]["_id"]).to eq("A")
829
- expect(dump["controller2_read_sync_res"]["page"]["_id"]).to eq("B")
852
+ expect(dump["controller1_read_sync_res"]["_id"]).to eq("A")
853
+ expect(dump["controller2_read_sync_res"]["_id"]).to eq("B")
830
854
  end
831
855
 
832
856
  it "Calling read_sync on frame0 for page 'B' on controller0 and then on frame1 for page 'A' on controller1 and page 'B' on controller2 will result in all controllers receiving the correct pages (reversed order from above)" do
@@ -846,7 +870,7 @@ RSpec.describe "kern:vm_service" do
846
870
  @driver.mexpect("if_per_get", ["vm", "spec", "B"], 0)
847
871
 
848
872
  #Send the disk read response back for controller0 pageB
849
- @driver.int "int_per_get_res", ["vm", "spec", {
873
+ @driver.int "int_per_get_res", ["vm", "spec", "B", {
850
874
  "_id" => "B",
851
875
  "_hash" => nil,
852
876
  "_next" => nil,
@@ -862,7 +886,7 @@ RSpec.describe "kern:vm_service" do
862
886
  @driver.mexpect("if_per_get", ["vm", "spec", "A"], 0)
863
887
 
864
888
  #Send the disk read response back for frame1 'A' for controller2
865
- @driver.int "int_per_get_res", ["vm", "spec", {
889
+ @driver.int "int_per_get_res", ["vm", "spec", "A", {
866
890
  "_id" => "A",
867
891
  "_hash" => nil,
868
892
  "_next" => nil,
@@ -875,8 +899,8 @@ RSpec.describe "kern:vm_service" do
875
899
  dump.controller2_read_sync_res = controller2_read_sync_res;
876
900
  }
877
901
 
878
- expect(dump["controller1_read_sync_res"]["page"]["_id"]).to eq("A")
879
- expect(dump["controller2_read_sync_res"]["page"]["_id"]).to eq("B")
902
+ expect(dump["controller1_read_sync_res"]["_id"]).to eq("A")
903
+ expect(dump["controller2_read_sync_res"]["_id"]).to eq("B")
880
904
  end
881
905
 
882
906
  it "Does send a sync read request from disk cache when watching a key for the first time with sync: true" do
@@ -916,45 +940,22 @@ RSpec.describe "kern:vm_service" do
916
940
  }.to raise_exception
917
941
  end
918
942
 
919
- it "Only sends one disk read request when multiple watches are attempted, and the first watch is sync: true" do
920
- ctx = flok_new_user File.read('./spec/kern/assets/vm/controller8.rb'), File.read("./spec/kern/assets/vm/config4.rb")
921
-
922
- ctx.eval %{
923
- base = _embed("my_controller_sync", 1, {}, null);
924
- base2 = _embed("my_controller", base+2, {}, null);
925
-
926
- //Drain queue
927
- int_dispatch([]);
928
- }
929
-
930
- @driver.ignore_up_to "if_per_get", 0
931
- @driver.get "if_per_get", 0
932
-
933
- #There should not be another request for the drive
934
- expect {
935
- @driver.ignore_up_to "if_per_get"
936
- }.to raise_exception
937
- end
938
-
939
- it "Sends two disk read request when multiple watches are attempted, and the second watch is sync: true but the disk does not read back before it is requested" do
940
- ctx = flok_new_user File.read('./spec/kern/assets/vm/controller8.rb'), File.read("./spec/kern/assets/vm/config4.rb")
943
+ it "A watch request with the sync flag enabled does trigger a synchronous read for a non-existant page" do
944
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller8ws.rb'), File.read("./spec/kern/assets/vm/config4.rb")
941
945
 
942
946
  ctx.eval %{
943
947
  base = _embed("my_controller", 1, {}, null);
944
- base2 = _embed("my_controller_sync", base+2, {}, null);
945
948
 
946
949
  //Drain queue
947
950
  int_dispatch([]);
948
951
  }
949
952
 
950
- #The inner controller's on_entry is called before, so it's in reverse order
951
953
  @driver.ignore_up_to "if_per_get", 0
952
- @driver.get "if_per_get", 0
953
- @driver.ignore_up_to "if_per_get", 2
954
+ @driver.mexpect("if_per_get", ["vm", "spec", "my_key"], 0)
954
955
  end
955
956
 
956
- it "Sends one disk read request when multiple watches are attempted, and the second watch is sync: true and the disk *does* read back before it is requested" do
957
- ctx = flok_new_user File.read('./spec/kern/assets/vm/controller8.rb'), File.read("./spec/kern/assets/vm/config4.rb");
957
+ it "A watch request with the sync flag enabled does return null to read_res if the page does not exist (really an illegal condition, page should always be avaliable if you're doing a watch with sync)" do
958
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller8ws.rb'), File.read("./spec/kern/assets/vm/config4.rb")
958
959
 
959
960
  ctx.eval %{
960
961
  base = _embed("my_controller", 1, {}, null);
@@ -963,50 +964,36 @@ RSpec.describe "kern:vm_service" do
963
964
  int_dispatch([]);
964
965
  }
965
966
 
966
- page0 = JSON.parse(ctx.eval("JSON.stringify(page0)"))
967
- @driver.int "int_per_get_res", ["vm", "spec", page0]
968
-
969
- ctx.eval %{
970
- base2 = _embed("my_controller_sync", base+2, {}, null);
971
- }
967
+ @driver.ignore_up_to "if_per_get", 0
968
+ @driver.mexpect("if_per_get", ["vm", "spec", "my_key"], 0)
972
969
 
973
- #The inner controller's on_entry is called before, so it's in reverse order
974
- @driver.ignore_up_to "if_per_get", 2
975
- @driver.get "if_per_get", 2
970
+ #Send back a blank page
971
+ @driver.int "int_per_get_res", ["vm", "spec", "my_key", nil]
976
972
 
977
- #There should not be another request for the drive
978
- expect {
979
- @driver.ignore_up_to "if_per_get"
980
- }.to raise_exception
973
+ read_res_params = ctx.dump "read_res_params"
974
+ expect(read_res_params).to eq({})
981
975
  end
982
976
 
983
- it "Only sends one disk read request when multiple sync watches are attempted" do
984
- ctx = flok_new_user File.read('./spec/kern/assets/vm/controller8.rb'), File.read("./spec/kern/assets/vm/config4.rb")
977
+ it "A watch request with the sync flag enabled does not send two read_res back after int_dispatch" do
978
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller8ws.rb'), File.read("./spec/kern/assets/vm/config4.rb")
985
979
 
986
980
  ctx.eval %{
987
- base = _embed("my_controller_sync", 1, {}, null);
981
+ base = _embed("my_controller", 1, {}, null);
988
982
 
989
983
  //Drain queue
990
984
  int_dispatch([]);
991
985
  }
992
986
 
993
987
  @driver.ignore_up_to "if_per_get", 0
994
- @driver.get "if_per_get", 0
988
+ @driver.mexpect("if_per_get", ["vm", "spec", "my_key"], 0)
995
989
 
996
- page = JSON.parse(ctx.eval("JSON.stringify(page)"))
997
- @driver.int "int_per_get_res", ["vm", "spec", page]
990
+ #Send back a blank page
991
+ @driver.int "int_per_get_res", ["vm", "spec", "my_key", nil]
998
992
 
999
- ctx.eval %{
1000
- base2 = _embed("my_controller_sync", base+2, {}, null);
1001
- }
1002
-
1003
- #There should not be another request for the drive
1004
- expect {
1005
- @driver.ignore_up_to "if_per_get"
1006
- }.to raise_exception
993
+ read_res_params = ctx.dump "read_res_params"
994
+ expect(read_res_params).to eq({})
1007
995
  end
1008
996
 
1009
-
1010
997
  it "Clears the dirty page when pageout runs" do
1011
998
  ctx = flok_new_user File.read('./spec/kern/assets/vm/controller18.rb'), File.read("./spec/kern/assets/vm/config4.rb")
1012
999
 
@@ -1134,7 +1121,7 @@ RSpec.describe "kern:vm_service" do
1134
1121
 
1135
1122
  #And then we let the cache from disk reply, which should be ignored
1136
1123
  #because the cache is already there from the pager
1137
- @driver.int "int_per_get_res", ["vm", "spec", page]
1124
+ @driver.int "int_per_get_res", ["vm", "spec", page["_id"], page]
1138
1125
 
1139
1126
  res = JSON.parse(ctx.eval("JSON.stringify(read_res)"))
1140
1127
  expect(res).to eq([
@@ -1195,7 +1182,7 @@ RSpec.describe "kern:vm_service" do
1195
1182
 
1196
1183
  #And then we let the cache from disk reply, which should be ignored
1197
1184
  #because the cache is already there from the pager
1198
- @driver.int "int_per_get_res", ["vm", "spec", page]
1185
+ @driver.int "int_per_get_res", ["vm", "spec", page["_id"], page]
1199
1186
 
1200
1187
  res = JSON.parse(ctx.eval("JSON.stringify(read_res)"))
1201
1188
  expect(res).to eq([
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flok
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.66
4
+ version: 0.0.67
5
5
  platform: ruby
6
6
  authors:
7
7
  - seo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-18 00:00:00.000000000 Z
11
+ date: 2015-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: execjs
@@ -1213,6 +1213,7 @@ files:
1213
1213
  - spec/kern/assets/vm/controller19e.rb
1214
1214
  - spec/kern/assets/vm/controller19f.rb
1215
1215
  - spec/kern/assets/vm/controller19g.rb
1216
+ - spec/kern/assets/vm/controller19h.rb
1216
1217
  - spec/kern/assets/vm/controller2.rb
1217
1218
  - spec/kern/assets/vm/controller20.rb
1218
1219
  - spec/kern/assets/vm/controller21.rb
@@ -1224,6 +1225,7 @@ files:
1224
1225
  - spec/kern/assets/vm/controller7.rb
1225
1226
  - spec/kern/assets/vm/controller8.rb
1226
1227
  - spec/kern/assets/vm/controller8b.rb
1228
+ - spec/kern/assets/vm/controller8ws.rb
1227
1229
  - spec/kern/assets/vm/controller9.rb
1228
1230
  - spec/kern/assets/vm/controller_exc_2watch.rb
1229
1231
  - spec/kern/assets/vm/controller_exc_ewatch.rb
@@ -2147,6 +2149,7 @@ test_files:
2147
2149
  - spec/kern/assets/vm/controller19e.rb
2148
2150
  - spec/kern/assets/vm/controller19f.rb
2149
2151
  - spec/kern/assets/vm/controller19g.rb
2152
+ - spec/kern/assets/vm/controller19h.rb
2150
2153
  - spec/kern/assets/vm/controller2.rb
2151
2154
  - spec/kern/assets/vm/controller20.rb
2152
2155
  - spec/kern/assets/vm/controller21.rb
@@ -2158,6 +2161,7 @@ test_files:
2158
2161
  - spec/kern/assets/vm/controller7.rb
2159
2162
  - spec/kern/assets/vm/controller8.rb
2160
2163
  - spec/kern/assets/vm/controller8b.rb
2164
+ - spec/kern/assets/vm/controller8ws.rb
2161
2165
  - spec/kern/assets/vm/controller9.rb
2162
2166
  - spec/kern/assets/vm/controller_exc_2watch.rb
2163
2167
  - spec/kern/assets/vm/controller_exc_ewatch.rb