1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11
12
13
14
15 #include <stdlib.h>
16
17 #include "DXStrings.h"
18 #include "lex.h"
19 #include "ProcessGroupManager.h"
20 #include "ProcessGroupAssignDialog.h"
21 #include "Dictionary.h"
22 #include "ListIterator.h"
23 #include "List.h"
24 #include "Network.h"
25 #include "ErrorDialogManager.h"
26 #include "EditorWindow.h"
27 #include "DXPacketIF.h"
28 #include "DXApplication.h"
29
ProcessGroupManager(Network * net)30 ProcessGroupManager::ProcessGroupManager(Network *net):
31 GroupManager(net, theSymbolManager->registerSymbol(PROCESS_GROUP))
32 {
33 // Would like to assert this, but in Network::Network, theDXApplication->network
34 // isn't set yet.
35 //ASSERT (theDXApplication->network == net);
36 this->assignment = NULL;
37 }
~ProcessGroupManager()38 ProcessGroupManager::~ProcessGroupManager()
39 {
40 }
41
clear()42 void ProcessGroupManager::clear()
43 {
44 this->GroupManager::clear();
45 this->clearArgument();
46
47 if(this->assignment)
48 {
49 this->sendAssignment(DETACH);
50 this->clearAssignment();
51 }
52
53 if(theDXApplication->processGroupAssignDialog)
54 theDXApplication->processGroupAssignDialog->unmanage();
55 }
56
getGroupHost(int n)57 const char* ProcessGroupManager::getGroupHost(int n)
58 {
59 return this->getGroupHost(this->getGroupName(n));
60 }
61
getGroupHost(const char * name)62 const char* ProcessGroupManager::getGroupHost(const char *name)
63 {
64 ProcessGroupRecord *record
65 = (ProcessGroupRecord*)this->groups.findDefinition(name);
66
67 if(NOT record)
68 return NULL;
69 else
70 return record->host;
71 }
72
getGroupNewHost(int n)73 const char* ProcessGroupManager::getGroupNewHost(int n)
74 {
75 return this->getGroupNewHost(this->getGroupName(n));
76 }
77
getGroupNewHost(const char * name)78 const char* ProcessGroupManager::getGroupNewHost(const char *name)
79 {
80 ProcessGroupRecord *record
81 = (ProcessGroupRecord*)this->groups.findDefinition(name);
82
83 if(NOT record)
84 return NULL;
85 else
86 return record->newhost;
87 }
88
getGroupHostDirty(const char * name)89 boolean ProcessGroupManager::getGroupHostDirty(const char *name)
90 {
91 ProcessGroupRecord *record
92 = (ProcessGroupRecord*)this->groups.findDefinition(name);
93
94 if(NOT record)
95 return FALSE;
96 else
97 return record->isDirty();
98 }
99
clearGroupHostDirty(const char * name)100 void ProcessGroupManager::clearGroupHostDirty(const char *name)
101 {
102 ProcessGroupRecord *record
103 = (ProcessGroupRecord*)this->groups.findDefinition(name);
104
105 if(record)
106 record->setDirty(FALSE);
107 }
108
assignHost(int n,const char * hostname)109 boolean ProcessGroupManager::assignHost(int n, const char *hostname)
110 {
111 return assignHost(this->getGroupName(n), hostname);
112 }
113
assignHost(const char * groupname,const char * hostname)114 boolean ProcessGroupManager::assignHost(const char *groupname,
115 const char *hostname)
116 {
117 ProcessGroupRecord *record
118 = (ProcessGroupRecord*)this->groups.findDefinition(groupname);
119
120 if(NOT record)
121 return FALSE;
122
123 if(record->newhost)
124 delete record->newhost;
125
126 if(hostname)
127 record->newhost = DuplicateString(hostname);
128 else
129 record->newhost = DuplicateString("localhost");
130
131 return TRUE;
132 }
133
updateHosts()134 void ProcessGroupManager::updateHosts()
135 {
136 int i;
137 const char *group;
138 ProcessGroupRecord *record;
139
140 for(i = 1; i <= this->getGroupCount(); i++)
141 {
142 group = this->getGroupName(i);
143 record = (ProcessGroupRecord*)this->groups.findDefinition(group);
144
145 if (!record OR !record->newhost) continue;
146
147 if (!record->host || !EqualString(record->host, record->newhost)) {
148 if(record->host)
149 delete record->host;
150
151 record->host = DuplicateString(record->newhost);
152 record->setDirty(TRUE);
153 record->getNetwork()->setFileDirty();
154 }
155 delete record->newhost;
156 record->newhost = NULL;
157 }
158 }
159
clearNewHosts()160 void ProcessGroupManager::clearNewHosts()
161 {
162 int i;
163 const char *group;
164 ProcessGroupRecord *record;
165
166 for(i = 1; i <= this->getGroupCount(); i++)
167 {
168 group = this->getGroupName(i);
169 record = (ProcessGroupRecord*)this->groups.findDefinition(group);
170
171 if (!record OR !record->newhost) continue;
172
173 delete record->newhost;
174 record->newhost = NULL;
175 }
176 }
177
getArgument(const char * name)178 const char* ProcessGroupManager::getArgument(const char *name)
179 {
180 ProcessHostRecord *record =
181 (ProcessHostRecord*)this->arguments.findDefinition(name);
182 if(record)
183 return record->args;
184 else
185 return NUL(char*);
186 }
187
getArgumentDirty(const char * name)188 boolean ProcessGroupManager::getArgumentDirty(const char *name)
189 {
190 ProcessHostRecord *record =
191 (ProcessHostRecord*)this->arguments.findDefinition(name);
192
193 if(record)
194 return record->dirty;
195 else
196 return FALSE;
197 }
198
clearArgumentDirty(const char * name)199 void ProcessGroupManager::clearArgumentDirty(const char *name)
200 {
201 ProcessHostRecord *record =
202 (ProcessHostRecord*)this->arguments.findDefinition(name);
203
204 if(record)
205 record->dirty = FALSE;
206 }
207
assignArgument(const char * host,const char * args)208 void ProcessGroupManager::assignArgument(const char *host,const char *args)
209 {
210 ProcessHostRecord *record =
211 (ProcessHostRecord*)this->arguments.findDefinition(host);
212
213 if (record)
214 {
215 if(record->args)
216 delete record->args;
217 if(args)
218 record->args = DuplicateString(args);
219 else
220 record->args = NUL(char*);
221 }
222 else
223 {
224 record = new ProcessHostRecord((char*)args);
225 this->arguments.addDefinition(host,(const void*)record);
226 }
227
228 record->dirty = TRUE;
229 this->app->network->setFileDirty();
230 }
231 // clear the argument dictionary
clearArgument()232 void ProcessGroupManager::clearArgument()
233 {
234 ProcessHostRecord *record;
235
236 while ( (record = (ProcessHostRecord*) this->arguments.getDefinition(1)) )
237 {
238 this->arguments.removeDefinition((const void*)record);
239 delete record;
240 }
241 }
242
243
createAssignment()244 Dictionary *ProcessGroupManager::createAssignment()
245 {
246 int i, size = this->groups.getSize();
247
248 if(size == 0)
249 return NULL;
250
251 Dictionary *dic = new Dictionary();
252 List *list;
253
254 for (i=1; i<=size; i++)
255 {
256 const char *host = this->getGroupHost(i);
257 char *group;
258 if(NOT host)
259 host = "localhost";
260 // continue;
261
262 group = DuplicateString((char*)this->groups.getStringKey(i));
263
264 if( (list = (List*)dic->findDefinition(host)) )
265 {
266 list->appendElement((void*)group);
267 }
268 else
269 {
270 list = new List();
271 list->appendElement((void*)group);
272 dic->addDefinition(host, (void*)list);
273 }
274 }
275
276 if(dic->getSize())
277 return dic;
278
279 delete dic;
280 return NULL;
281 }
282
clearAssignment()283 void ProcessGroupManager::clearAssignment()
284 {
285 if(NOT this->assignment)
286 return;
287
288 int i, size = this->assignment->getSize();
289 ListIterator li;
290 char *group;
291 List *list;
292
293 for (i=1; i<=size; i++)
294 {
295 list = (List*)this->assignment->getDefinition(i);
296 li.setList(*list);
297
298 while( (group = (char*)li.getNext()) )
299 delete group;
300
301 list->clear();
302 delete list;
303 }
304
305 delete this->assignment;
306 this->assignment = NULL;
307 }
308
sendAssignment(int function)309 void ProcessGroupManager::sendAssignment(int function)
310 {
311 DXPacketIF *p = this->app->getPacketIF();
312 if (!p)
313 return;
314
315 this->setDirty(FALSE);
316 if (!this->assignment)
317 return;
318
319 List *list;
320 ListIterator li;
321 int i;
322 boolean first;
323 char *func = NULL, *host, *grouplist,*group, *cmd;
324
325 switch(function)
326 {
327 case ATTACH:
328
329 func = "group attach";
330 this->dirty = FALSE;
331 break;
332
333 case DETACH:
334
335 func = "group detach";
336 break;
337
338 default:
339
340 ASSERT(FALSE);
341 }
342
343 for(i = 1; i <= this->assignment->getSize(); i++)
344 {
345 host = (char*)this->assignment->getStringKey(i);
346 this->clearArgumentDirty(host);
347 const char *args = this->getArgument(host);
348 list = (List*)this->assignment->getDefinition(i);
349
350 /* figure out how much, and allocate space for all group names */
351 int grouplistSize = 0;
352 li.setList(*list);
353 while( (group = (char*)li.getNext()) )
354 grouplistSize += STRLEN(group);
355 grouplist = new char[grouplistSize + 20 * list->getSize()];
356 grouplist[0] = '\0';
357
358 first = TRUE;
359 li.setList(*list);
360 while( (group = (char*)li.getNext()) )
361 {
362 this->clearGroupHostDirty(group);
363 if(first)
364 first = FALSE;
365 else
366 strcat(grouplist, ",");
367
368 if(function == DETACH)
369 strcat(grouplist, "\"");
370
371 strcat(grouplist, group);
372
373 if(function == DETACH)
374 strcat(grouplist, "\"");
375 }
376
377 cmd = new char[STRLEN("exective( ), ")
378 + STRLEN(func)
379 + STRLEN(host)
380 + STRLEN(args)
381 + STRLEN(grouplist) + 20];
382
383 if(function == ATTACH)
384 {
385 if(args)
386 SPRINTF(cmd, "Executive(\"%s\",{\"%s: %s %s\"});\n",
387 func,grouplist,host,args);
388 else
389 SPRINTF(cmd, "Executive(\"%s\",{\"%s: %s\"});\n",
390 func,grouplist,host);
391 }
392 else
393 SPRINTF(cmd, "Executive(\"%s\",{%s});\n",func,grouplist);
394
395 p->send(PacketIF::FOREGROUND, cmd);
396 p->sendImmediate("sync");
397
398 delete grouplist;
399 delete cmd;
400 }
401
402
403 }
404
updateAssignment()405 void ProcessGroupManager::updateAssignment()
406 {
407 DXPacketIF *p = this->app->getPacketIF();
408
409 //
410 // If the assignment hasn't been sent, don't bother detaching.
411 //
412 if(this->isDirty() OR !this->assignment OR !p)
413 {
414 this->clearAssignment();
415 this->assignment = this->createAssignment();
416 if(p)
417 this->sendAssignment(ATTACH);
418 else
419 this->setDirty();
420 return;
421 }
422
423 List *list, *oldList;
424 ListIterator li, oldLi;
425 int i;
426 boolean first, argsDirty;
427 char *host, *grouplist,*group,*oldGroup, *cmd;
428
429 //
430 // Detach groups that changed their assignment.
431 //
432 for(i = 1; i <= this->assignment->getSize(); i++)
433 {
434 host = (char*)this->assignment->getStringKey(i);
435 list = (List*)this->assignment->getDefinition(i);
436 argsDirty = this->getArgumentDirty(host);
437
438 li.setList(*list);
439 while( (group = (char*)li.getNext()) )
440 if(argsDirty OR this->getGroupHostDirty(group))
441 this->detachGroup(host,group);
442 }
443
444 Dictionary *newAss = this->createAssignment();
445
446 if(NOT newAss)
447 {
448 this->clearAssignment();
449 this->setDirty();
450 return;
451 }
452
453 //
454 // Attach groups that changed their assignment.
455 //
456 for(i = 1; i <= newAss->getSize(); i++)
457 {
458 host = (char*)newAss->getStringKey(i);
459 const char *args = this->getArgument(host);
460 argsDirty = this->getArgumentDirty(host);
461 list = (List*)newAss->getDefinition(i);
462
463 /* figure out how much, and allocate space for all group names */
464 int grouplistSize = 0;
465 li.setList(*list);
466 while( (group = (char*)li.getNext()) )
467 grouplistSize += STRLEN(group);
468 grouplist = new char[grouplistSize + 20 * list->getSize()];
469 grouplist[0] = '\0';
470
471
472 this->clearArgumentDirty(host);
473
474 if(argsDirty)
475 oldList = NULL;
476 else
477 oldList = (List*)this->assignment->findDefinition(host);
478
479 first = TRUE;
480 li.setList(*list);
481 while( (group = (char*)li.getNext()) )
482 {
483 if(oldList)
484 {
485 oldLi.setList(*oldList);
486 while( (oldGroup = (char*)oldLi.getNext()) )
487 if(EqualString(oldGroup, group)
488 AND NOT this->getGroupHostDirty(group))
489 break;
490
491 if(oldGroup)
492 continue;
493 }
494
495 this->clearGroupHostDirty(group);
496
497 if(first)
498 {
499 strcpy(grouplist, group);
500 first = FALSE;
501 }
502 else
503 {
504 strcat(grouplist, ",");
505 strcat(grouplist, group);
506 }
507 }
508 if(NOT first)
509 {
510 cmd = new char[STRLEN("exective( group attach ), ")
511 + STRLEN(host)
512 + STRLEN(args)
513 + STRLEN(grouplist) + 20];
514
515 if(args)
516 SPRINTF(cmd, "Executive(\"group attach\",{\"%s: %s %s\"});\n",
517 grouplist,host,args);
518 else
519 SPRINTF(cmd, "Executive(\"group attach\",{\"%s: %s\"});\n",
520 grouplist,host);
521
522 p->send(PacketIF::FOREGROUND, cmd);
523 p->sendImmediate("sync");
524 delete cmd;
525 }
526 delete grouplist;
527 }
528
529 this->clearAssignment();
530 this->assignment = newAss;
531 this->dirty = FALSE;
532 }
533
534
detachGroup(const char * host,const char * group)535 void ProcessGroupManager::detachGroup(const char *host, const char *group)
536 {
537 DXPacketIF *p = theDXApplication->getPacketIF();
538 if (NOT p)
539 return;
540
541 char* cmd = new char[STRLEN("Executive( group detach );") + 10
542 + STRLEN(host) + STRLEN(group)];
543
544 sprintf(cmd, "Executive(\"group detach\",{\"%s\"});\n", group);
545
546 p->send(PacketIF::FOREGROUND, cmd);
547 p->sendImmediate("sync");
548
549 delete cmd;
550
551 }
552
attachGroup(const char * host,const char * group)553 void ProcessGroupManager::attachGroup(const char *host, const char *group)
554 {
555 DXPacketIF *p = theDXApplication->getPacketIF();
556 if (NOT p)
557 return;
558
559 this->clearGroupHostDirty(group);
560
561 const char* args = this->getArgument(host);
562 char* cmd = new char[STRLEN("Executive( group attach );") + 10
563 + STRLEN(host) + STRLEN(args) + STRLEN(group)];
564
565 if(args)
566 sprintf(cmd, "Executive(\"group attach\", {\"%s: %s %s\"});\n",
567 group,host,args);
568 else
569 sprintf(cmd, "Executive(\"group attach\", {\"%s: %s\"});\n",
570 group,host);
571
572 p->send(PacketIF::FOREGROUND, cmd);
573 p->sendImmediate("sync");
574
575 delete cmd;
576 }
577
addGroupAssignment(const char * host,const char * group)578 boolean ProcessGroupManager::addGroupAssignment(const char* host,
579 const char *group)
580 {
581 if(NOT this->assignment)
582 {
583 this->assignment = this->createAssignment();
584 this->sendAssignment(ATTACH);
585 return TRUE;
586 }
587
588 List *list = (List*)this->assignment->findDefinition(host);
589 if(NOT list)
590 {
591 list = new List();
592 if(NOT this->assignment->addDefinition(host, (void*)list))
593 return FALSE;
594 }
595
596 list->appendElement((void*)DuplicateString(group));
597 this->attachGroup(host, group);
598
599 return TRUE;
600 }
601
removeGroupAssignment(const char * group)602 boolean ProcessGroupManager::removeGroupAssignment(const char *group)
603 {
604 if(NOT this->assignment)
605 return FALSE;
606
607 List *list;
608 ListIterator li;
609 int i, size = this->assignment->getSize();
610 boolean found;
611 char *name;
612
613 for(i=1; i<=size; i++)
614 {
615 list = (List*)this->assignment->getDefinition(i);
616 found = FALSE;
617 li.setList(*list);
618 while( (name = (char*)li.getNext()) )
619 if(EqualString(name, group))
620 {
621 found = TRUE;
622 break;
623 }
624
625 if(found)
626 {
627 list->removeElement((void*)name);
628 if(NOT this->isDirty())
629 this->detachGroup(this->assignment->getStringKey(i), group);
630
631 if(list->getSize() == 0)
632 this->assignment->removeDefinition((void*)list);
633
634 if(this->assignment->getSize() == 0)
635 this->clearAssignment();
636
637 return TRUE;
638 }
639 }
640
641 return FALSE;
642 }
643
printComment(FILE * f)644 boolean ProcessGroupManager::printComment(FILE *f)
645 {
646
647 int i;
648 List *list;
649 ListIterator li;
650 const char *host, *args, *group;
651
652 if(NOT this->assignment)
653 return TRUE;
654
655 if (fprintf(f, "//\n") <= 0)
656 return FALSE;
657
658 for(i=1; i <= this->assignment->getSize(); i++)
659 {
660 host = this->assignment->getStringKey(i);
661 args = this->getArgument(host);
662 list = (List*)this->assignment->getDefinition(i);
663
664 if(args)
665 {
666 if (fprintf(f, "// pgroup assignment: \"%s(%s): ", host,args) <= 0)
667 return FALSE;
668 }
669 else
670 {
671 if (fprintf(f, "// pgroup assignment: \"%s: ", host) <= 0)
672 return FALSE;
673 }
674
675 li.setList(*list);
676
677 group = (char*)li.getNext();
678 if (fprintf(f, "%s", group) <= 0)
679 return FALSE;
680
681 while( (group = (char*)li.getNext()) )
682 if (fprintf(f, ", %s", group) <= 0)
683 return FALSE;
684
685 if (fprintf(f, "\"\n") <= 0)
686 return FALSE;
687 }
688
689 return TRUE;
690 }
691
printAssignment(FILE * f)692 boolean ProcessGroupManager::printAssignment(FILE *f)
693 {
694 if (NOT this->assignment)
695 return TRUE;
696
697 List *list;
698 ListIterator li;
699 int i;
700 boolean first;
701 char *func, *host, *grouplist,*group, *cmd;
702
703 func = "group attach";
704
705 if(fprintf(f, "\n") <= 0)
706 return FALSE;
707
708 for(i = 1; i <= this->assignment->getSize(); i++)
709 {
710 host = (char*)this->assignment->getStringKey(i);
711 const char *args = this->getArgument(host);
712 list = (List*)this->assignment->getDefinition(i);
713
714 /* figure out how much, and allocate space for all group names */
715 int grouplistSize = 0;
716 li.setList(*list);
717 while( (group = (char*)li.getNext()) )
718 grouplistSize += STRLEN(group);
719 grouplist = new char[grouplistSize + 20 * list->getSize()];
720 grouplist[0] = '\0';
721
722
723 first = TRUE;
724 li.setList(*list);
725 while( (group = (char*)li.getNext()) )
726 {
727 if(first)
728 {
729 strcpy(grouplist, group);
730 first = FALSE;
731 }
732 else
733 {
734 strcat(grouplist, ",");
735 strcat(grouplist, group);
736 }
737 }
738 cmd = new char[STRLEN("exective( ), ")
739 + STRLEN(func)
740 + STRLEN(host)
741 + STRLEN(args)
742 + STRLEN(grouplist) + 20];
743
744 if(args)
745 SPRINTF(cmd, "Executive(\"%s\",{\"%s: %s %s\"});\n",
746 func,grouplist,host,args);
747 else
748 SPRINTF(cmd, "Executive(\"%s\",{\"%s: %s\"});\n",
749 func,grouplist,host);
750
751 if(fprintf(f, "%s", cmd) <= 0)
752 return FALSE;
753
754 if(fprintf(f, "$sync\n") <= 0)
755 return FALSE;
756
757 delete grouplist;
758 delete cmd;
759 }
760
761
762 return TRUE;
763 }
764
765 //
766 // Parse the group information from the cfg file.
767 //
parseComment(const char * comment,const char * filename,int lineno,Network * net)768 boolean ProcessGroupManager::parseComment(const char *comment,
769 const char *filename, int lineno,Network *net)
770 {
771
772 char *p, *c, *host, *args;
773
774 if (strncmp(comment," pgroup assignment",STRLEN(" pgroup assignment")))
775 return FALSE;
776
777 char *line = DuplicateString(comment);
778
779 p = (char *) strchr(comment,'"');
780 if (!p)
781 goto error;
782
783 // Parse the host name.
784 host = p + 1;
785 p = strchr(host,'"');
786 if (!p)
787 goto error;
788
789 p = strchr(host,':');
790 if (!p)
791 goto error;
792
793 *p = '\0';
794
795 // Parse the options.
796 args = strchr(host,'(');
797 if (args)
798 {
799 *args++ = '\0';
800 c = strchr(args,')');
801 if (!c)
802 goto error;
803 *c = '\0';
804 }
805
806 p++;
807 SkipWhiteSpace(p);
808
809 while(*p)
810 {
811 c = strchr(p, ',');
812 if(!c)
813 c = strchr(p, '"');
814
815 *c = '\0';
816
817 this->registerGroup(p, net);
818 this->assignHost(p, host);
819
820 *c = ',';
821 p = c + 1;
822
823 SkipWhiteSpace(p);
824 }
825
826 if(args)
827 this->assignArgument(host, args);
828
829 this->updateHosts();
830 this->clearAssignment();
831 this->assignment = this->createAssignment();
832
833 this->dirty = TRUE;
834
835 delete line;
836 return TRUE;
837
838 error:
839
840 ErrorMessage("Bad process group aasignment(%s, line %d).",filename,lineno);
841 delete line;
842 return FALSE;
843 }
844
removeGroup(const char * name,Network * net)845 boolean ProcessGroupManager::removeGroup(const char *name, Network *net)
846 {
847 boolean ret = this->GroupManager::removeGroup (name, net);
848 this->removeGroupAssignment(name);
849
850 return ret;
851 }
852
853