// // DTrack::RegisterDestruction // // Register the destruction of the item 'info' // void DTrack::RegisterDestruction(Info &info) { // Never registered, or has died - perhaps deleting twice? if (!info.IsSetup()) { ERR_FATAL(("Invalid destruction : Item is NOT setup! (Tracker %s)", name.str)); } // Different id, something bad has happened - perhaps bad memory? if (*info.trackPos != info.id) { ERR_FATAL(("Invalid destruction : Different Id (Tracker %s, %d, %d)", name.str, *info.trackPos, info.id)); } // Set item as empty *info.trackPos = DTRACK_EMPTY; // Add to cache CacheAdd(info.trackPos); // Info is no longer setup info.Clear(); ASSERT(stateInfo.items); // Decrease number of items stateInfo.items--; }
// // DTrack::HitCache // // Get an available position from the cache (never fails) // U32* DTrack::HitCache() { // Is there an item in the cache if (cacheCount) { // This is a cache hit stateInfo.cacheHits++; } else { ASSERT(blocks.GetCount() * blockSize >= stateInfo.items); // Is the remaining number of items below the free limit if ((blocks.GetCount() * blockSize) - stateInfo.items < DTRACK_FREELIMIT) { // So allocate a new block AllocateNewBlock(); } else { // This is a cache miss stateInfo.cacheMisses++; // Stop scanning when cache is full Bool cacheFull = FALSE; // Scan each block for (NList<Block>::Iterator b(&blocks); *b && !cacheFull; b++) { // Check each item in block for (U32 i = 0; i < blockSize && !cacheFull; i++) { // Is this position empty if ((*b)->data[i] == DTRACK_EMPTY) { // Add to cache cacheFull = CacheAdd(&(*b)->data[i]); } } } } } // Must be positions in cache now ASSERT(cacheCount); // Return top item return (cache[--cacheCount]); }
// // DTrack::AllocateNewBlock // // Allocate a new block and fill cache // void DTrack::AllocateNewBlock() { // Allocate new block Block *newBlock = new Block(blockSize); // Append to block list blocks.Append(newBlock); // Do not try and add if cache is full Bool cacheFull = FALSE; // Step through each new item for (U32 i = 0; i < blockSize; i++) { // Flag it as empty newBlock->data[i] = DTRACK_EMPTY; // Add new position to cache if (!cacheFull) { cacheFull = CacheAdd(&newBlock->data[i]); } } }
/** * Loads a plugins cache file. * * This function will load the plugin cache if present and valid. This cache * will in turn be queried by AllocateAllPlugins() to see if it needs to * actually load the dynamically loadable module. * This allows us to only fully load plugins when they are actually used. */ size_t CacheLoad( vlc_object_t *p_this, const char *dir, module_cache_t **r ) { char *psz_filename; FILE *file; int i_size, i_read; char p_cachestring[sizeof(CACHE_STRING)]; size_t i_cache; int32_t i_marker; assert( dir != NULL ); *r = NULL; if( asprintf( &psz_filename, "%s"DIR_SEP CACHE_NAME, dir ) == -1 ) return 0; msg_Dbg( p_this, "loading plugins cache file %s", psz_filename ); file = vlc_fopen( psz_filename, "rb" ); if( !file ) { msg_Warn( p_this, "cannot read %s: %s", psz_filename, vlc_strerror_c(errno) ); free( psz_filename ); return 0; } free( psz_filename ); /* Check the file is a plugins cache */ i_size = sizeof(CACHE_STRING) - 1; i_read = fread( p_cachestring, 1, i_size, file ); if( i_read != i_size || memcmp( p_cachestring, CACHE_STRING, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #ifdef DISTRO_VERSION /* Check for distribution specific version */ char p_distrostring[sizeof( DISTRO_VERSION )]; i_size = sizeof( DISTRO_VERSION ) - 1; i_read = fread( p_distrostring, 1, i_size, file ); if( i_read != i_size || memcmp( p_distrostring, DISTRO_VERSION, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #endif /* Check Sub-version number */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != CACHE_SUBVERSION_NUM ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } /* Check header marker */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != ftell( file ) - (int)sizeof(i_marker) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } if (fread( &i_cache, 1, sizeof(i_cache), file ) != sizeof(i_cache) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(file too short)" ); fclose( file ); return 0; } module_cache_t *cache = NULL; for (size_t count = 0; count < i_cache;) { module_t *module; int i_submodules; module = vlc_module_create (NULL); /* Load additional infos */ LOAD_STRING(module->psz_shortname); LOAD_STRING(module->psz_longname); LOAD_STRING(module->psz_help); LOAD_IMMEDIATE(module->i_shortcuts); if (module->i_shortcuts > MODULE_SHORTCUT_MAX) goto error; else { module->pp_shortcuts = xmalloc (sizeof (*module->pp_shortcuts) * module->i_shortcuts); for (unsigned j = 0; j < module->i_shortcuts; j++) LOAD_STRING(module->pp_shortcuts[j]); } LOAD_STRING(module->psz_capability); LOAD_IMMEDIATE(module->i_score); LOAD_IMMEDIATE(module->b_unloadable); /* Config stuff */ if (CacheLoadModuleConfig (module, file) != VLC_SUCCESS) goto error; LOAD_STRING(module->domain); if (module->domain != NULL) vlc_bindtextdomain (module->domain); LOAD_IMMEDIATE( i_submodules ); while( i_submodules-- ) { module_t *submodule = vlc_module_create (module); free (submodule->pp_shortcuts); LOAD_STRING(submodule->psz_shortname); LOAD_STRING(submodule->psz_longname); LOAD_IMMEDIATE(submodule->i_shortcuts); if (submodule->i_shortcuts > MODULE_SHORTCUT_MAX) goto error; else { submodule->pp_shortcuts = xmalloc (sizeof (*submodule->pp_shortcuts) * submodule->i_shortcuts); for (unsigned j = 0; j < submodule->i_shortcuts; j++) LOAD_STRING(submodule->pp_shortcuts[j]); } LOAD_STRING(submodule->psz_capability); LOAD_IMMEDIATE(submodule->i_score); } char *path; struct stat st; /* Load common info */ LOAD_STRING(path); if (path == NULL) goto error; LOAD_IMMEDIATE(st.st_mtime); LOAD_IMMEDIATE(st.st_size); CacheAdd (&cache, &count, path, &st, module); free (path); /* TODO: deal with errors */ } fclose( file ); *r = cache; return i_cache; error: msg_Warn( p_this, "plugins cache not loaded (corrupted)" ); /* TODO: cleanup */ fclose( file ); return 0; }
/** * Loads a plugins cache file. * * This function will load the plugin cache if present and valid. This cache * will in turn be queried by AllocateAllPlugins() to see if it needs to * actually load the dynamically loadable module. * This allows us to only fully load plugins when they are actually used. */ size_t CacheLoad( vlc_object_t *p_this, const char *dir, module_cache_t **r ) { char *psz_filename; FILE *file; int i_size, i_read; char p_cachestring[sizeof(CACHE_STRING)]; int32_t i_marker; assert( dir != NULL ); *r = NULL; if( asprintf( &psz_filename, "%s"DIR_SEP CACHE_NAME, dir ) == -1 ) return 0; msg_Dbg( p_this, "loading plugins cache file %s", psz_filename ); file = vlc_fopen( psz_filename, "rb" ); if( !file ) { msg_Warn( p_this, "cannot read %s: %s", psz_filename, vlc_strerror_c(errno) ); free( psz_filename ); return 0; } free( psz_filename ); /* Check the file is a plugins cache */ i_size = sizeof(CACHE_STRING) - 1; i_read = fread( p_cachestring, 1, i_size, file ); if( i_read != i_size || memcmp( p_cachestring, CACHE_STRING, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #ifdef DISTRO_VERSION /* Check for distribution specific version */ char p_distrostring[sizeof( DISTRO_VERSION )]; i_size = sizeof( DISTRO_VERSION ) - 1; i_read = fread( p_distrostring, 1, i_size, file ); if( i_read != i_size || memcmp( p_distrostring, DISTRO_VERSION, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #endif /* Check sub-version number */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != CACHE_SUBVERSION_NUM ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } /* Check header marker */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != ftell( file ) - (int)sizeof(i_marker) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } module_cache_t *cache = NULL; size_t count = 0; char *path = NULL; for (;;) { module_t *module = CacheLoadModule (file); if (module == NULL) { if (feof (file)) break; goto error; } struct stat st; /* Load common info */ LOAD_STRING(path); if (path == NULL) goto error; LOAD_IMMEDIATE(st.st_mtime); LOAD_IMMEDIATE(st.st_size); CacheAdd (&cache, &count, path, &st, module); free (path); path = NULL; /* TODO: deal with errors */ } fclose( file ); *r = cache; return count; error: free( path ); if (ferror (file)) msg_Err(p_this, "plugins cache read error: %s", vlc_strerror_c(errno)); msg_Warn( p_this, "plugins cache not loaded (corrupted)" ); /* TODO: cleanup */ fclose( file ); return 0; }