/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #include "defines.h" #include "Strings.h" #include "lex.h" #include "ProcessGroupManager.h" #include "ProcessGroupAssignDialog.h" #include "Dictionary.h" #include "ListIterator.h" #include "List.h" #include "Network.h" #include "ErrorDialogManager.h" #include "EditorWindow.h" #include "DXPacketIF.h" #include "DXApplication.h" ProcessGroupManager::ProcessGroupManager(Network *net): GroupManager(net, theSymbolManager->registerSymbol(PROCESS_GROUP)) { // Would like to assert this, but in Network::Network, theDXApplication->network // isn't set yet. //ASSERT (theDXApplication->network == net); this->assignment = NULL; } ProcessGroupManager::~ProcessGroupManager() { } void ProcessGroupManager::clear() { this->GroupManager::clear(); this->clearArgument(); if(this->assignment) { this->sendAssignment(DETACH); this->clearAssignment(); } if(theDXApplication->processGroupAssignDialog) theDXApplication->processGroupAssignDialog->unmanage(); } const char* ProcessGroupManager::getGroupHost(int n) { return this->getGroupHost(this->getGroupName(n)); } const char* ProcessGroupManager::getGroupHost(const char *name) { ProcessGroupRecord *record = (ProcessGroupRecord*)this->groups.findDefinition(name); if(NOT record) return NULL; else return record->host; } const char* ProcessGroupManager::getGroupNewHost(int n) { return this->getGroupNewHost(this->getGroupName(n)); } const char* ProcessGroupManager::getGroupNewHost(const char *name) { ProcessGroupRecord *record = (ProcessGroupRecord*)this->groups.findDefinition(name); if(NOT record) return NULL; else return record->newhost; } boolean ProcessGroupManager::getGroupHostDirty(const char *name) { ProcessGroupRecord *record = (ProcessGroupRecord*)this->groups.findDefinition(name); if(NOT record) return FALSE; else return record->isDirty(); } void ProcessGroupManager::clearGroupHostDirty(const char *name) { ProcessGroupRecord *record = (ProcessGroupRecord*)this->groups.findDefinition(name); if(record) record->setDirty(FALSE); } boolean ProcessGroupManager::assignHost(int n, const char *hostname) { return assignHost(this->getGroupName(n), hostname); } boolean ProcessGroupManager::assignHost(const char *groupname, const char *hostname) { ProcessGroupRecord *record = (ProcessGroupRecord*)this->groups.findDefinition(groupname); if(NOT record) return FALSE; if(record->newhost) delete record->newhost; if(hostname) record->newhost = DuplicateString(hostname); else record->newhost = DuplicateString("localhost"); return TRUE; } void ProcessGroupManager::updateHosts() { int i; const char *group; ProcessGroupRecord *record; for(i = 1; i <= this->getGroupCount(); i++) { group = this->getGroupName(i); record = (ProcessGroupRecord*)this->groups.findDefinition(group); if (!record OR !record->newhost) continue; if (!record->host || !EqualString(record->host, record->newhost)) { if(record->host) delete record->host; record->host = DuplicateString(record->newhost); record->setDirty(TRUE); record->getNetwork()->setFileDirty(); } delete record->newhost; record->newhost = NULL; } } void ProcessGroupManager::clearNewHosts() { int i; const char *group; ProcessGroupRecord *record; for(i = 1; i <= this->getGroupCount(); i++) { group = this->getGroupName(i); record = (ProcessGroupRecord*)this->groups.findDefinition(group); if (!record OR !record->newhost) continue; delete record->newhost; record->newhost = NULL; } } const char* ProcessGroupManager::getArgument(const char *name) { ProcessHostRecord *record = (ProcessHostRecord*)this->arguments.findDefinition(name); if(record) return record->args; else return NUL(char*); } boolean ProcessGroupManager::getArgumentDirty(const char *name) { ProcessHostRecord *record = (ProcessHostRecord*)this->arguments.findDefinition(name); if(record) return record->dirty; else return FALSE; } void ProcessGroupManager::clearArgumentDirty(const char *name) { ProcessHostRecord *record = (ProcessHostRecord*)this->arguments.findDefinition(name); if(record) record->dirty = FALSE; } void ProcessGroupManager::assignArgument(const char *host,const char *args) { ProcessHostRecord *record = (ProcessHostRecord*)this->arguments.findDefinition(host); if (record) { if(record->args) delete record->args; if(args) record->args = DuplicateString(args); else record->args = NUL(char*); } else { record = new ProcessHostRecord((char*)args); this->arguments.addDefinition(host,(const void*)record); } record->dirty = TRUE; this->app->network->setFileDirty(); } // clear the argument dictionary void ProcessGroupManager::clearArgument() { ProcessHostRecord *record; while (record = (ProcessHostRecord*) this->arguments.getDefinition(1)) { this->arguments.removeDefinition((const void*)record); delete record; } } Dictionary *ProcessGroupManager::createAssignment() { int i, size = this->groups.getSize(); if(size == 0) return NULL; Dictionary *dic = new Dictionary(); List *list; for (i=1; i<=size; i++) { const char *host = this->getGroupHost(i); char *group; if(NOT host) host = "localhost"; // continue; group = DuplicateString((char*)this->groups.getStringKey(i)); if(list = (List*)dic->findDefinition(host)) { list->appendElement((void*)group); } else { list = new List(); list->appendElement((void*)group); dic->addDefinition(host, (void*)list); } } if(dic->getSize()) return dic; delete dic; return NULL; } void ProcessGroupManager::clearAssignment() { if(NOT this->assignment) return; int i, size = this->assignment->getSize(); ListIterator li; char *group; List *list; for (i=1; i<=size; i++) { list = (List*)this->assignment->getDefinition(i); li.setList(*list); while(group = (char*)li.getNext()) delete group; list->clear(); delete list; } delete this->assignment; this->assignment = NULL; } void ProcessGroupManager::sendAssignment(int function) { DXPacketIF *p = this->app->getPacketIF(); if (!p) return; this->setDirty(FALSE); if (!this->assignment) return; List *list; ListIterator li; int i; boolean first; char *func, *host, *grouplist,*group, *cmd; switch(function) { case ATTACH: func = "group attach"; this->dirty = FALSE; break; case DETACH: func = "group detach"; break; default: ASSERT(FALSE); } for(i = 1; i <= this->assignment->getSize(); i++) { host = (char*)this->assignment->getStringKey(i); this->clearArgumentDirty(host); const char *args = this->getArgument(host); list = (List*)this->assignment->getDefinition(i); /* figure out how much, and allocate space for all group names */ int grouplistSize = 0; li.setList(*list); while(group = (char*)li.getNext()) grouplistSize += STRLEN(group); grouplist = new char[grouplistSize + 20 * list->getSize()]; grouplist[0] = '\0'; first = TRUE; li.setList(*list); while(group = (char*)li.getNext()) { this->clearGroupHostDirty(group); if(first) first = FALSE; else strcat(grouplist, ","); if(function == DETACH) strcat(grouplist, "\""); strcat(grouplist, group); if(function == DETACH) strcat(grouplist, "\""); } cmd = new char[STRLEN("exective( ), ") + STRLEN(func) + STRLEN(host) + STRLEN(args) + STRLEN(grouplist) + 20]; if(function == ATTACH) { if(args) SPRINTF(cmd, "Executive(\"%s\",{\"%s: %s %s\"});\n", func,grouplist,host,args); else SPRINTF(cmd, "Executive(\"%s\",{\"%s: %s\"});\n", func,grouplist,host); } else SPRINTF(cmd, "Executive(\"%s\",{%s});\n",func,grouplist); p->send(PacketIF::FOREGROUND, cmd); p->sendImmediate("sync"); delete grouplist; delete cmd; } } void ProcessGroupManager::updateAssignment() { DXPacketIF *p = this->app->getPacketIF(); // // If the assignment hasn't been sent, don't bother detaching. // if(this->isDirty() OR !this->assignment OR !p) { this->clearAssignment(); this->assignment = this->createAssignment(); if(p) this->sendAssignment(ATTACH); else this->setDirty(); return; } List *list, *oldList; ListIterator li, oldLi; int i; boolean first, argsDirty; char *host, *oldHost, *grouplist,*group,*oldGroup, *cmd; // // Detach groups that changed their assignment. // for(i = 1; i <= this->assignment->getSize(); i++) { host = (char*)this->assignment->getStringKey(i); list = (List*)this->assignment->getDefinition(i); argsDirty = this->getArgumentDirty(host); li.setList(*list); while(group = (char*)li.getNext()) if(argsDirty OR this->getGroupHostDirty(group)) this->detachGroup(host,group); } Dictionary *newAss = this->createAssignment(); if(NOT newAss) { this->clearAssignment(); this->setDirty(); return; } // // Attach groups that changed their assignment. // for(i = 1; i <= newAss->getSize(); i++) { host = (char*)newAss->getStringKey(i); const char *args = this->getArgument(host); argsDirty = this->getArgumentDirty(host); list = (List*)newAss->getDefinition(i); /* figure out how much, and allocate space for all group names */ int grouplistSize = 0; li.setList(*list); while(group = (char*)li.getNext()) grouplistSize += STRLEN(group); grouplist = new char[grouplistSize + 20 * list->getSize()]; grouplist[0] = '\0'; this->clearArgumentDirty(host); if(argsDirty) oldList = NULL; else oldList = (List*)this->assignment->findDefinition(host); first = TRUE; li.setList(*list); while(group = (char*)li.getNext()) { if(oldList) { oldLi.setList(*oldList); while(oldGroup = (char*)oldLi.getNext()) if(EqualString(oldGroup, group) AND NOT this->getGroupHostDirty(group)) break; if(oldGroup) continue; } this->clearGroupHostDirty(group); if(first) { strcpy(grouplist, group); first = FALSE; } else { strcat(grouplist, ","); strcat(grouplist, group); } } if(NOT first) { cmd = new char[STRLEN("exective( group attach ), ") + STRLEN(host) + STRLEN(args) + STRLEN(grouplist) + 20]; if(args) SPRINTF(cmd, "Executive(\"group attach\",{\"%s: %s %s\"});\n", grouplist,host,args); else SPRINTF(cmd, "Executive(\"group attach\",{\"%s: %s\"});\n", grouplist,host); p->send(PacketIF::FOREGROUND, cmd); p->sendImmediate("sync"); delete cmd; } delete grouplist; } this->clearAssignment(); this->assignment = newAss; this->dirty = FALSE; } void ProcessGroupManager::detachGroup(const char *host, const char *group) { DXPacketIF *p = theDXApplication->getPacketIF(); if (NOT p) return; char* cmd = new char[STRLEN("Executive( group detach );") + 10 + STRLEN(host) + STRLEN(group)]; sprintf(cmd, "Executive(\"group detach\",{\"%s\"});\n", group); p->send(PacketIF::FOREGROUND, cmd); p->sendImmediate("sync"); delete cmd; } void ProcessGroupManager::attachGroup(const char *host, const char *group) { DXPacketIF *p = theDXApplication->getPacketIF(); if (NOT p) return; this->clearGroupHostDirty(group); const char* args = this->getArgument(host); char* cmd = new char[STRLEN("Executive( group attach );") + 10 + STRLEN(host) + STRLEN(args) + STRLEN(group)]; if(args) sprintf(cmd, "Executive(\"group attach\", {\"%s: %s %s\"});\n", group,host,args); else sprintf(cmd, "Executive(\"group attach\", {\"%s: %s\"});\n", group,host); p->send(PacketIF::FOREGROUND, cmd); p->sendImmediate("sync"); delete cmd; } boolean ProcessGroupManager::addGroupAssignment(const char* host, const char *group) { if(NOT this->assignment) { this->assignment = this->createAssignment(); this->sendAssignment(ATTACH); return TRUE; } List *list = (List*)this->assignment->findDefinition(host); if(NOT list) { list = new List(); if(NOT this->assignment->addDefinition(host, (void*)list)) return FALSE; } list->appendElement((void*)DuplicateString(group)); this->attachGroup(host, group); return TRUE; } boolean ProcessGroupManager::removeGroupAssignment(const char *group) { if(NOT this->assignment) return FALSE; List *list; ListIterator li; int i, size = this->assignment->getSize(); boolean found; char *name; for(i=1; i<=size; i++) { list = (List*)this->assignment->getDefinition(i); found = FALSE; li.setList(*list); while(name = (char*)li.getNext()) if(EqualString(name, group)) { found = TRUE; break; } if(found) { list->removeElement((void*)name); if(NOT this->isDirty()) this->detachGroup(this->assignment->getStringKey(i), group); if(list->getSize() == 0) this->assignment->removeDefinition((void*)list); if(this->assignment->getSize() == 0) this->clearAssignment(); return TRUE; } } return FALSE; } boolean ProcessGroupManager::printComment(FILE *f) { int i, inst; List *list; ListIterator li; const char *host, *args, *group; if(NOT this->assignment) return TRUE; if (fprintf(f, "//\n") <= 0) return FALSE; for(i=1; i <= this->assignment->getSize(); i++) { host = this->assignment->getStringKey(i); args = this->getArgument(host); list = (List*)this->assignment->getDefinition(i); if(args) { if (fprintf(f, "// pgroup assignment: \"%s(%s): ", host,args) <= 0) return FALSE; } else { if (fprintf(f, "// pgroup assignment: \"%s: ", host) <= 0) return FALSE; } li.setList(*list); group = (char*)li.getNext(); if (fprintf(f, "%s", group) <= 0) return FALSE; while(group = (char*)li.getNext()) if (fprintf(f, ", %s", group) <= 0) return FALSE; if (fprintf(f, "\"\n") <= 0) return FALSE; } return TRUE; } boolean ProcessGroupManager::printAssignment(FILE *f) { if (NOT this->assignment) return TRUE; List *list; ListIterator li; int i; boolean first; char *func, *host, *grouplist,*group, *cmd; func = "group attach"; if(fprintf(f, "\n") <= 0) return FALSE; for(i = 1; i <= this->assignment->getSize(); i++) { host = (char*)this->assignment->getStringKey(i); const char *args = this->getArgument(host); list = (List*)this->assignment->getDefinition(i); /* figure out how much, and allocate space for all group names */ int grouplistSize = 0; li.setList(*list); while(group = (char*)li.getNext()) grouplistSize += STRLEN(group); grouplist = new char[grouplistSize + 20 * list->getSize()]; grouplist[0] = '\0'; first = TRUE; li.setList(*list); while(group = (char*)li.getNext()) { if(first) { strcpy(grouplist, group); first = FALSE; } else { strcat(grouplist, ","); strcat(grouplist, group); } } cmd = new char[STRLEN("exective( ), ") + STRLEN(func) + STRLEN(host) + STRLEN(args) + STRLEN(grouplist) + 20]; if(args) SPRINTF(cmd, "Executive(\"%s\",{\"%s: %s %s\"});\n", func,grouplist,host,args); else SPRINTF(cmd, "Executive(\"%s\",{\"%s: %s\"});\n", func,grouplist,host); if(fprintf(f, "%s", cmd) <= 0) return FALSE; if(fprintf(f, "$sync\n") <= 0) return FALSE; delete grouplist; delete cmd; } return TRUE; } // // Parse the group information from the cfg file. // boolean ProcessGroupManager::parseComment(const char *comment, const char *filename, int lineno,Network *net) { char *p, *c, *host, *args; int inst; if (strncmp(comment," pgroup assignment",STRLEN(" pgroup assignment"))) return FALSE; char *line = DuplicateString(comment); p = strchr(comment,'"'); if (!p) goto error; // Parse the host name. host = p + 1; p = strchr(host,'"'); if (!p) goto error; p = strchr(host,':'); if (!p) goto error; *p = '\0'; // Parse the options. args = strchr(host,'('); if (args) { *args++ = '\0'; c = strchr(args,')'); if (!c) goto error; *c = '\0'; } p++; SkipWhiteSpace(p); while(*p) { c = strchr(p, ','); if(!c) c = strchr(p, '"'); *c = '\0'; this->registerGroup(p, net); this->assignHost(p, host); *c = ','; p = c + 1; SkipWhiteSpace(p); } if(args) this->assignArgument(host, args); this->updateHosts(); this->clearAssignment(); this->assignment = this->createAssignment(); this->dirty = TRUE; delete line; return TRUE; error: ErrorMessage("Bad process group aasignment(%s, line %d).",filename,lineno); delete line; return FALSE; } boolean ProcessGroupManager::removeGroup(const char *name, Network *net) { boolean ret = this->GroupManager::removeGroup (name, net); this->removeGroupAssignment(name); return ret; }