📄 checkpoint.c
字号:
{ /* Keep list in order of insertion */ if (group->tail == NULL) { group->tail = group->hint = entry->prev = entry->next = entry; } else { entry->prev = group->tail; entry->next = group->tail->next; group->tail->next->prev = entry; group->tail->next = entry; group->tail = entry; }}static voidFreeEntry(CptEntry *entry){ free(entry->name); free(entry);}/* Finds entry in list, and removes it if found before returning it *//* If the entry found is optional, keep looking to see if a value loaded from the checkpoint file is also present in the list */static CptEntry *FindEntryInList(CptGroup *group, char *name, int i1, int i2){ if (group->tail == NULL) { return NULL; } else { CptEntry *entry = group->hint; CptEntry *optentry = NULL; /* Circularly linked list; start at the hint pointer and make one pass through */ do { if (!strcmp(entry->name,name) && (entry->i1 == i1) && (entry->i2 == i2)) { if (entry->prev == entry) { group->tail = NULL; } else { group->hint = entry->next; entry->prev->next = entry->next; entry->next->prev = entry->prev; if (group->tail == entry) group->tail = entry->prev; } if (entry->optional) /* If this entry is optional, keep looking for an entry from the file */ optentry = entry; else /* Otherwise, go ahead and return this entry */ return entry; } entry = entry->next; } while (entry != group->hint); /* If we get here, no non-optional entry was found. */ return optentry; }}static intLogCheckpointCB(CptDescriptor *cptd){ if (cptd->mode == CPT_SAVE) { CptGroup *group; int g = 0; while ((group = IterGroup(ITER_LOG)) != NULL) { SaveLine(cptd->group, "CheckpointFile", g, NO_INDEX, group->tag); g++; } } return 0;}static voidSaveLine(CptGroup *group, char *name, int i1, int i2, char *valstring){ if (group->stream == NULL) { CPUPrint("CPT: Checkpoint file %s not opened for writing\n",group->tag); return; } if (i1 == NO_INDEX) { fprintf(group->stream, lineFormat[0], name, valstring); } else if (i2 == NO_INDEX) { fprintf(group->stream, lineFormat[1], name, i1, valstring); } else { fprintf(group->stream, lineFormat[2], name, i1, i2, valstring); } fprintf(group->stream, "\n");}static intRestoreLine(CptGroup *group, char *name, int *i1, int *i2, char *valstring){ char line[MAX_LENGTH]; int status = 0; if (group->stream == NULL) { CPUPrint("CPT: Checkpoint file %s not opened for reading\n",group->tag); return -2; } do status = GetLineFromFile(group->stream, line, MAX_LENGTH); while ((status > 0) && (line[0] == '#')); /* Ignore comment lines */ ASSERT( strlen(line)< MAX_LENGTH); if (status > 0) { if (sscanf(line, lineFormat[2], name, i1, i2, valstring) == 4) { /* Nothing to do -- all arguments in place */ } else if (sscanf(line, lineFormat[1], name, i1, valstring) == 3) { *i2 = NO_INDEX; } else if (sscanf(line, lineFormat[0], name, valstring) == 2) { *i1 = NO_INDEX; *i2 = NO_INDEX; } else { status = -2; } } return status;}static voidSaveBlock(CptGroup *group, caddr_t addr, int size){ if (group->binfd < 0) { OpenBinFile(CPT_SAVE, group); } write(group->binfd, addr, size); group->binpos += size;}static intRestoreBlock(CptGroup *group, caddr_t addr, int pos, int size){ int cnt; if (group->binfd < 0) { OpenBinFile(CPT_RESTORE, group); } if(outputFD >= 0) { pid_t retPid; int waitState; CPUPrint("CPT: Waiting for death of child\n"); while (1) { retPid = wait(&waitState); if (retPid != compressPID) { continue; } if (WIFSTOPPED(waitState)) { CPUWarning("CPT: decompress process stopped by signal %d\nWaiting...\n", WSTOPSIG(waitState)); continue; } if (WIFEXITED(waitState) && (WEXITSTATUS(waitState)==0)) { break; } CPUWarning("CPT: Decompress of checkpoint file failed\n"); if (WIFEXITED(waitState)) { CPUWarning("CPT: Exit status of %d\n", WEXITSTATUS(waitState)); } else { CPUWarning("CPT: Terminate by signal %d\n", WTERMSIG(waitState)); } group->failure = TRUE; return -1; } CloseBinFile(group); return 0; } if (group->binpos != pos) { /* Test for group->failure so this message is only given once */ if (!group->failure) { CPUWarning("CPT: The binary file for %s was restored out of order\n", group->tag); group->failure = TRUE; return -1; } } while (size > 0) { cnt = read(group->binfd, addr, size); if (cnt <= 0) { /* Test for group->failure so this message is only given once */ if (!group->failure) { perror("CPT: RestoreBlock"); CPUWarning("CPT: Error in reading the binary file for %s addr=%llx size=%llx \n", group->tag, (uint64)addr, (uint64)size); } group->failure = TRUE; return -1; } group->binpos += cnt; addr += cnt; size -= cnt; } return 0;}/* Read checkpoint file, searching for the given entry and returning its value. Any intervening values are placed on the entry list for the group */static CptEntry *FindEntryInFile(CptGroup *group, char *name, int i1, int i2){ while (TRUE) { char fname[MAX_LENGTH]; char fvalstr[MAX_LENGTH]; int fi1, fi2; int status = RestoreLine(group, fname, &fi1, &fi2, fvalstr); if (status <= 0) return NULL; else { CptEntry *entry; cptlong ival; cptlong pval; char buf[MAX_LENGTH]; if (ParseInteger(fvalstr, &ival)) { entry = NewEntry(fname, fi1, fi2, CPT_INTEGER); entry->intval = ival; } else if (ParseBlock(fvalstr, &pval, &ival)) { entry = NewEntry(fname, fi1, fi2, CPT_BLOCK); entry->ptrval = pval; entry->intval = ival; } else if (ParseString(fvalstr, buf)) { ASSERT( strlen(buf) < MAX_LENGTH); entry = NewEntry(fname, fi1, fi2, CPT_STRING); entry->ptrval = (int64) PTR_TO_UINT64(SaveString(buf)); } else { CPUWarning("CPT: Could not parse value %s\n", fvalstr); continue; } if (!strcmp(name, fname) && (i1 == fi1) && (i2 == fi2)) { /* Check to see if the entry is also resident in the in-memory list */ CptEntry *listEntry = FindEntryInList(group, name, i1, i2); if (listEntry != NULL) { if (listEntry->optional == FALSE) CPUWarning("CPT: Entry %s [%d,%d] appears multiple times in file\n",name,i1,i2); } return entry; } else AddEntry(group, entry); } } return NULL;}static FILE *OpenCompressedFile(CptMode mode, CptCompression c, FILE *fp){ int pfd[2]; int ffd = fileno(fp); if (pipe(pfd) < 0) { perror("pipe"); CPUWarning("CPT: Cannot create pipe to compress file.\n"); } compressPID = fork(); if (compressPID == (pid_t) -1) { perror("fork"); CPUWarning("CPT: Cannot fork compress process.\n"); } else if (compressPID == 0) { /* Child process */ if (mode == CPT_SAVE) { SIM_DEBUG(('g', "CPT: Using %s to compress file\n", compression[c].compress)); close(pfd[1]); dup2(pfd[0], 0); dup2(ffd, 1); execlp(compression[c].compress, compression[c].compress, (char *) 0); } else { SIM_DEBUG(('g', "CPT: Using %s to decompress file\n" ,compression[c].decompress)); close(pfd[0]); if (outputFD >= 0) { dup2(outputFD, 1); } else { dup2(pfd[1], 1); } dup2(ffd, 0); execlp(compression[c].decompress, compression[c].decompress, (char *) 0); } /* Should not return */ CPUError("execlp of compress/decompress returned\n"); } else { /* Parent process */ if (mode == CPT_SAVE) { close(pfd[0]); return fdopen(pfd[1], "w"); } else { close(pfd[1]); return fdopen(pfd[0], "r"); } } return NULL;}static CptCompressionGetCompression(char *filename, char *pathname){ CptCompression c; for (c = NO_COMPRESSION; c < NUM_COMPRESS_TYPES; c++) { bool found; if (cptRemote) { sprintf(pathname, "%s%s", filename, compression[c].extender); found = Simrmt_access(pathname); } else { sprintf(pathname, "%s%s", filename, compression[c].extender); found = (access(pathname, R_OK) == 0); } if (found) break; } return c;}static FILE *OpenFile(CptMode mode, char *filename, CptCompression compress) { FILE *fp; char pathname[MAX_PATH_LENGTH]; if (mode == CPT_RESTORE) { compress = GetCompression(filename, pathname); if (compress == NUM_COMPRESS_TYPES) { CPUError("Could not find checkpoint file %s -- " "all known extensions tried\n", filename); return NULL; } if (cptRemote) { CPUPrint("CPT: Reading %s from remote access server\n", pathname); fp = Simrmt_fopen(pathname); } else { SIM_DEBUG(('g', "CPT: Reading from file %s....\n", pathname)); fp = fopen(pathname, "r"); } } else { if (cptRemote) { CPUWarning("CPT: Not allowed to write checkpoint to remote access server\n"); return NULL; } else { sprintf(pathname, "%s/%s%s", cptSaveDir, filename, compression[compress].extender); fp = fopen(pathname, "w"); SIM_DEBUG(('g', "CPT: Writing to file %s....\n", pathname)); } } if (fp == NULL) { CPUWarning("CPT: Couldn't open checkpoint file %s.\n", filename); return fp; } else if ((compress == NO_COMPRESSION) && (outputFD < 0)) { return fp; } else { FILE *cfp = OpenCompressedFile(mode, compress, fp); fclose(fp); return cfp; }}static voidOpenBinFile(CptMode mode, CptGroup *group){ char filename[MAX_PATH_LENGTH]; /* Do not open if file is already open -- this is necessary to make Simcpt_CheckpointRmtDisk work on the rmtaccess servers */ if (group->binfd >= 0) return; sprintf(filename, "%s.%s.bin", cptName, group->tag); group->binfd = fileno(OpenFile(mode, filename, group->compressBin[mode])); group->binpos = 0;}static voidOpenCptFile(CptMode mode, CptGroup *group){ char filename[MAX_PATH_LENGTH]; int length; /* Do not open if file is already open -- this is necessary to make Simcpt_CheckpointRmtDisk work on the rmtaccess servers */ if (group->stream != NULL) return; /* Strip the ending period off of the checkpoint name if it's there. */ length = strlen(cptName); if (cptName[length-1] == '.') { cptName[length-1] = '\000'; } sprintf(filename, "%s.%s", cptName, group->tag); group->stream = OpenFile(mode, filename, group->compressCpt[mode]);}static voidCloseBinFile(CptGroup *group){ close(group->binfd); group->binfd = -1; group->binpos = 0;}static voidCloseCptFile(CptGroup *group)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -