bool doCmd(const char* path, enum CmdType cmd_type, enum FileType file_type, CacheStat* pStat){ int fd = 0; DIR *dir = NULL; DIR *soft_dir = NULL; struct dirent *dp = NULL; char file_name[256]; char link_name[256]; char real_path[256]; void *pbase = NULL; char *vec = NULL; struct stat st; int in_cache = 0; int str_len = 0; int page_index; int page_count; int pagesize = getpagesize(); int time_used = 0; struct timeval begin, end; if(realpath(path, real_path) == NULL){ goto ERROR; } if(file_type == REGFILE){ fd = open(real_path, O_RDONLY); if(fd<0){ goto ERROR; } if(stat(real_path, &st)<0){ goto ERROR; } switch(cmd_type){ case CLEAR: if(posix_fadvise(fd, 0, st.st_size, POSIX_FADV_DONTNEED) != 0){ goto ERROR; } fprintf(stdout, "Release:%s\n", real_path); break; case STAT: if(st.st_size == 0) goto EMPTYFILE; pbase = mmap((void *)0, st.st_size, PROT_NONE, MAP_SHARED, fd, 0); if(pbase == MAP_FAILED){ goto ERROR; } page_count = (st.st_size+pagesize-1)/pagesize; vec = (char*)calloc(1, page_count); if(mincore(pbase, st.st_size, (unsigned char *)vec) != 0){ goto ERROR; } for(page_index=0; page_index<page_count; page_index++){ if(vec[page_index]&1 != 0){ ++in_cache; } } pStat->page_count += page_count; pStat->in_cache += in_cache; EMPTYFILE: if(pStat->is_print == true){ fprintf(stdout, "Stat:%s size:%s cached:%s\n", real_path, sizeFit(st.st_size, buf1), sizeFit(in_cache*(pagesize), buf2)); } break; case LOCK: if(st.st_size == 0){ fprintf(stderr, "Empty file %s\n", real_path); return true; } pbase = mmap((void *)0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if(pbase == MAP_FAILED){ goto ERROR; } if(mlock(pbase, st.st_size) == 0){ fprintf(stdout, "Lock %s succeed, size:%s\n", real_path, sizeFit(st.st_size, buf1)); return true; }else{ goto ERROR; } case WARM: gettimeofday(&begin, NULL); if(posix_fadvise(fd, 0, st.st_size, POSIX_FADV_WILLNEED) != 0){ goto ERROR; } gettimeofday(&end, NULL); time_used = getUsedTime(&begin, &end); fprintf(stdout, "Warmup File:%s TimeUsed:%d ms\n", real_path, time_used); break; default: fprintf(stderr, "do not support cmd type %d\n", cmd_type); goto ERROR; } close(fd); if(vec) free(vec); if(pbase) munmap(pbase, st.st_size); return true; }else if(file_type == DIRECTORY){ if((dir = opendir(real_path)) == NULL){ goto ERROR; } gettimeofday(&begin, NULL); while((dp = readdir(dir)) != NULL){ if(strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0){ memset(file_name, 0, sizeof(file_name)); strcat(file_name, real_path); strcat(file_name, "/"); strcat(file_name, dp->d_name); if(dp->d_type == DT_REG){ doCmd(file_name, cmd_type, REGFILE, pStat); }else if(dp->d_type == DT_DIR){ doCmd(file_name, cmd_type, DIRECTORY, pStat); }else if(dp->d_type == DT_LNK){ if(realpath(file_name, link_name) != NULL){ if(stat(link_name, &st)<0){ goto ERROR; } if(st.st_mode & S_IFREG){ doCmd(file_name, cmd_type, REGFILE, pStat); }else if(st.st_mode & S_IFDIR){ doCmd(file_name, cmd_type, DIRECTORY, pStat); } } }else{ fprintf(stdout, "%s:%c type unsupported!\n", dp->d_name, dp->d_type); } } } gettimeofday(&end, NULL); time_used = getUsedTime(&begin, &end); if(cmd_type == WARM){ fprintf(stdout, "Warmup Dir:%s TimeUsed:%d ms\n", real_path, time_used); } closedir(dir); return true; } ERROR: fprintf(stderr, "File:%s %s\n", real_path, strerror(errno)); if(fd) close(fd); if(dir) closedir(dir); if(vec) free(vec); if(pbase) munmap(pbase, st.st_size); return false; }
bool lock(const char* path, enum FileType file_type){ int fd = 0; DIR *dir = NULL; void *pbase = NULL; struct dirent *dp = NULL; struct stat st; char file_name[256]; if(file_type == REGFILE){ fd = open(path, O_RDONLY); if(fd<0){ goto ERROR; } if(stat(path, &st)<0){ goto ERROR; } pbase = mmap((void *)0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if(pbase == MAP_FAILED){ goto ERROR; } if(mlock(pbase, st.st_size) == 0){ fprintf(stdout, "Lock %s succeed, size:%s\n", path, sizeFit(st.st_size, buf1)); return true; }else{ goto ERROR; } }else if(file_type == DIRECTORY){ if((dir = opendir(path)) == NULL){ goto ERROR; } while((dp = readdir(dir)) != NULL){ if(strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0){ memset(file_name, 0, sizeof(file_name)); strcat(file_name, path); strcat(file_name, "/"); strcat(file_name, dp->d_name); if(dp->d_type == DT_REG){ lock(file_name, REGFILE); }else if(dp->d_type == DT_DIR){ lock(file_name, DIRECTORY); }else{ fprintf(stdout, "%s:%c type unsupported!\n", dp->d_name, dp->d_type); } } } closedir(dir); return true; } ERROR: fprintf(stderr, "File:%s %s\n", path, strerror(errno)); if(pbase) munmap(pbase, st.st_size); if(fd) close(fd); if(dir) closedir(dir); return false; }
int main(int argc, char *argv[]){ if(argc<=2){ usage(argv[0]); exit(-1); } int pagesize = getpagesize(); CmdParam cmd; CacheStat stat; memset(&stat, 0, sizeof(stat)); memset(&cmd, 0, sizeof(cmd)); stat.isPrint = true; //default true parseArgs(argc, argv, &cmd); if(cmd.isDaemon) daemonMe(); if(cmd.cmd_type == CLEAR){ clear(cmd.path, cmd.file_type); }else if(cmd.cmd_type == STAT){ normalStat(cmd.path, cmd.file_type, &stat); if(cmd.file_type == DIRECTORY){ fprintf(stdout, "\nTotal Cache of Directory:%s size:%s cached:%s\n", cmd.path, sizeFit(stat.pageCount*pagesize, buf1), sizeFit(stat.inCache*pagesize, buf2)); } }else if(cmd.cmd_type == RSTAT){ realStat(cmd.path, cmd.interval, cmd.file_type, cmd.isSuppress); }else if(cmd.cmd_type == LOCK){ lock(cmd.path, cmd.file_type); select(0, NULL, NULL, NULL, NULL); }else if(cmd.cmd_type == WARM){ warmup(cmd.path, cmd.file_type); } return 0; }
bool normalStat(const char* path, enum FileType file_type, struct CacheStat* stat_cache){ int fd = 0; int pageIndex; int pageCount; int inCache = 0; DIR *dir = NULL; void *pbase = NULL; char *vec = NULL; struct stat st; struct dirent *dp = NULL; char file_name[256]; int pagesize = getpagesize(); if(file_type == REGFILE){ fd = open(path, O_RDONLY); if(fd<0){ goto ERROR; } if(stat(path, &st)<0){ goto ERROR; } pbase = mmap((void *)0, st.st_size, PROT_NONE, MAP_SHARED, fd, 0); if(pbase == MAP_FAILED){ goto ERROR; } pageCount = (st.st_size+pagesize-1)/pagesize; vec = (char*)calloc(1, pageCount); if(mincore(pbase, st.st_size, (unsigned char *)vec) != 0){ goto ERROR; } for(pageIndex=0; pageIndex<pageCount; pageIndex++){ if(vec[pageIndex]&1 != 0){ ++inCache; } } stat_cache->pageCount += pageCount; stat_cache->inCache += inCache; if(stat_cache->isPrint == true){ fprintf(stdout, "Stat:%s size:%s cached:%s\n", path, sizeFit(st.st_size, buf1), sizeFit(inCache*(pagesize), buf2)); } free(vec); munmap(pbase, st.st_size); close(fd); return true; }else if(file_type == DIRECTORY){ if((dir = opendir(path)) == NULL){ goto ERROR; } while((dp = readdir(dir)) != NULL){ if(dp->d_name[0] != '.'){ memset(file_name, 0, sizeof(file_name)); strcat(file_name, path); strcat(file_name, "/"); strcat(file_name, dp->d_name); if(dp->d_type == DT_REG){ normalStat(file_name, REGFILE, stat_cache); }else if(dp->d_type == DT_DIR){ normalStat(file_name, DIRECTORY, stat_cache); }else{ fprintf(stdout, "%s:%c type unsupported!\n", dp->d_name, dp->d_type); } } } closedir(dir); return true; } ERROR: if(stat_cache->isPrint == true){ fprintf(stderr, "File:%s %s\n", path, strerror(errno)); } if(vec) free(vec); if(pbase) munmap(pbase, st.st_size); if(fd>0) close(fd); if(dir) closedir(dir); return false; }