fixed buggy optimization
[brisk.git] / web / briskin5 / Obj / briskin5.phh
1 <?php
2 define(BRISKIN5_PLAYERS_N, 3);
3 define(BRISKIN5_MAX_PLAYERS, BRISKIN5_PLAYERS_N);
4 // define(BRISKIN5_SHM_MIN, (50000 * BRISKIN5_MAX_PLAYERS));
5 define(BRISKIN5_SHM_MIN, 10000);
6 define(BRISKIN5_SHM_MAX, (BRISKIN5_SHM_MIN + 1048576));
7 define(BRISKIN5_SHM_DLT, 65536);
8
9 class Briskin5 {
10   var $user;
11   var $table;
12   var $table_idx;
13   var $table_token;
14
15   var $comm; // commands for many people
16   var $step; // current step of the comm array
17   var $garbage_timeout;
18
19   var $the_end;
20   
21   var $tok;
22   var $shm_sz;
23
24   function Briskin5 (&$room, $table_idx, $table_token) {
25     $this->user = array();
26     $this->table = array();
27
28     $this->the_end = FALSE;
29     $this->shm_sz = BRISKIN5_SHM_MIN;
30     if (($this->tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
31       echo "FTOK FAILED";
32       exit;
33     }
34
35     $user  =& $room->user;
36     $table =& $room->table[$table_idx];
37
38     log_wr("Briskin5 constructor");
39
40     for ($i = 0 ; $i < $table->player_n ; $i++) {
41       $user[$table->player[$i]]->table_token = $table_token;
42       $this->user[$i] =& User::spawn(&$user[$table->player[$i]], 0, $i);
43     }
44     $this->table[0] =& Table::spawn(&$table);
45     $this->table_idx = $table_idx;
46     $this->table_token = $table_token;
47     $this->garbage_timeout = 0;
48     
49     log_wr("Briskin5 constructor end");
50   }
51
52
53   function &get_user($sess, &$idx)
54   {
55     GLOBAL $PHP_SELF, $G_false;
56
57     if (validate_sess($sess)) {
58       for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
59         if (strcmp($sess, $this->user[$i]->sess) == 0) {
60           // find it
61           $idx = $i;
62           $ret = &$this->user[$i];
63           return ($ret);
64         }
65       }
66       log_main(sprintf("get_user: Wrong sess from page [%s]",$PHP_SELF));
67       // for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) 
68       // log_main(sprintf("get_user: Wrong sess compared with [%s]",$this->user[$i]->sess));
69     }
70     else {
71       log_main(sprintf("get_user: Wrong strlen [%s]",$sess));
72     }
73
74     return ($G_false);
75   }
76
77
78   function garbage_manager($force)
79   {
80     
81     /* Garbage collector degli utenti in timeout */
82     $ismod = FALSE;
83     $curtime = time();
84     if ($force || $this->garbage_timeout < $curtime) {
85       
86       for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
87         $user_cur = &$this->user[$i];
88         if ($user_cur->sess == "" || 
89             ($user_cur->stat == 'table' && ($user_cur->subst == 'shutdowned' || $user_cur->subst == 'shutdowner')))
90           continue;
91         
92         if ($user_cur->lacc + EXPIRE_TIME_RD < $curtime) { // Auto logout dell'utente
93           log_rd2($user_cur->sess." bin5 AUTO LOGOUT.");
94
95           if ($user_cur->stat == 'table') {
96             log_auth($user_cur->sess," bin5 Autologout session.");
97
98             /* SI DELEGA AL garbage_manager principale LA RIMOZIONE DELL'UTENTE 
99
100             $tmp_sess = $user_cur->sess;
101             $user_cur->sess = "";
102             step_unproxy($tmp_sess);
103             $user_cur->name = "";
104             $user_cur->the_end = FALSE;
105             
106             */
107
108             $this->table_wakeup(&$user_cur);
109           }
110         }
111       }
112       log_rd2($user_cur->sess." GARBAGE UPDATED!");
113       
114       $this->garbage_timeout = $curtime + GARBAGE_TIMEOUT;
115       $ismod = TRUE;
116     }
117
118     return ($ismod);
119   }
120
121
122
123
124   //
125   //  static functions
126   //
127   function &load_data($table_idx, $table_token = "") 
128   {
129     GLOBAL $G_false, $sess;
130     $doexit = FALSE;
131     $shm = FALSE;
132
133     log_wr("TABLE_IDX ".FTOK_PATH."/table".$table_idx);
134     
135     do {
136       if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
137         log_main("ftok failed");
138         $doexit = TRUE;
139         break;
140       }
141
142       if (($shm_sz = sharedmem_sz($tok)) == -1) {
143         log_main("shmop_open failed");
144         break;
145       }
146         
147       if (($shm = shm_attach($tok, $shm_sz)) == FALSE)
148         break;
149
150       if (($bri = @shm_get_var($shm, $tok)) == FALSE) 
151         break;
152
153       if ($table_token != "" && $bri->table_token != $table_token) {
154         log_wr("bri->table_token: ".$bri->table_token."table_token: ".$table_token);
155         
156         break;
157       }
158       $bri->tok = $tok;
159
160       shm_detach($shm);
161         
162       $ret = &$bri;
163       return ($ret); 
164     } while (FALSE);
165
166     if ($shm != FALSE)
167       shm_detach($shm);
168
169     log_wr("briskin5 load_data failed");
170     if ($doexit)
171       exit();
172     
173     return ($G_false);
174   }
175   
176
177
178   function save_data(&$bri) 
179   {
180     GLOBAL $sess;
181     
182     $ret =   FALSE;
183     $shm =   FALSE;
184     
185     log_main("SAVE BRISKIN5 DATA");
186     
187     if (!isset($bri->tok))
188       return (FALSE);
189     
190     while ($bri->shm_sz < BRISKIN5_SHM_MAX) {
191       if (($shm = shm_attach($bri->tok, $bri->shm_sz)) == FALSE)
192         break;
193       
194       // log_only("PUT_VAR DI ".strlen(serialize($room)));
195       if (@shm_put_var($shm, $bri->tok, $bri) != FALSE) {
196         shm_detach($shm);
197         return (TRUE);
198       }
199       if (shm_remove($shm) === FALSE) {
200         log_only("REMOVE FALLITA");
201         break;
202       }
203       shm_detach($shm);
204       $bri->shm_sz += BRISKIN5_SHM_DLT;
205     } 
206
207     if ($shm)
208       shm_detach($shm);
209     
210     return ($ret);
211   }
212
213
214
215   function save_data_orig(&$bri) 
216   {
217     GLOBAL $sess;
218     
219     $ret =   FALSE;
220     $shm =   FALSE;
221     $isacq = FALSE;
222     
223     log_main("SAVE BRISKIN5 DATA");
224     // var_dump($bri);
225     
226     if (!isset($bri->tok))
227       return (FALSE);
228     
229     do {
230       $isacq = TRUE;
231       
232       if (($shm = shm_attach($bri->tok, BRISKIN5_SHM_DIMS)) == FALSE)
233         break;
234       
235       // log_only("PUT_VAR DI ".strlen(serialize($bri)));
236       if (shm_put_var($shm, $bri->tok, $bri) == FALSE) {
237         log_only("PUT_VAR FALLITA ".strlen(serialize($bri)));
238         log_only(serialize($bri));
239         break;
240       }
241       // log_main("QUI CI ARRIVA [".$bri->user[0]->name."]");
242       $ret = TRUE;
243     } while (0);
244     
245     if ($shm)
246       shm_detach($shm);
247     
248     return ($ret);
249   }
250
251   function destroy_data($table_idx) 
252   {
253     GLOBAL $sess;
254
255     $ret =   FALSE;
256     $shm =   FALSE;
257     log_main("DESTROY BRISKIN5 DATA");
258     
259     do {
260       log_main("DESTROY2 BRISKIN5 DATA");
261
262       if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) 
263         break;
264
265       if (($shm = @shmop_open($tok, 'a', 0, 0)) == FALSE)
266         break;
267       
268       if (shmop_delete($shm) == 0) {
269         log_only("REMOVE FALLITA ");
270         break;
271       }
272    
273       $shm = FALSE;
274       log_main("DESTROY2 BRISKIN5 DATA SUCCESS");
275       
276       // log_main("QUI CI ARRIVA [".$bri->user[0]->name."]");
277       $ret = TRUE;
278     } while (0);
279     
280     if ($shm)
281       shm_detach($shm);
282     
283     return ($ret);
284   }
285
286   function lock_data($table_idx)
287   {
288     GLOBAL $sess; 
289     
290     log_wr("LOCK_DATA ".FTOK_PATH."/table".$table_idx);
291     //  echo "LOCK: ".FTOK_PATH."/main";
292     //  exit;
293     // FIXME monitor this step
294     if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
295       echo "FTOK FAILED";
296       exit;
297     }
298     // FIXME monitor this step
299     if (($res = @sem_get($tok)) == FALSE) {
300       echo "SEM_GET FAILED";
301       exit;
302     }
303     if (sem_acquire($res)) {   
304       log_lock("LOCK table ".$table_idx."[res: ".$res."]");
305       return ($res);
306     }
307     else {
308       log_lock("LOCK table ".$table_idx.":FAILED");
309       return (FALSE);
310     }
311   }
312   
313   function unlock_data($res)
314   {
315     GLOBAL $sess; 
316     
317     log_lock("UNLOCK table [res: ".$res."]");
318
319     return (sem_release($res));
320   }
321
322
323   function chatt_send(&$user, $mesg)
324   {
325     if ($user->stat == 'table') {
326       $table = &$this->table[$user->table];
327     }
328     
329     $user_mesg = substr($mesg,6);
330     
331     $timecur = time();
332     
333     $dt = date("H:i ", $timecur);
334     if (strncmp($user_mesg, "/nick ", 6) == 0) {
335       log_main($user->sess." chatt_send BEGIN");
336
337       if (($name_new = validate_name(substr($user_mesg, 6))) == FALSE) {
338           $user->comm[$user->step % COMM_N] = "gst.st = ".($user->step+1)."; ";
339           $user->comm[$user->step % COMM_N] .= sprintf('chatt_sub("%s","Il nickname deve contenere almeno una lettera o una cifra.");', $dt.NICKSERV, xcape($name_new));
340           $user->step_inc();
341
342           return;
343       }
344       $user_mesg = "COMMAND ".$user_mesg;
345       // Search dup name
346       // change
347       // update local graph
348       // update remote graphs
349       for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
350         $user_cur = &$this->user[$i];
351         //      if ($user_cur->sess == '' || $user_cur->stat != 'room')
352         if ($user_cur->sess == '')
353           continue;
354         if ($user_cur->name == $name_new) {
355           $user->comm[$user->step % COMM_N] = "gst.st = ".($user->step+1)."; ";
356           $user->comm[$user->step % COMM_N] .= sprintf('chatt_sub("%s","Nickname <b>%s</b> gi&agrave; in uso.");', $dt.NICKSERV, xcape($name_new));
357           $user->step_inc();
358           break;
359         }
360       }
361       if ($i == BRISKIN5_MAX_PLAYERS) {
362         $user->name = $name_new;
363
364       log_main($user->sess." chatt_send start set");
365         
366
367         for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
368           log_main($user->sess." chatt_send set loop");
369           
370           $user_cur = &$this->user[$i];
371           if ($user_cur->sess == '')
372             continue;
373           if ($user_cur->stat == 'room') {
374             if ($user->stat == 'room' && $user->subst == 'standup') {
375               $this->standup_update(&$user);
376             }
377             else if ($user->stat == 'room' && $user->subst == 'sitdown' ||
378                      $user->stat == 'table') {
379               log_main($user->sess." chatt_send pre table update");
380
381               $this->table_update(&$user);
382
383               log_main($user->sess." chatt_send post table update");
384             }
385           }
386           else if ($user_cur->stat == 'table' && $user_cur->table == $user->table) {
387             $table = &$this->table[$user->table];
388             
389             $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
390             $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('set_names(" %s", " %s", " %s", " %s", " %s"); ',
391                 xcape($this->user[$table->player[($user_cur->table_pos) % BRISKIN5_PLAYERS_N]]->name),
392                 xcape($this->user[$table->player[($user_cur->table_pos+1) % BRISKIN5_PLAYERS_N]]->name),
393                 xcape($this->user[$table->player[($user_cur->table_pos+2) % BRISKIN5_PLAYERS_N]]->name),
394                 (BRISKIN5_PLAYERS_N == 3 ? "" :  xcape($this->user[$table->player[($user_cur->table_pos+3) % BRISKIN5_PLAYERS_N]]->name)),
395                 (BRISKIN5_PLAYERS_N == 3 ? "" :  xcape($this->user[$table->player[($user_cur->table_pos+4) % BRISKIN5_PLAYERS_N]]->name)));
396             if ($user_cur == $user)
397               $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('$("myname").innerHTML = "<b>%s</b>";', 
398                                                                    xcape($user->name,ENT_COMPAT,"UTF-8"));
399             $user_cur->step_inc();
400           }
401         }
402       }
403     }
404     else {
405       for ($i = 0 ; $i < ($user->stat == 'room' ? BRISKIN5_MAX_PLAYERS : BRISKIN5_PLAYERS_N) ; $i++) {
406         if ($user->stat == 'room') {
407           $user_cur = &$this->user[$i];
408           if ($user_cur->sess == '' || $user_cur->stat != 'room')
409             continue;
410         }
411         else {
412           $user_cur = &$this->user[$table->player[$i]];
413         }
414         
415         $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
416         $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('chatt_sub("%s","%s");',
417                                                              $dt.xcape($user->name), xcape($user_mesg));
418         $user_cur->step_inc();
419       }
420       log_legal($timecur, $user->sess, $user->name, 
421                 ($user->stat == 'room' ? 'room' : 'table '.$user->table),$user_mesg);
422     }
423   }
424
425   function table_wakeup(&$user)
426   {
427     $table = &$this->table[0];
428
429     log_main("BRISKIN5_WAKEUP begin function table  stat: ".$user->stat."  subst: ".$user->subst);
430
431     $curtime = time();
432
433     log_main("BRISKIN5_WAKEUP from table [".$user->table."] nplayers_n: ".$this->table[$user->table]->player_n);
434     
435     for ($i = 0 ; $i < $table->player_n ; $i++) {
436       $user_cur = &$this->user[$i];
437       log_main("PREIMPOST INLOOP name: ".$user_cur->name);
438       
439       if ($user_cur == $user)
440         $user_cur->subst = "shutdowner";
441       else
442         $user_cur->subst = "shutdowned";
443       $user_cur->laccwr = $curtime;
444
445       $ret = "gst.st = ".($user_cur->step+1)."; ";
446       $ret .= 'gst.st_loc++; the_end=true; window.onunload = null; document.location.assign("../index.php");|';
447
448       log_wr($user_cur->sess." BRISKIN5_WAKEUP: ".$ret);
449       $user_cur->comm[$user_cur->step % COMM_N] = $ret;
450       $user_cur->step_inc();
451     }
452
453     $this->the_end = TRUE;
454   }
455   
456   /*
457    *  If all players are freezed the room garbage_manager clean up table and users.
458    */ 
459   function is_abandoned() 
460   {
461     $is_ab = TRUE;
462     $curtime = time();
463
464     $table = &$this->table[0];
465
466     for ($i = 0 ; $i < $table->player_n ; $i++) {
467       $user_cur = &$this->user[$i];
468
469       if ($user_cur->lacc + (EXPIRE_TIME_RD * 2) >= $curtime) { 
470         $is_ab = FALSE;
471         break;
472       }
473     }
474
475     return ($is_ab);
476   }
477 } // end class Briskin5
478
479 function locshm_exists($tok)
480 {
481   // return (TRUE);
482
483   if (($id = @shmop_open($tok,"a", 0, 0)) == FALSE) {
484     log_main($tok." SHM NOT exists");
485
486     return (FALSE);
487   }
488   else {
489     shmop_close($id);
490     log_main($tok." SHM exists");
491
492     return (TRUE);
493   }
494     
495 }
496
497
498 ?>