int moveToPreloadedDir (const char *path, const char *iRODSPath) { int status; char preloadCachePath[MAX_NAME_LEN]; off_t cacheSize; if (path == NULL || iRODSPath == NULL) { rodsLog (LOG_DEBUG, "moveToPreloadedDir: input path or iRODSPath is NULL"); return (SYS_INTERNAL_NULL_INPUT_ERR); } status = _getCachePath(iRODSPath, preloadCachePath); if(status < 0) { rodsLog (LOG_DEBUG, "moveToPreloadedDir: failed to get cache path - %s", path); return status; } // make dir makeParentDirs(preloadCachePath); // move the file status = rename(path, preloadCachePath); if(status < 0) { rodsLog (LOG_DEBUG, "moveToPreloadedDir: rename error : %d", status); return status; } // check whether preload cache exceeds limit if(PreloadConfig.cacheMaxSize > 0) { cacheSize = getFileSizeRecursive(PreloadConfig.cachePath); if(cacheSize > (off_t)PreloadConfig.cacheMaxSize) { // evict? status = _evictOldCache(cacheSize - (off_t)PreloadConfig.cacheMaxSize); if(status < 0) { rodsLog (LOG_DEBUG, "moveToPreloadedDir: failed to evict old cache"); return status; } } } return (0); }
off_t getFileSizeRecursive(const char *path) { off_t accumulatedSize = 0; DIR *dir = NULL; char filepath[MAX_NAME_LEN]; struct dirent *entry; struct stat statbuf; off_t localSize; dir = opendir(path); if (dir != NULL) { while ((entry = readdir(dir)) != NULL) { if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { continue; } snprintf(filepath, MAX_NAME_LEN, "%s/%s", path, entry->d_name); if (!stat(filepath, &statbuf)) { // has entry if (S_ISDIR(statbuf.st_mode)) { // directory // call myself recursively localSize = getFileSizeRecursive(filepath); if(localSize > 0) { accumulatedSize += localSize; } } else { // file localSize = statbuf.st_size; if(localSize > 0) { accumulatedSize += localSize; } } } } closedir(dir); } return accumulatedSize; }
int preloadFile (const char *path, struct stat *stbuf) { int status; preloadThreadInfo_t *existingThreadInfo = NULL; preloadThreadInfo_t *threadInfo = NULL; preloadThreadData_t *threadData = NULL; char iRODSPath[MAX_NAME_LEN]; off_t cacheSize; // convert input path to iRODSPath status = _getiRODSPath(path, iRODSPath); if(status < 0) { rodsLogError(LOG_ERROR, status, "preloadFile: _getiRODSPath error."); rodsLog (LOG_ERROR, "preloadFile: failed to get iRODS path - %s", path); return status; } // check the given file is already preloaded or preloading LOCK(PreloadLock); // check the given file is preloading existingThreadInfo = (preloadThreadInfo_t *)lookupFromHashTable(PreloadThreadTable, iRODSPath); if(existingThreadInfo != NULL) { rodsLog (LOG_DEBUG, "preloadFile: preloading is already running - %s", iRODSPath); UNLOCK(PreloadLock); return 0; } if(_hasValidCache(iRODSPath, stbuf) != 0) { // invalidate cache - this may fail if cache file does not exists // if old cache exists in local, invalidate it _invalidateCache(iRODSPath); if(stbuf->st_size < PreloadConfig.preloadMinSize) { rodsLog (LOG_DEBUG, "preloadFile: given file is smaller than preloadMinSize, canceling preloading - %s", iRODSPath); UNLOCK(PreloadLock); return (0); } // check whether preload cache exceeds limit if(PreloadConfig.cacheMaxSize > 0) { // cache max size is set if(stbuf->st_size > (off_t)PreloadConfig.cacheMaxSize) { rodsLog (LOG_DEBUG, "preloadFile: given file is bigger than cacheMaxSize, canceling preloading - %s", iRODSPath); UNLOCK(PreloadLock); return (0); } cacheSize = getFileSizeRecursive(PreloadConfig.cachePath); if((cacheSize + stbuf->st_size) > (off_t)PreloadConfig.cacheMaxSize) { // evict? status = _evictOldCache((cacheSize + stbuf->st_size) - (off_t)PreloadConfig.cacheMaxSize); if(status < 0) { rodsLog (LOG_ERROR, "preloadFile: failed to evict old cache"); UNLOCK(PreloadLock); return status; } } } // does not have valid cache. now, start a new preloading // create a new thread to preload threadInfo = (preloadThreadInfo_t *)malloc(sizeof(preloadThreadInfo_t)); threadInfo->path = strdup(iRODSPath); threadInfo->running = PRELOAD_THREAD_RUNNING; INIT_STRUCT_LOCK((*threadInfo)); insertIntoHashTable(PreloadThreadTable, iRODSPath, threadInfo); // prepare thread argument threadData = (preloadThreadData_t *)malloc(sizeof(preloadThreadData_t)); threadData->path = strdup(iRODSPath); memcpy(&threadData->stbuf, stbuf, sizeof(struct stat)); threadData->threadInfo = threadInfo; rodsLog (LOG_DEBUG, "preloadFile: start preloading - %s", iRODSPath); #ifdef USE_BOOST status = threadInfo->thread = new boost::thread(_preloadThread, (void *)threadData); #else status = pthread_create(&threadInfo->thread, NULL, _preloadThread, (void *)threadData); #endif } else { rodsLog (LOG_DEBUG, "preloadFile: given file is already preloaded - %s", iRODSPath); status = 0; } UNLOCK(PreloadLock); return status; }