LBMStreamDialogInfo::~LBMStreamDialogInfo(void) { resetStreams(); }
/// user function:add a new query to a pipeline of filters. Called by user manager runs this. /// \param layout System Layout. /// \param work Buffer with a Unit of Work (UoW) /// \param workSize Unit of Work Size (UoW) /// \return Zero on success, -1 on error. int appendWork(Layout *layout, void *work, int workSize) { #ifdef NO_BARRIER // sends work for each filter pvm_initsend(PvmDataRaw); // First tell that is a mensage of WORK int msgType = MSGT_WORK; pvm_pkint(&msgType, 1, 1); //then attach the work to it pvm_pkbyte((char *)work, workSize, 1); // for each filter, send his work for(i = 0; i < layout->numFilters; i++) { FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement); // sends work to all filters of this set pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0); } #else int i; int totalEows = 0, numEowsReceived; #ifdef ATTACH int totalAttachedFilters = 0; #endif int reconf = 0 /** should we reconfigure? */, remainingReconfs = 0; //how many times should we try? #ifdef VOID_INST #ifdef BMI_FT char instDir[MAX_IDIR_LENGTH]; sprintf(instDir, "%s/", INST_DIR); for (i=0; i < layout->numFilters-1; i++) { if (strlen(instDir) >= (MAX_IDIR_LENGTH - 3)) { //dont want to overflow this array fprintf(stderr, "%s %d: warning, instrumentation directory name too big, truncating to %s\n", __FILE__, __LINE__, instDir); break; } sprintf(instDir, "%s%d-", instDir, layout->filters[i]->filterPlacement.numInstances); } sprintf(instDir, "%s%d", instDir, layout->filters[layout->numFilters-1]->filterPlacement.numInstances); char managerLogFile[MAX_IDIR_LENGTH+20]; sprintf(managerLogFile, "%s/manager.time", instDir); FILE *fp = fopen(managerLogFile, "w"); struct timeval tv; struct timezone tz; //not used //get the time gettimeofday(&tv, &tz); if(fp != NULL) fprintf(fp, "1 %ld %ld\n", tv.tv_sec, tv.tv_usec); #endif #endif //before sending, we check if we received any filter error int bufid = pvm_probe(-1, MSGT_FERROR); if (bufid != 0) { int bytes, tag, tid; char *msg; pvm_bufinfo(bufid, &bytes, &tag, &tid); msg = (char*)malloc(bytes+1); pvm_recv(tid, MSGT_FERROR); pvm_upkbyte(msg, bytes, 1); msg[bytes] = '\0'; fprintf(stderr, "Manager.c: Error, received death notification\n"); fprintf(stderr, "Manager.c: %s\n", msg); free(msg); killAllFilters(layout); exit(-1); } printf("Manager.c: starting work...\n"); // number of EOWs we expect to receive for(i = 0; i < layout->numFilters; i++) { totalEows += layout->filters[i]->filterPlacement.numInstances; #ifdef ATTACH if(layout->filters[i]->attached) { totalAttachedFilters += layout->filters[i]->filterPlacement.numInstances; } // TODO:TOSCO::: if(layout->filters[i]->attach) return 0; #endif } //we stay in this loop while we have to reconfigure //usually, this will be only one time, unless a we get some reconf message do { // sends work for each filter pvm_initsend(PvmDataRaw); int msgType; #ifdef VOID_FT if(!reconf) { #endif // First tell that is a mensage of WORK msgType = MSGT_WORK; #ifdef VOID_FT } else { // one fault has occurred msgType = MSGT_FT; } #endif pvm_pkint(&msgType, 1, 1); //then attach the work to it pvm_pkbyte((char *)work, workSize, 1); reconf = 0; //we are optimistic, always expect to not reconfigure // for each filter, send his work for(i = 0; i < layout->numFilters; i++) { FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement); // sends work to all filters of this set pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0); } /* TaskIdList *finalTaskIdList = NULL, *currentTaskIdList; int filtersThatUseTasks = 0; // Manager receives filter's terminated tasks list for(i = 0; i < layout->numFilters; i++) { FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement); #ifdef ATTACH // if this filter is of the attached // type i dont need worry about use Task // if(layout->filters[i]->attached)continue; #endif for(j = 0; j < pFilterP->numInstances; j++) { int instanceUseTasks = -1; // Get is this filter use tasks pvm_recv(pFilterP->tids[j], 0); pvm_upkint(&instanceUseTasks, 1, 1); layout->filters[i]->useTasks = instanceUseTasks; #ifdef VOID_FT if (instanceUseTasks) { currentTaskIdList = (TaskIdList *)unpackTaskIdList(); // Para fazer intersecao, gerente ordenar? as listas de tarefas recebidas e utilizar? a fun??o meet() do CrazyMiner/ID3. qsort(currentTaskIdList->vetor, currentTaskIdList->size, sizeof(int), compareTaskId); if(finalTaskIdList == NULL) { finalTaskIdList = currentTaskIdList; } else { // Manager makes the intersection of all finished tasks lists finalTaskIdList = taskIdListIntersection(finalTaskIdList, currentTaskIdList); taskIdListDestroy(currentTaskIdList); } } #endif } // for if (layout->filters[i]->useTasks) filtersThatUseTasks++; } // Gerente devolve resultado das intersecoes para todas as instancias de todos os filtros. for(i = 0; i < layout->numFilters; i++) { FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement); #ifdef ATTACH // if this filter is of the attached // type i dont need worry about use Task //TODO if(layout->filters[i]->attached)continue; #endif int needForwardTaskMessages = 1; if (filtersThatUseTasks < 2) needForwardTaskMessages = 0; #ifdef VOID_FT if (layout->filters[i]->useTasks) { // Send if they should forward task messages // and pigback :-) the final task id list pvm_initsend(PvmDataDefault); pvm_pkint(&needForwardTaskMessages, 1, 1); packTaskIdList(finalTaskIdList); pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0); } else { #endif // Only send if they should forward task messages pvm_initsend(PvmDataDefault); pvm_pkint(&needForwardTaskMessages, 1, 1); pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0); #ifdef VOID_FT } #endif } taskIdListDestroy(finalTaskIdList); */ //now we receive the EOWs numEowsReceived = 0; //now we expect to receive EOW or errors while(numEowsReceived < totalEows) { //we are open to receive anything from anyone here //all messages to the manager should be tagged, so we now their type int szMsg = -1; int inst_tid = -1; int msgTag = -1; int bufid = pvm_recv(-1, -1); pvm_bufinfo(bufid, &szMsg, &msgTag, &inst_tid); switch (msgTag) { case (MSGT_EOW): { //received EOW, expect this usually int instance = -1; FilterSpec *pFilter = NULL; getFilterByTid(layout, inst_tid, &pFilter, &instance); if ((pFilter != NULL) && (instance != -1)) { printf("Manager.c: EOW received from %s, instance %d\n", pFilter->name, instance); } else { fprintf(stderr, "Manager.c: unknown EOW received! Shouldnt get here!\n"); } numEowsReceived++; break; } case (MSGT_AEXIT): case (MSGT_FERROR): { //someone called dsExit or system error at the filter side //common cause for this are library not found, wrong initscritpt etc char *message = (char*)malloc(sizeof(char)*szMsg+1); pvm_upkbyte(message, szMsg, 1); message[szMsg] = '\0'; //the filter and the instance FilterSpec *fp = NULL; int instance = -1; getFilterByTid(layout, inst_tid, &fp, &instance); if (msgTag == MSGT_AEXIT) { printf("Manager.c: Filter %s, instance %d(tid %x) called dsExit: %s\n", fp->name, instance, inst_tid, message); } else { printf("Manager.c: Filter %s error, instance %d(tid %x) called exit: %s\n", fp->name, instance, inst_tid, message); } free(message); // kill all instances killAllFilters(layout); exit(-1); break; } //task exited or host crashed case (MSGT_TEXIT): case (MSGT_HDEL): { //we only reconfigure a fixed number of times if (remainingReconfs <= 0) { //max number of reconfigurations reached... aborting fprintf(stderr, "Manager.c: max reconfigurations reached, aborting...\n"); fflush(stderr); fprintf(stdout, "Manager.c: max reconfigurations reached, aborting...\n"); fflush(stdout); reconf = 0; // kill all instances which might be alive killAllFilters(layout); exit(-1);; } #ifdef BMI_FT gettimeofday(&tv, &tz); fprintf(fp, "2 %ld %ld\n", tv.tv_sec, tv.tv_usec); #endif remainingReconfs--; reconf = 1; // In case of pvm notification, inst_tid will be t80000000 int notifiesRecv = 1; // We are receiving the first death notification int deadFilterTid = -1; FilterSpec *pFilter = NULL; int instanceDead = -1; // Get the tid and name of the dead filter int info = pvm_upkint(&deadFilterTid, 1, 1); if (info < 0) pvm_perror("Manager.c: error calling pvm_upkint"); //discover which filter died getFilterByTid(layout, deadFilterTid, &pFilter, &instanceDead); if((pFilter != NULL) && (instanceDead != -1)) { if (msgTag == MSGT_TEXIT) { fprintf(stderr, "Manager.c: filter %s: instance %d (tid t%x) of %d is dead!!!\n", pFilter->name, instanceDead, deadFilterTid, pFilter->filterPlacement.numInstances); } else { fprintf(stderr, "Manager.c: filter %s: instance %d (tid t%x) of %d machine's crashed!!!\n", pFilter->name, instanceDead, deadFilterTid, pFilter->filterPlacement.numInstances); } } printf("Manager.c: starting reconfiguration\n"); // kill all filters in the pipeline killAllFilters(layout); if (msgTag == MSGT_HDEL) { //int his case, host died, so we must change layout replaceCrashedHost(layout, pFilter, instanceDead); } #ifdef ATTACH if (pFilter->attached) { // In this case, all filters that were killed have to notify // their dead. notifiesRecv = 0; } #endif //Flush the streams //receive all messages which are about to arrive till we get the death notification //pvm order should garantee this #ifdef ATTACH while (notifiesRecv < (totalEows - totalAttachedFilters)) { #else while (notifiesRecv < totalEows) { #endif int newMsgTag = -1; bufid = pvm_recv(-1, MSGT_TEXIT); info = pvm_bufinfo(bufid, NULL, &newMsgTag, &inst_tid); info = pvm_upkint(&deadFilterTid, 1, 1); if (info < 0) pvm_perror("Manager.c: error calling pvm_upkint"); fprintf(stderr, "Manager.c: WARNING: received notification (tag %d) about pvm tid t%x death\n", newMsgTag, deadFilterTid); notifiesRecv++; } #ifdef ATTACH if(pFilter->attached) { notifiesRecv = 1; } else { notifiesRecv = 0; } // Receive all EOW messages from the attached filters. while(notifiesRecv < totalAttachedFilters) { int newMsgTag = -1; bufid = pvm_recv(-1, MSGT_EOW); info = pvm_bufinfo(bufid, NULL, &newMsgTag, &inst_tid); if (info < 0) pvm_perror("Manager.c: error calling pvm_upkint"); fprintf(stderr, "Manager.c: WARNING: received EOW (tag %d) from pvm tid t%x\n", newMsgTag, inst_tid); notifiesRecv++; } #endif // probes for remaining machine crash notifications while (pvm_probe(-1, MSGT_HDEL) > 0) { int newMsgTag = -1; bufid = pvm_recv(-1, MSGT_HDEL); info = pvm_bufinfo(bufid, NULL, &newMsgTag, &inst_tid); info = pvm_upkint(&deadFilterTid, 1, 1); if (info < 0) pvm_perror("Manager.c: error calling pvm_upkint"); fprintf(stderr, "Manager.c: WARNING: received notification (tag %d) about pvm tid t%x machine's crash\n", newMsgTag, deadFilterTid); // Replace the died host FilterSpec *pCrashedFilter = NULL; int crashedInstance = -1; getFilterByTid(layout, deadFilterTid, &pCrashedFilter, &crashedInstance); replaceCrashedHost(layout, pCrashedFilter, crashedInstance); } #ifdef BMI_FT updateAllFiltersFaultStatus(layout, FAULT_OTHER_FILTER_INST); pFilter->faultStatus = instanceDead; #endif //spawn all filters again spawnAllFilter(layout); #ifdef ATTACH // Verifies if the dead filter is an attached. If yes, spawn it. if(pFilter->attached == 1) { spawnOneAttachedInstance(layout, pFilter, instanceDead); } #endif resetStreams(layout); //resend the data sendFiltersData(layout); //start all over again numEowsReceived = 0; #ifdef BMI_FT gettimeofday(&tv, &tz); fprintf(fp, "3 %ld %ld\n", tv.tv_sec, tv.tv_usec); #endif break; } #ifdef VOID_TERM // One filter instance detected local termination case (MSGT_LOCALTERM): { int localTermTag; // filter instance local termination tag pvm_upkint(&localTermTag, 1, 1); verifyGlobalTermination(inst_tid, localTermTag); break; } #endif default: { fprintf(stderr, "Manager.c: error receiving EOW, unknown tag!!!\n"); } } //end switch message tag if((msgTag == MSGT_TEXIT) || (msgTag == MSGT_HDEL)) { // work should be sent again break; } } //end receiving eows } while(reconf == 1); //leave this loop if we will not reconfigure #ifdef BMI_FT gettimeofday(&tv, &tz); fprintf(fp, "4 %ld %ld\n", tv.tv_sec, tv.tv_usec); #endif printf("Manager.c: Work ended\n\n"); return 0; #endif } /// Finalize a Void pipeline. Only manager runs this. int finalizeDs(Layout *layout) { #ifdef NO_BARRIER #else int i; // Envia eof para todos os filtros // Primeiro envia se eh work (WORK) ou EOF (END_OF_FILTER) pvm_initsend(PvmDataRaw); int tipo_msg = MSGT_EOF; pvm_pkint(&tipo_msg, 1, 1); //sends the EOF message for all instances of the filter for(i = 0; i < layout->numFilters; i++) { FilterPlacement *pFilterP = &(layout->filters[i]->filterPlacement); #ifdef ATTACH if(layout->filters[i]->attach) continue;// this filter cant not receive a EOF because // it needs still runnig #endif pvm_mcast(pFilterP->tids, pFilterP->numInstances, 0); } destroyLayout(layout); pvm_exit(); return 0; #endif }