1 'use strict';
  2 
  3 /**
  4  *
  5  *  Waits for the timeout (in ms) for the given servers to be online
  6  *  and in one of the provided states.
  7  *
  8  *  Returns true if MAGIC_WEATHER is online, FTM_CONTROL is in Idle
  9  *  and LID_CONTROL is either in Open or Closed.
 10  *
 11  *  Returns false if all given servers are online, but at least one is
 12  *  not in the expected state.
 13  *
 14  *  Throws an exception if not all provided servers are online after
 15  *  the given timeout.
 16  *
 17  *  If you want to wait infinitely: CheckStates(table, null)
 18  *  If the timeout is negative (e.g. -500 means 500ms) or zero,
 19  *     no exception is thrown but false is returned.
 20  *
 21  * @param table
 22  *
 23  * @param {Integer} [timeout=5000]
 24  *    timeout in milliseconds
 25  *
 26  * @returns
 27  *
 28  * @throws
 29  *
 30  * @example
 31  *    var table =
 32  *    [
 33  *        [ "MAGIC_WEATHER"  ],
 34  *        [ "FTM_CONTROL",  [ "Idle" ] ],
 35  *        [ "LID_CONTROL",  [ "Open", "Closed" ] ],
 36  *    ];
 37  *
 38  *    checkStates(table);
 39  *
 40  *
 41  */
 42 function checkStates(table, timeout, wait)
 43 {
 44     if (timeout===undefined)
 45         timeout = 5000;
 46 
 47     var states = [];
 48 
 49     var time = new Date();
 50     while (1)
 51     {
 52         // Get states of all servers in question
 53         states = [];
 54         for (var i=0; i<table.length; i++)
 55         {
 56             var state = dim.state(table[i][0]);
 57             states[i] = state ? state.name : undefined;
 58         }
 59 
 60         // Check if they are all valid
 61         if (states.indexOf(undefined)<0)
 62         {
 63             // If they are all valid, check them against the
 64             // state lists provided for each server
 65             var rc = true;
 66             for (var i=0; i<table.length; i++)
 67             {
 68                 if (!table[i][1] || table[i][1].indexOf(states[i])>=0)
 69                     continue;
 70 
 71                 if (!wait)
 72                     dim.log(table[i][0]+" in ["+states[i]+"] not as it ought to be ["+table[i][1]+"]");
 73 
 74                 rc = false;
 75             }
 76             if (rc)
 77                 return rc;
 78 
 79             if (!wait)
 80                 return false;
 81         }
 82 
 83         if ((new Date())-time>=Math.abs(timeout))
 84             break;
 85 
 86         v8.sleep();
 87     }
 88 
 89     if (timeout<0)
 90         return false;
 91 
 92     // Create a list of all servers which do not have valid states yet
 93     var servers = [];
 94     for (var i=0; i<table.length; i++)
 95         if (!states[i])
 96             servers.push(table[i][0]);
 97 
 98     // If all servers do not yet have valid states, it is obsolete to
 99     // print all their names
100     if (servers.length==table.length && servers.length>1)
101         servers = [ "servers." ];
102 
103     throw new Error("Timeout waiting for access to named states of "+servers.join(", "));
104 }
105 
106 function checkSend(servers, timeout)
107 {
108     if (timeout===undefined)
109         timeout = 5000;
110 
111     var states = [];
112 
113     var time = new Date();
114     while (1)
115     {
116         // Get states of all servers in question
117         states = [];
118         for (var i=0; i<servers.length; i++)
119             states[i] = dim.send(servers[i]);
120 
121         // Check if they are all valid
122         if (states.indexOf(false)<0)
123             return true;
124 
125         if ((new Date())-time>=Math.abs(timeout))
126             break;
127 
128         v8.sleep();
129     }
130 
131     if (timeout<0)
132         return false;
133 
134     // Create a list of all servers which do not have valid states yet
135     var missing = [];
136     for (var i=0; i<servers.length; i++)
137         if (!states[i])
138             missing.push(servers[i]);
139 
140     throw new Error("Timeout waiting for send-ready of "+missing.join(", "));
141 }
142 
143 function Wait(server,states,timeout1,timeout2)
144 {
145     if (typeof(states)=="string")
146         states = [ states ];
147 
148     // If timeout2 is defined and >0 wait first for the
149     // server to come online. If it does not come online
150     // in time, an exception is thrown.
151     if (timout2>0 && CheckStates([ server ], timeout2))
152         return true;
153 
154     var time = new Date();
155     while (1)
156     {
157         // If a server disconnects now while checking for the
158         // states, an exception will be thrown, too.
159         if (CheckStates([ server, states ], 0))
160             return true;
161 
162         if (Date()-time>=abs(timeout1))
163             break;
164 
165         v8.sleep();
166     }
167 
168     if (timeout1<0)
169         throw new Error("Timeout waiting for Server "+server+" to be in ["+states+"]");
170 
171     return false;
172 }
173 
174 // Wait 5s for the FAD_CONTROL to get to the states
175 //   return false if FAD_CONTROL is not online
176 //   return false if state is not
177 // Wait("FAD_CONTROL", [ "COnnected", "Disconnected" ], 5000);
178 
179 function dimwait(server, state, timeout)
180 {
181     if (!timeout)
182         timeout = 5000;
183 
184     var time = new Date();
185     while (1)
186     {
187         var s = dim.state(server);
188         if (s.index===state || s.name===state)
189             return true;
190 
191         //if (s.index==undefined)
192         //    throw "Server "+server+" not connected waiting for "+state+".";
193 
194         if (Date()-time>=timeout)
195             break;
196 
197         v8.sleep();
198     }
199 
200     if (timeout>0)
201         throw new Error("Timeout waiting for ["+states+"] of "+server+".");
202 
203     return false;
204 
205 
206     /*
207     if (!timeout)
208         timeout = 5000;
209 
210     var time = new Date();
211     while (timeout<0 || new Date()-time<timeout)
212     {
213         var s = dim.state(server);
214         if (s.index===state || s.name===state)
215             return true;
216 
217         if (s.index==undefined)
218             throw "Server "+server+" not connected waiting for "+state+".";
219 
220         v8.sleep();
221     }
222 
223     return false;
224 */
225 }
226 
227 function Sleep(timeout)
228 {
229     if (!timeout)
230         timeout = 5000;
231 
232     var time = new Date();
233     while (Date()-time<timeout)
234         v8.sleep();
235 }
236 
237 function Timer()
238 {
239     this.date = new Date();
240 
241     this.reset = function() { this.date = new Date(); }
242     this.print = function(id)
243     {
244         var diff = Date()-this.date;
245         if (id)
246             console.out("Time["+id+"]: "+diff+"ms");
247         else
248             console.out("Time: "+diff+"ms");
249     }
250 }
251 
252 function WaitStates(server, states, timeout, func)
253 {
254     var save = dim.onchange[server];
255 
256     function inner()
257     {
258         dim.onchange[server] = function(arg)
259         {
260             if (!this.states)
261                 this.states = states instanceof Array ? states : [ states ];
262 
263             var comp = this.states[0];
264             if (arg.index===comp || arg.name===comp || comp=='*')
265                 this.states.shift();
266 
267             //console.out(JSON.stringify(arg), this.states, comp, arg.name, "");
268 
269             if (save instanceof Function)
270                 save();
271 
272             if (this.states.length==0)
273                 delete dim.onchange[server];
274 
275         }
276 
277         if (func instanceof Function)
278             func();
279 
280         var time = new Date();
281         while (1)
282         {
283             if (!dim.onchange[server])
284                 return true;
285 
286             if (new Date()-time>=timeout)
287                 break;
288 
289             v8.sleep();
290         }
291 
292         delete dim.onchange[server];
293 
294         if (timeout>0)
295             throw new Error("Timeout waiting for ["+states+"] of "+server+".");
296 
297         return false;
298     }
299 
300     var rc = inner();
301     dim.onchang
302         e[server] = save;
303     return rc;
304 }
305