1 # temporal-selector.tcl --
2 #
3 # This file contains the TemporalSelector base class
4 #
5 # Copyright (c) 1998-2002 The Regents of the University of California.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
10 #
11 # A. Redistributions of source code must retain the above copyright notice,
12 # this list of conditions and the following disclaimer.
13 # B. Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 # C. Neither the names of the copyright holders nor the names of its
17 # contributors may be used to endorse or promote products derived from this
18 # software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
24 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 # The TemporalSelector object responds to graph interface communication
32 # received through its recv_graph_comm method and sends graph
33 # interface communication through the send_graph_comm method.
34 #
35
36 # Object fields
37 #
38 # input_id_list_ : list of input ids. The same ids are expected to be used
39 # by individual execution subgraphs
40 # input_info_ : array of info on input_ids. For each input id $i,
41 # ($i,spec) : multicast spec for input data
42 # ($i,trigger) : 0/1 indicating if input is execution trigger
43 # ($i,selector) : selector object for this input
44 # vagent_array_ : array associated by "addr,port" indexes that holds
45 # the name of video agents used by this object.
46 # subgraph_list_ : list of subgraph identifiers. These identifiers are
47 # local only.
48 # subgraph_info_ : array of info on subgraphs. For each subgraph $s and
49 # each input id $i,
50 # ($s,comm_obj) : graph comm object for talking to this subgraph
51 # ($s,spec) : cntrl spec for this subgraph
52 # id_ : id of this object to be used in graph communication
53 # comm_obj_ : object for graph comm (from above, NOT to subgraphs)
54 # callback_array_ : holds comm callbacks with index <sid>,<mid>
55
56 import GraphComm
57 import PsvpVideoAgent
58 import TemporalSelectorInput
59
60 Class TemporalSelector
61
62 TemporalSelector instproc init {id control_spec} {
63 $self next;
64
65 $self instvar input_id_list_;
66 $self instvar input_info_;
67 $self instvar vagent_array_;
68 $self instvar subgraph_list_;
69 $self instvar subgraph_info_;
70 $self instvar id_;
71 $self instvar comm_obj_;
72 $self instvar callback_array_;
73 $self instvar next_subgraph_;
74 $self instvar ctoken_subgraph_q_;
75 $self instvar sid_;
76 $self instvar ctoken_count_;
77 $self instvar token_rate_period_;
78 $self instvar rate_pressure_ rate_constant_;
79
80 # set rate_pressure_ 1.1;
81 set rate_pressure_ 1.0
82 # set rate_constant_ [expr 1.0/1000.0];
83 set rate_constant_ 0.0;
84
85 set input_id_list_ "";
86 set id_ $id;
87
88 set comm_obj_ [new GraphComm/TemporalSelector $self $id_ $control_spec];
89
90 set sid_ -1;
91 set subgraph_list_ "";
92 set next_subgraph_ "";
93 set ctoken_subgraph_q_ "";
94 set ctoken_count_ 0;
95 set token_rate_period_ 1000;
96
97 $self instvar trigger_count_;
98 $self instvar fire_count_;
99
100 set trigger_count_ 0;
101 set fire_count_ 0;
102 }
103
104 TemporalSelector instproc decr_ctoken_count {} {
105 $self instvar ctoken_count_;
106
107 incr ctoken_count_ -1;
108
109 }
110
111 TemporalSelector instproc decr_trigger_count {} {
112 $self instvar trigger_count_;
113
114 incr trigger_count_ -1;
115 }
116
117 TemporalSelector instproc handle_trigger_count {} {
118 $self instvar trigger_count_;
119 $self instvar token_rate_period_;
120
121 incr trigger_count_ 1;
122 after $token_rate_period_ "$self decr_trigger_count";
123 }
124
125 TemporalSelector instproc decr_fire_count {} {
126 $self instvar fire_count_
127
128 incr fire_count_ -1;
129 }
130
131 TemporalSelector instproc handle_fire_count {} {
132 $self instvar fire_count_;
133 $self instvar token_rate_period_;
134
135 incr fire_count_ 1;
136
137 after $token_rate_period_ "$self decr_fire_count";
138 }
139
140 TemporalSelector instproc SetupInput {new_input} {
141 $self instvar subgraph_list_;
142 $self instvar subgraph_info_;
143 $self instvar vagent_array_;
144
145 $self instvar input_id_list_;
146 $self instvar input_info_;
147
148 if {[lsearch $input_id_list_ $new_input] == -1} {
149 $self instvar comm_obj_;
150
151 lappend input_id_list_ $new_input;
152 set input_info_($new_input,spec) "";
153 set input_info_($new_input,trigger) 0;
154 set input_info_($new_input,selector) "";
155
156 $comm_obj_ create_input $new_input
157 }
158 }
159
160 TemporalSelector instproc ReflectInputAttr {iname aname} {
161 $self instvar comm_obj_
162
163 $comm_obj_ create_input_attr $iname $aname
164 }
165
166 TemporalSelector instproc trigger {} {
167 $self instvar next_subgraph_;
168 $self instvar ctoken_subgraph_q_;
169 $self instvar subgraph_list_;
170 $self instvar subgraph_info_;
171 $self instvar input_id_list_;
172 $self instvar input_info_;
173 $self instvar fire_count_;
174
175 $self handle_trigger_count;
176
177 # This is a total hack to prevent overflowing the processors.
178
179 $self instvar last_time_click_;
180 $self instvar update_status;
181 $self instvar ctoken_count_ token_rate_period_;
182 $self instvar rate_pressure_ rate_constant_;
183
184 if {![info exists last_time_click_]} {
185 set last_time_click_ [clock clicks];
186 }
187
188 set now [clock clicks];
189
190 set target_rate [expr ($rate_pressure_ * \
191 (($ctoken_count_*1.0) / ($token_rate_period_*1.0)) + \
192 $rate_constant_)];
193
194 if {$target_rate <= 0.0} {
195 set target_rate .001;
196 }
197
198 set target_interval [expr (0.5 / $target_rate) + (rand() * (0.5 / $target_rate))];
199
200 set tdiff [expr ($now - $last_time_click_) / 1000.0];
201
202 if {$tdiff < $target_interval} {
203 set update_status 0;
204 } elseif {$fire_count_ == $ctoken_count_} {
205 set update_status 1;
206 set last_time_click_ $now
207 } else {
208 set update_status 1;
209 # set last_time_click_ [expr $last_time_click_ + int(($target_interval * 1000.0))];
210 set last_time_click_ $now
211 }
212
213 set s "";
214 if {$update_status} {
215 if {[llength $ctoken_subgraph_q_] > 0} {
216 set s [lindex $ctoken_subgraph_q_ 0];
217 set ctoken_subgraph_q_ [lreplace $ctoken_subgraph_q_ 0 0];
218 } else {
219 set s [lindex $next_subgraph_ 0];
220 set next_subgraph_ [lreplace $next_subgraph_ 0 0];
221 lappend next_subgraph_ $s;
222 }
223
224 # Build and send trigger vector
225 $self instvar tvector_;
226 set tvector_ "";
227 foreach i $input_id_list_ {
228 set selector $input_info_($i,selector);
229 if {$selector != ""} {
230 set ts [$selector get_current_ts];
231 lappend tvector_ [list $i $ts];
232 }
233 }
234 #puts "Trigger: $tvector_"
235 $subgraph_info_($s,comm_obj) send_trigger_vector $tvector_;
236 $self handle_fire_count;
237 }
238 foreach i $input_id_list_ {
239 set selector $input_info_($i,selector);
240 if {$selector != ""} {
241 $selector update_subgraph $s
242 }
243 }
244 }
245
246 TemporalSelector instproc set_input_spec {in_id spec} {
247 $self instvar input_info_;
248 $self instvar vagent_array_;
249 $self instvar subgraph_list_;
250 $self instvar subgraph_info_;
251
252 if {$input_info_($in_id,spec) == $spec} {
253 return;
254 }
255
256 # If input already associated with a spec, delete selector no longer
257 # needed.
258
259 if {$input_info_($in_id,spec) != ""} {
260 set selector $input_info_($in_id,selector);
261 if {$selector != ""} {
262 set vagent [$selector set vagent_];
263
264 set src [[$selector get_decoder] set src_];
265 $src proc trigger_sr {args} {};
266
267 $vagent delete_decoder [$selector get_decoder];
268 delete $selector;
269 set input_info_($id,selector) "";
270 }
271 set input_info_($in_id,spec) "";
272 }
273
274 set spec_split [split $spec "/"];
275
276 set addr [lindex $spec_split 0];
277 set port [lindex $spec_split 1];
278 set srcid [lindex $spec_split 2];
279
280 if {![info exists vagent_array_($addr,$port)]} {
281 set vagent_array_($addr,$port) [new PsvpVideoAgent $addr/$port];
282 }
283 set vagent $vagent_array_($addr,$port);
284
285 set src [$vagent get_source_by_id $srcid];
286
287 if {$src == ""} {
288 $vagent set_create_decoder_callback $srcid "$self set_input_spec_cb $in_id $spec"
289 } else {
290 set fmt_name [$vagent classmap [$src format_name]];
291
292 set selector [new TemporalSelectorInput/${fmt_name} $self $in_id]
293
294 if {$selector == ""} {
295 set selector [new TemporalSelectorInput/Null $self $in_id];
296 }
297 if {$input_info_($in_id,trigger) != 0} {
298 $selector set_callback "$self trigger; # ";
299 }
300 foreach s $subgraph_list_ {
301 $selector add_subgraph $s;
302 }
303 $vagent set_src_decoder $src [$selector get_decoder];
304
305 $selector set vagent_ $vagent;
306
307 set input_info_($in_id,selector) $selector;
308
309 # Major hack to get sender report triggers to work
310 $src proc trigger_sr {args} "catch {$selector trigger_sr $src}";
311
312 }
313 set input_info_($in_id,spec) $spec;
314 }
315
316 TemporalSelector instproc set_input_spec_cb {id spec src} {
317 $self instvar input_info_
318 $self instvar vagent_array_
319 $self instvar subgraph_info_
320 $self instvar subgraph_list_
321
322 if {$input_info_($id,spec) != $spec} {
323 puts "$input_info_($id,spec) != $spec !!!";
324 return;
325 }
326
327 if {$input_info_($id,selector) != ""} {
328 puts "$input_info_($id,selector) != {} !!!";
329 return;
330 }
331
332 # Find videoagent and source
333
334 set spec_split [split $spec "/"];
335
336 set addr [lindex $spec_split 0];
337 set port [lindex $spec_split 1];
338 set srcid [lindex $spec_split 2];
339
340 set vagent $vagent_array_($addr,$port);
341
342 # Setup decoder.
343
344 set fmt_name [$vagent classmap [$src format_name]];
345
346 set selector [new TemporalSelectorInput/${fmt_name} $self $id];
347
348 if {$selector == ""} {
349 # No such selector. Create a NULL decoder and associate that.
350 set selector [new TemporalSelectorInput/Null $self $id];
351 } else {
352 if {$input_info_($id,trigger) != 0} {
353 $selector set_callback "$self trigger; #";
354 }
355 foreach s $subgraph_list_ {
356 $selector add_subgraph $s;
357 }
358 }
359 # Update input info array
360
361 $selector set vagent_ $vagent;
362
363 set input_info_($id,selector) $selector;
364
365 # Major hack to get sender report triggers to work
366 $src proc trigger_sr {args} "catch {$selector trigger_sr $src}";
367
368 return [$selector get_decoder];
369 }
370
371 TemporalSelector instproc set_subgraph_input_spec {sid in_id spec} {
372 $self instvar subgraph_info_;
373
374 $subgraph_info_($sid,comm_obj) set_input_spec $in_id $spec;
375 }
376
377 TemporalSelector instproc GenerateSpec {} {
378 # OK, this is a REAL hack
379
380 global spec_generator;
381
382 if {![info exists spec_generator(init)]} {
383 set gen_spec [split [$self get_option gen_spec] "."];
384
385 set spec_generator(init) 1;
386 set spec_generator(b1) [lindex $gen_spec 0];
387 set spec_generator(b2) [lindex $gen_spec 1];
388 set spec_generator(b3) [lindex $gen_spec 2];
389 set spec_generator(b4) [lindex $gen_spec 3];
390 set spec_generator(port) [expr (int(rand() * 5000)*2) + 10000]
391 }
392
393 incr spec_generator(b4);
394
395 return "$spec_generator(b1).$spec_generator(b2).$spec_generator(b3).$spec_generator(b4)/$spec_generator(port)/16";
396 }
397
398 Class GraphComm/TemporalSelector -superclass GraphComm
399
400 GraphComm/TemporalSelector instproc init {tselect id spec} {
401 $self instvar tselect_;
402
403 set tselect_ $tselect;
404
405 set spec [split $spec "/"];
406
407 set addr [lindex $spec 0];
408 set port [lindex $spec 1];
409 set ttl [lindex $spec 2];
410
411 $self next $id $addr $port $ttl;
412
413 $self instvar sess_map_ primary_sess_;
414
415 set sess_map_($primary_sess_,inputs) 1;
416 set sess_map_($primary_sess_,outputs) 0;
417 set sess_map_($primary_sess_,parameters) 0;
418 set sess_map_($primary_sess_,misc) 1;
419 set sess_map_($primary_sess_,trigger_cmds) 1;
420 set sess_map_($primary_sess_,map_cmds) 1;
421 }
422
423 GraphComm/TemporalSelector instproc recv_misc {data} {
424 $self next $data;
425
426 $self instvar tselect_;
427
428 set cmd [lindex $data 0];
429
430 switch -exact -- $cmd {
431 add_subgraph {
432 puts "In add_subgraph"; #debug
433
434 $tselect_ instvar subgraph_list_ subgraph_info_ id_ sid_;
435 $tselect_ instvar next_subgraph_;
436
437 set new_subgraph [lindex $data 1];
438
439 foreach sid $subgraph_list_ {
440 if {$subgraph_info_($sid,spec) == $new_subgraph} {
441 return;
442 }
443 }
444
445 incr sid_;
446 lappend subgraph_list_ $sid_;
447 lappend next_subgraph_ $sid_;
448
449 puts "Creating subgraph comm"; # debug
450 $self instvar primary_sess_;
451
452 set subgraph_info_($sid_,comm_obj) [new GraphComm/TSToSubgraph $tselect_ $id_ $new_subgraph];
453 $subgraph_info_($sid_,comm_obj) send_map_command [list map_parameters [$primary_sess_ set addr_] [$primary_sess_ set rport_] [$primary_sess_ set ttl_]];
454 $self send_map_command [list map_parameters [[$subgraph_info_($sid_,comm_obj) set primary_sess_] set addr_] [[$subgraph_info_($sid_,comm_obj) set primary_sess_] set rport_] [[$subgraph_info_($sid_,comm_obj) set primary_sess_] set ttl_]];
455
456 $subgraph_info_($sid_,comm_obj) set sid_ $sid_;
457
458 set subgraph_info_($sid_,spec) $new_subgraph;
459
460 $tselect_ instvar input_id_list_ input_info_;
461
462 foreach i $input_id_list_ {
463 if {$input_info_($i,selector) != ""} {
464 $input_info_($i,selector) add_subgraph $sid_;
465 }
466 }
467 }
468 del_subgraph {
469 $tselect_ instvar subgraph_info_ subgraph_list_ next_subgraph_;
470
471 set spec_to_del [lindex $data 1];
472 set sid_to_del "";
473 foreach s $subgraph_list_ {
474 if {$subgraph_info_($s,spec) == $spec_to_del} {
475 set sid_to_del $s;
476 break;
477 }
478 }
479 if {$sid_to_del == ""} {
480 return;
481 }
482 set idx [lindex $subgraph_list_ $sid_to_del];
483 set subgraph_list_ [lreplace $subgraph_list_ $idx $idx];
484
485 set idx [lindex $next_subgraph_ $sid_to_del];
486 if {$idx != -1} {
487 set next_subgraph_ [lreplace $next_subgraph_ $idx $idx];
488 }
489
490 $tselect_ instvar input_id_list_ input_info_;
491
492 foreach i $input_id_list_ {
493 set selector $input_info_($i,selector);
494 if {$selector != ""} {
495 $selector del_subgraph $sid_to_del;
496 }
497 }
498 delete $subgraph_info_($sid_to_del,comm_obj);
499 unset subgraph_info_($sid_to_del,comm_obj);
500 unset subgraph_info_($sid_to_del,spec);
501
502 if {$subgraph_list_ == ""} {
503 # All the subgraphs are gone.
504 # FIXME Need to handle this case.
505 }
506 }
507 }
508 return;
509 }
510
511 GraphComm/TemporalSelector instproc recv_trigger_command {data} {
512 $self next $data;
513
514 $self instvar tselect_;
515
516 $tselect_ instvar subgraph_list_;
517
518 if {$subgraph_list_ == ""} {
519 return;
520 }
521
522 set cmd [lindex $data 0];
523
524 switch -exact -- $cmd {
525 trigger {
526 $tselect_ trigger;
527 }
528 }
529 return;
530 }
531
532 GraphComm/TemporalSelector instproc update_input_attr_value {input_name attr value} {
533 $self next $input_name $attr $value;
534
535 $self instvar tselect_
536 $tselect_ instvar input_id_list_;
537
538 if {[lsearch $input_id_list_ $input_name] == -1} {
539 return;
540 }
541
542 switch -exact -- $attr {
543 spec {
544 $tselect_ set_input_spec $input_name $value;
545 }
546 trigger {
547 $tselect_ instvar input_info_;
548
549 set type [lindex $value 0];
550 if {$type == "auto"} {
551 set trigger_flag [lindex $value 1];
552 if {$input_info_($input_name,trigger) != $trigger_flag} {
553 set input_info_($input_name,trigger) $trigger_flag;
554
555 if {$input_info_($input_name,selector) != ""} {
556 if {$input_info_($input_name,trigger) != 0} {
557 $input_info_($input_name,selector) set_callback "$tselect_ trigger; # ";
558 } else {
559 $input_info_($input_name,selector) set_callback "";
560 }
561 }
562 }
563 }
564
565 set some_trigger 0;
566 foreach in_id $input_id_list_ {
567 if {$input_info_($in_id,trigger) != 0} {
568 set some_trigger 1;
569 break;
570 }
571 }
572 if {$some_trigger == 0} {
573 $tselect_ instvar last_time_click_;
574 if {[info exists last_time_click_]} {
575 unset last_time_click_;
576 }
577 }
578 }
579 }
580 }
581
582 Class GraphComm/TSToSubgraph -superclass GraphComm;
583
584 GraphComm/TSToSubgraph instproc init {tselect id spec} {
585 $self instvar tselect_;
586
587 set tselect_ $tselect;
588
589 set spec [split $spec "/"];
590
591 set addr [lindex $spec 0];
592 set port [lindex $spec 1];
593 set ttl [lindex $spec 2];
594
595 $self next $id $addr $port $ttl;
596
597 $self instvar primary_sess_ sess_map_;
598
599 set sess_map_($primary_sess_,outputs) 0;
600 set sess_map_($primary_sess_,parameters) 0;
601 }
602
603 GraphComm/TSToSubgraph instproc new_input {new_input} {
604 $self next $new_input;
605
606 $self instvar tselect_;
607
608 $tselect_ SetupInput $new_input;
609 }
610
611 GraphComm/TSToSubgraph instproc new_input_attribute {iname aname} {
612 $self next $iname $aname;
613
614 $self instvar tselect_;
615
616 $tselect_ ReflectInputAttr $iname $aname
617 }
618
619
620 GraphComm/TSToSubgraph instproc set_input_spec {id value} {
621 $self create_input $id;
622 $self create_input_attr $id spec;
623 $self set_input_attr $id spec $value;
624 }
625
626 GraphComm/TSToSubgraph instproc send_trigger_vector {vec} {
627 $self send_trigger_command [list trigger_vector $vec];
628 }
629
630 GraphComm/TSToSubgraph instproc recv_trigger_command {data} {
631 $self instvar sid_;
632
633 set cmd [lindex $data 0];
634
635 switch -exact -- $cmd {
636 trigger_completion_token {
637 $self instvar tselect_;
638 $tselect_ instvar next_subgraph_;
639 $tselect_ instvar ctoken_subgraph_q_;
640 $tselect_ instvar subgraph_list_;
641
642 $tselect_ instvar ctoken_count_ token_rate_period_;
643
644 incr ctoken_count_ 1;
645 #######
646 #puts "CTokenCount = $ctoken_count_";
647 #######
648 after $token_rate_period_ "$tselect_ decr_ctoken_count";
649
650 if {[lsearch $subgraph_list_ $sid_] != -1} {
651 lappend ctoken_subgraph_q_ $sid_;
652 }
653 }
654 }
655 }
656
657 GraphComm/TSToSubgraph instproc recv_map_command {cmd} {
658 set type [lindex $cmd 0];
659 set addr [lindex $cmd 1];
660 set port [lindex $cmd 2];
661 set ttl [lindex $cmd 3];
662
663 switch -exact -- $type {
664 map_parameter -
665 map_parameters {
666 $self instvar tselect_;
667 $tselect_ instvar comm_obj_;
668
669 $comm_obj_ send_map_command $cmd;
670 }
671 default {
672 $self next $cmd;
673 }
674 }
675 }
676
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.