/*------------------------------------------------------------------------------ FILE : Interface.c CREATED : 98/05/21 AUTHOR : Catalin Cocos CONTENTS: user end functions ------------------------------------------------------------------------------*/ #include "StdInc.h" #include "Interface.h" #include "Register.h" #include "Parser.h" #include "Refs.h" #include "Error.h" #ifdef LDT_LOG_STATISTICS int LogFileOpened = 0; TimerStruct TotalFlushtime = {0}; TimerStruct Totalsolvetime = {0}; TimerStruct Totalreadtime = {0}; TimerStruct TotalPostprtime = {0}; unsigned TotalFileCount = 0, TotalNumLinks = 0; double TotalFileSize = 0.; #endif #ifdef LDT_LOG_MEMORY unsigned long g_allocsize = 0; unsigned long g_Maxallocsize = 0; unsigned long g_size; void* g_palloc; unsigned long g_allocCount = 0; unsigned long g_reallocCount = 0; unsigned long g_freeCount = 0; #endif int g_nInitialized = 0; extern int g_isFileNameValid = 1; LDT_tdst_Link *g_pGetFrom = NULL; unsigned short g_usLinkingPerstincence; /* Link-Value association array ----------------------------------*/ LDT_tdst_DSArray g_arLinkAssocTable; /* Initialization/Closing functions -------------------------------------*/ /*------------------------------------------------------------------------------ DESC. : initialization method can be called any number of times. The method must be called before using the other module functions !!!!!! OUTPUT : 0 if the module was already initialized, 1 otherwise CREATED : 98/10/07 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ int LDT_Initialize() { if( g_nInitialized ) return 0; #ifdef LDT_USE_MMG /* initialization of the memory module */ LDT_fn_v_Mem_InitModule(); #endif /* LDT_USE_MMG */ #ifdef LDT_LOG_MEMORY g_allocsize = 0; g_Maxallocsize = 0; g_allocCount = 0; g_reallocCount = 0; g_freeCount = 0; #endif #ifdef LDT_LOG_STATISTICS TotalFileCount = 0; TotalFileSize = 0.; TotalNumLinks = 0; TotalFlushtime.TimeCounter = 0; Totalsolvetime.TimeCounter = 0; Totalreadtime.TimeCounter = 0; TotalPostprtime.TimeCounter = 0; { FILE* file = fopen("LDT.log", LogFileOpened++?"a+":"w"); time_t strTime; struct tm *newtime; time( &strTime ); newtime = localtime( &strTime ); fprintf(file, "===================================================================\n" ); fprintf(file, "LDT module initialized: %s", asctime( newtime ) ); fprintf(file, "===================================================================\n" ); fclose(file); } #endif g_usLinkingPerstincence = 0; /* maximum linking perstincence */ /* initialize the section type registration table */ LDT_DSAr_Init( &g_ArSectionCallbacks ); LDT_DSAr_SetSortMethod( &g_ArSectionCallbacks, LDT_Compare_CallbackEntries); LDT_DSAr_SetGranularity( &g_ArSectionCallbacks, 25 ); /* initialize the file type registration table */ LDT_DSAr_Init( &g_ArFileCallbacks ); LDT_DSAr_SetSortMethod( &g_ArFileCallbacks, LDT_Compare_CallbackEntries); LDT_DSAr_SetGranularity( &g_ArFileCallbacks, 25 ); /* initialize the paths array */ LDT_DSAr_Init( &g_ArBaseDirectories ); /* initialize the paths array */ LDT_DSAr_Init( &g_ArPaths ); LDT_DSAr_SetSortMethod( &g_ArPaths, LDT_Compare_CallbackEntries); LDT_DSAr_SetGranularity( &g_ArPaths, 25 ); /* initialize the path strings array */ LDT_DSAr_Init( &g_ArPathStrings ); LDT_DSAr_SetSortMethod( &g_ArPathStrings, LDT_Compare_Strings); LDT_DSAr_SetGranularity( &g_ArPathStrings, 25 ); /* initialize the post-process registration table */ LDT_DSAr_Init( &g_ArSolvers ); LDT_DSAr_SetSortMethod( &g_ArSolvers, SortSolvers ); LDT_DSAr_SetGranularity( &g_ArSolvers, 25 ); /* contents initialization */ LDT_DSAr_Init( &TheFileDesc.arContents ); LDT_DSAr_SetSortMethod( &TheFileDesc.arContents, LDT_Compare_Positions ); LDT_DSAr_SetGranularity( &TheFileDesc.arContents, 100 ); /* contents initialization */ #ifdef LDT_LOG_STATISTICS InitializeTimingEnvironment(); #endif #ifdef LDT_MULTITHREADED InitializeCriticalSection( &GReadExclusion ); #endif /* initialize the parser */ InitParser(); /* first instance activated */ #ifdef LDT_LOG_ERRORS InitErrFile(); #endif /* initialize the link/value table */ LDT_DSAr_Init( &g_arLinkAssocTable ); LDT_DSAr_SetSortMethod( &g_arLinkAssocTable, LDT_Compare_LinkValues); LDT_DSAr_SetGranularity( &g_arLinkAssocTable, 100 ); /* initialize the string array */ LDT_DSAr_Init( &g_ArFilenames ); LDT_DSAr_SetSortMethod( &g_ArFilenames, LDT_Compare_Strings); LDT_DSAr_SetGranularity( &g_ArFilenames, 100 ); /* initialize the reference table */ LDT_DSAr_Init( &g_ArRefs ); LDT_DSAr_SetSortMethod( &g_ArRefs, LDT_Compare_Refs); LDT_DSAr_SetGranularity( &g_ArRefs, 100 ); /* initialize the link table */ LDT_DSHs_Init(&g_HashLinks, (int(*)(void*))LDT_Link_Dispersion, LDT_Compare_Links, (void(*)(void*))LDT_Delete_Link); LDT_DSHs_SetGranularity( &g_HashLinks, 100 ); return (g_nInitialized = 1); /* the module was initialized */ } /*------------------------------------------------------------------------------ DESC. : Closing method can be called any number of times. OUTPUT : 0 if the module was already closed, 1 otherwise CREATED : 98/05/21 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ int LDT_Close() { if(!g_nInitialized) return 0; /*_____________________________________________________________________________*/ LDT_FlushAndForget(0); /* load the unresolved refs and delete the internal linktable */ LDT_CleanUpRegistrations(); /* delete the registered stuff */ /*ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ*/ /* close the link table (deleting the existing links) */ LDT_DSHs_Close( &g_HashLinks, 1); #ifdef LDT_MULTITHREADED DeleteCriticalSection( &GReadExclusion ); #endif #ifdef LDT_LOG_ERRORS CLoseErrFile(); #endif #ifdef LDT_LOG_STATISTICS { TimerStruct TempTimer; FILE* file = fopen("LDT.log", LogFileOpened++?"a+":"w"); time_t strTime; struct tm *newtime; time( &strTime ); newtime = localtime( &strTime ); fprintf(file, "===================================================================\n" ); fprintf(file, "Totals:\n\n" ); fprintf(file, "Flush Time:\t\t%.3f\n", ReadTimer(&TotalFlushtime) ); fprintf(file, "Read Time:\t\t%.3f\n", ReadTimer(&Totalreadtime) ); #ifdef LDT_MULTITHREADED fprintf(file, "Process Time:\t\t%.3f\n", ReadTimer(&Totalsolvetime) ); #else TempTimer.TimeCounter = Totalsolvetime.TimeCounter - Totalreadtime.TimeCounter; fprintf(file, "Process Time:\t\t%.3f\n", ReadTimer(&TempTimer)); #endif fprintf(file, "Postprocess Time:\t%.3f\n", ReadTimer(&TotalPostprtime) ); #ifdef LDT_MULTITHREADED { TempTimer.TimeCounter = TotalPostprtime.TimeCounter + Totalsolvetime.TimeCounter + Totalreadtime.TimeCounter; fprintf(file, "\nMultithreaded disk read performance:\n"); fprintf(file, "Useful Time:\t\t%.3f\n", ReadTimer(&TempTimer)); fprintf(file, "Absloute Time Gain:\t%.3f\n", ReadTimer(&TempTimer) - ReadTimer(&TotalFlushtime)); TempTimer.TimeCounter -= TotalFlushtime.TimeCounter; fprintf(file, "Disk Read Savings: \t%.1f%%\n", (ReadTimer(&TempTimer))*100/ReadTimer(&Totalreadtime)); } #endif fprintf(file, "\nSections:\t\t%u", TotalNumLinks ); fprintf(file, "\nFiles:\t\t\t%u", TotalFileCount ); fprintf(file, "\nRead:\t\t\t%.3f MB\n\n", TotalFileSize/1024/1024 ); #ifdef LDT_LOG_MEMORY fprintf(file, "\nMaximum Memory Used:\t%.3f MB\n", ((double)g_Maxallocsize)/1024/1024 ); fprintf(file, "\nMalloc Count:\t\t%u\n", g_allocCount ); fprintf(file, "Free Count:\t\t%u\n", g_freeCount ); fprintf(file, "Realloc Count:\t\t%u\n", g_reallocCount ); fprintf(file, "Memory Leaks:\t\t%.3f KB\n", ((double)g_allocsize)/1024 ); fprintf(file, "\nWarning, time estimation is affected by the memory measurements. \n\n"); #endif fprintf(file, "LDT module closed: %s", asctime( newtime ) ); fprintf(file, "===================================================================\n" ); fprintf(file, "\n\n\n"); fclose(file); } #endif #ifdef LDT_USE_MMG /* release the memory module */ LDT_fn_v_Mem_CloseModule(); #endif /* DMS_USE_MMG */ g_nInitialized = 0; return 1; } /*------------------------------------------------------------------------------ DESC. : unregisters all registered types, paths and solvers - memory clean-up CREATED : 98/09/22 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ void LDT_CleanUpRegistrations() { int i, j; // if(InstanceCount) // { // ERRoR(0, NULL, 0, "All types and paths registrations are deleted during a loading session"); // return; // } if( g_nInitialized == 0 ) return; /* close the section type registration table */ for( i = LDT_DSAr_GetUpperBound(&g_ArSectionCallbacks); i>=0; i--) { free(((LDT_tdst_CallbackEntry*)g_ArSectionCallbacks.pData[i])->szType); free( g_ArSectionCallbacks.pData[i]); } LDT_DSAr_RemoveAll( &g_ArSectionCallbacks ); /* close the file type registration table */ for( i = LDT_DSAr_GetUpperBound(&g_ArFileCallbacks); i>=0; i--) { free(((LDT_tdst_CallbackEntry*)g_ArFileCallbacks.pData[i])->szType); free( g_ArFileCallbacks.pData[i]); } LDT_DSAr_RemoveAll( &g_ArFileCallbacks ); /* close the post-process registration table */ { LDT_tdst_DSArray* pRef; for( i = LDT_DSAr_GetUpperBound(&g_ArSolvers); i>=0; i--) { pRef = (LDT_tdst_DSArray*)((tdst_Solver*)g_ArSolvers.pData[i])->hRef; if(pRef) for( j = LDT_DSAr_GetUpperBound(pRef); j>=0; j--) free( pRef->pData[j]); LDT_DSAr_delete( pRef ); free( g_ArSolvers.pData[i]); } } LDT_DSAr_RemoveAll( &g_ArSolvers ); /* close the base paths table */ for( i = LDT_DSAr_GetUpperBound(&g_ArBaseDirectories); i>=0; i--) free(g_ArBaseDirectories.pData[i]); LDT_DSAr_RemoveAll(&g_ArBaseDirectories); /* close the path table */ for( i = LDT_DSAr_GetUpperBound(&g_ArPaths); i>=0; i--) { LDT_DSAr_RemoveAll(&((LDT_tdst_TypePaths*)g_ArPaths.pData[i])->arPaths); free( ((LDT_tdst_TypePaths*)g_ArPaths.pData[i])->szExtension ); free(g_ArPaths.pData[i]); } LDT_DSAr_RemoveAll(&g_ArPaths); /* close the path strings table */ for( i = LDT_DSAr_GetUpperBound(&g_ArPathStrings); i>=0; i--) free(g_ArPathStrings.pData[i]); LDT_DSAr_RemoveAll(&g_ArPathStrings); } /* Link-Value association functions -------------------------------------*/ /*------------------------------------------------------------------------------ DESC. : associates an userd-supplied value to a link CREATED : 98/08/19 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ void LDT_SetLinkValue( LDT_tdst_Link* pLink, unsigned long value ) { int idx, iidx; idx = LDT_DSAr_Index( &g_arLinkAssocTable, (LDT_tdst_LinkValue*)&pLink, &iidx ); if( idx<0 ) { /* the link is not present in the table */ LDT_tdst_LinkValue* pNewAssoc = malloc(sizeof(LDT_tdst_LinkValue)); pNewAssoc->pLink = pLink; pNewAssoc->value = value; LDT_DSAr_InsertAt( &g_arLinkAssocTable, iidx, pNewAssoc ); } else { ((LDT_tdst_LinkValue*)g_arLinkAssocTable.pData[idx])->value = value; /* link already present -> change the associated value */ #if defined(LDT_ERROR_TREATMENT) && ( LDT_WARNING_LEVEL >= 3 || LDT_ERROR_LEVEL >= 3) ERRoR(3, pLink, 0, "Link associated value already present. The old value was overwritten."); #endif } } /*------------------------------------------------------------------------------ DESC. : retrieves the user-supplied value associated to the link CREATED : 98/08/19 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ unsigned long LDT_GetLinkValue( LDT_tdst_Link* pLink ) { int idx = LDT_DSAr_Index( &g_arLinkAssocTable, (LDT_tdst_LinkValue*)&pLink, NULL ); if(idx < 0) { #if defined(LDT_ERROR_TREATMENT) && ( LDT_WARNING_LEVEL >= 3 || LDT_ERROR_LEVEL >= 3) ERRoR(3, pLink, 0, "No associated value available for this link."); #endif return 0; } return ((LDT_tdst_LinkValue*)LDT_DSAr_GetAt( &g_arLinkAssocTable, idx ))->value; } /*------------------------------------------------------------------------------ DESC. : retrieves and removes the user-supplied value associated to the link CREATED : 98/09/31 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ unsigned long LDT_RemoveLinkValue( LDT_tdst_Link* pLink ) { LDT_tdst_LinkValue* pAssoc; unsigned long value; int idx = LDT_DSAr_Index( &g_arLinkAssocTable, (LDT_tdst_LinkValue*)&pLink, NULL ); if(idx < 0) { #if defined(LDT_ERROR_TREATMENT) && ( LDT_WARNING_LEVEL >= 3 || LDT_ERROR_LEVEL >= 3) ERRoR(3, pLink, 0, "No associated value available for this link."); #endif return 0; } pAssoc = (LDT_tdst_LinkValue*)LDT_DSAr_RemoveAt( &g_arLinkAssocTable, idx ); value = pAssoc->value; free(pAssoc); return value; } /* Loading functions -------------------------------------*/ /*------------------------------------------------------------------------------ DESC. : Find a link OUTPUT : The pointer to link ( NULL if not found ) -1 on error; CREATED : 98/08/19 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ LDT_tdst_Link* LDT_GetLink( char *szSection ) { LDT_tdst_Link *pLink, *pRetVal; if( szSection==NULL) return NULL; pLink=LDT_CreateLinkFromReference( szSection ); pRetVal=LDT_DSHs_GetEqOf(&g_HashLinks, (void *)pLink); LDT_Delete_Link( pLink ); #if defined(LDT_ERROR_TREATMENT) && ( LDT_WARNING_LEVEL >= 2 || LDT_ERROR_LEVEL >= 2) if(!pRetVal) ERRoR(2, NULL, 0, "No link matches this description."); #endif return pRetVal; } /*------------------------------------------------------------------------------ DESC. : Load a section OUTPUT : The allocated object(can be NULL) -1 on error; CREATED : 98/05/22 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ void* LDT_LoadSection( char* szSection ) { int errcode, level; LDT_tdst_Link *Link = NULL; g_pGetFrom=NULL; /* MP-for refs */ if(szSection) /* loading request */ { Link = LDT_CreateLinkFromReference( szSection );/* normal call */ if( !Link ) return (void*)-1; /* error */ Link = LDT_DSHs_Insert( &g_HashLinks, Link, 1); g_pGetFrom=Link; /* MP-for refs */ if( Link->dwFlags & LDT_LF_ALLOCATED ) return Link->pObject; /* the link was already processed */ g_isFileNameValid = 0; errcode = Link->Type->Create( Link ); /* create the object */ g_isFileNameValid = 1; if(errcode) { #if defined(LDT_ERROR_TREATMENT) ERRoR(0, Link, errcode, "Unable to create associated object."); #endif return (void*)-1; } Link->dwFlags |= LDT_LF_ALLOCATED; /* set the corresponding flag */ AddReference( Link ); /* append the reference */ return Link->pObject; } if( g_FileDesc ) /* sub-section loading */ { void* pObject; LDT_tdst_CallbackEntry* Type = GetType( g_szType, LDT_REG_SECTION ); Link=LDT_Create_Link( g_szId, g_szParent, g_FileDesc->szFile, Type, g_usLinkingPerstincence, NULL, pParent[g_FileDesc->iLevel-1] ); Link=(LDT_tdst_Link *)LDT_DSHs_Insert( &g_HashLinks, (void *)Link, 1 ); pParent[ g_FileDesc->iLevel ]=Link; g_CrtSection=Link; if( Link->dwFlags&LDT_LF_LOADED ) { pObject = Link->pObject; /* the link was already processed */ LDT_SkipSection(); if( Link->dwFlags & LDT_LF_VOLATILE) free ( LDT_DSHs_RemoveEqOf( &g_HashLinks, Link)); /* remove volatile subsection*/ return pObject; } if( (Link->dwFlags & LDT_LF_ALLOCATED) == 0 ) { errcode = Type->Create( Link ); if(errcode ) { #if defined(LDT_ERROR_TREATMENT) ERRoR(0, Link, errcode, "Unable to create associated object."); #endif return (void*)-1; } Link->dwFlags |= LDT_LF_ALLOCATED; /* the link was allocated */ } level = g_FileDesc->iLevel - 1; errcode = Type->Load( Link ); pObject = Link->pObject; if(errcode) { #if defined(LDT_ERROR_TREATMENT) ERRoR(0, Link, errcode, "Unable to load section. User error triggered in callback."); #endif pObject = (void*)-1; } else if(level != g_FileDesc->iLevel) { #if defined(LDT_ERROR_TREATMENT) ERRoR(0, Link, 0, "Erroneous load callback. Failure to reach the section end mark! (premature return or subsections not treated)"); #endif pObject = (void*)-1; } Link->dwFlags |= LDT_LF_LOADED; /* the link was loaded */ if( Link->dwFlags & LDT_LF_VOLATILE) LDT_Delete_Link( LDT_DSHs_RemoveEqOf( &g_HashLinks, Link)); /* remove volatile subsection*/ return pObject; } #if defined(LDT_ERROR_TREATMENT) ERRoR(0, NULL, 0, "Cannot Load Subsection. Called from outside any \"Load\" callback."); #endif return (void*)-1; } /*------------------------------------------------------------------------------ DESC. : Load a section OUTPUT : pointer to the allocated object ( can be different from the received parameter - if the section was previously allocated) -1 on error; CREATED : 98/05/22 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ void* LDT_LoadSectionAt( char* szSection, void* pSection ) { int errcode, level; LDT_tdst_Link *Link = NULL; g_pGetFrom=NULL; /* MP-for refs */ if(szSection) /* loading request */ { Link = LDT_CreateLinkFromReference( szSection );/* normal call */ if( !Link ) return (void*)-1; /* error */ Link = LDT_DSHs_Insert( &g_HashLinks, Link, 1); g_pGetFrom=Link; /* MP-for refs */ if( Link->dwFlags & LDT_LF_ALLOCATED ) return Link->pObject; /* the link was already processed */ Link->pObject = pSection; /* copy the object */ #if defined(LDT_ERROR_TREATMENT) && ( LDT_WARNING_LEVEL >= 2 || LDT_ERROR_LEVEL >= 2) if(!pSection) ERRoR(2, Link, 0, "Associated object is set to NULL."); #endif Link->dwFlags |= LDT_LF_ALLOCATED; /* set the corresponding flag */ AddReference( Link ); /* append the reference */ return Link->pObject; } if( g_FileDesc ) /* sub-section loading */ { void* pObject; LDT_tdst_CallbackEntry* Type = GetType( g_szType, LDT_REG_SECTION ); Link=LDT_Create_Link( g_szId, g_szParent, g_FileDesc->szFile, Type, g_usLinkingPerstincence, NULL, pParent[g_FileDesc->iLevel-1] ); Link=(LDT_tdst_Link *)LDT_DSHs_Insert( &g_HashLinks, (void *)Link, 1 ); pParent[ g_FileDesc->iLevel ]=Link; g_CrtSection=Link; if( Link->dwFlags&LDT_LF_LOADED ) { pObject = Link->pObject; /* the link was already processed */ LDT_SkipSection(); if( Link->dwFlags & LDT_LF_VOLATILE) free ( LDT_DSHs_RemoveEqOf( &g_HashLinks, Link)); /* remove volatile subsection*/ return pObject; } if( (Link->dwFlags & LDT_LF_ALLOCATED) == 0 ) { Link->pObject = pSection; /* copy the object */ #if defined(LDT_ERROR_TREATMENT) && ( LDT_WARNING_LEVEL >= 2 || LDT_ERROR_LEVEL >= 2) if(!pSection) ERRoR(2, Link, 0, "Associated object is set to NULL."); #endif Link->dwFlags |= LDT_LF_ALLOCATED; /* the link was allocated */ } level = g_FileDesc->iLevel - 1; errcode = Type->Load( Link ); pObject = Link->pObject; if(errcode) { #if defined(LDT_ERROR_TREATMENT) ERRoR(0, Link, errcode, "Unable to load section. User error triggered in callback."); #endif pObject = (void*)-1; } else if(level != g_FileDesc->iLevel) { #if defined(LDT_ERROR_TREATMENT) ERRoR(0, Link, 0, "Erroneous load callback. Failure to reach the section end mark! (premature return or subsections not treated)"); #endif pObject = (void*)-1; } Link->dwFlags |= LDT_LF_LOADED; /* the link was loaded */ if( Link->dwFlags & LDT_LF_VOLATILE) LDT_Delete_Link( LDT_DSHs_RemoveEqOf( &g_HashLinks, Link)); /* remove volatile subsection*/ return pObject; } #if defined(LDT_ERROR_TREATMENT) ERRoR(0, NULL, 0, "Cannot Load Subsection. Called from outside any \"Load\" callback."); #endif return (void*)-1; } #ifdef LDT_MULTITHREADED HANDLE GReadCount; /* the number of files read from disk */ HANDLE GReadLimit; /* the number of available files */ HANDLE GFileLimit = NULL; /* the maximum number of files read in advance */ #pragma warning(disable: 4100) /*------------------------------------------------------------------------------ DESC. : File Reading thread method CREATED : 98/07/07 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ //unsigned int __stdcall DiskRead( void * p); unsigned int __stdcall DiskRead( void * p) { LDT_tdst_Refs * pRefs; LDT_tdst_MemFile* pFile; unsigned int uiPos=0; static char buffer[256]; int ok=1; // SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE ); for(;;) { WaitForSingleObject( GReadLimit, INFINITE); /* wait to have the number of opened files less than the max allowed */ WaitForSingleObject( GFileLimit, INFINITE); /* wait to have at least one file available for reading */ EnterCriticalSection( &GReadExclusion ); if((pRefs = g_pFileToRead)==NULL) { LeaveCriticalSection( &GReadExclusion ); break; } g_pFileToRead = pRefs->p_NextReferencedFile; LeaveCriticalSection( &GReadExclusion ); // SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); pFile = AccessFile( pRefs->szFile ); /* open the file */ // SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE ); pRefs->pFile = pFile; ReleaseSemaphore( GReadCount, 1, NULL); /* the file was opened */ } return 0; } #pragma warning(default: 4100) #endif void LDT_SetLinkingPersistence (unsigned short Level) { if( g_ArRefs.nSize ) LDT_Flush(); g_usLinkingPerstincence = Level; } void LDT_Forget(unsigned short Level) { int i, gap, maxValue, HashDimension; LDT_tdst_DSArray* pCrtAr; void** pData; LDT_DSAr_RemoveAll( &g_ArRefs ); /* the reference table is empty at this point - no other closing procedure necessary*/ LDT_DSAr_RemoveAll( &TheFileDesc.arContents); #ifdef LDT_USE_SINGLE_FILE_BUFFER if(GBuff) free(GBuff); GBuff = NULL; GBuffSize = 0; #endif if(Level) { /* Partial clean-up. Not reccomended due to low speed performance */ /* delete the invalid associations from the link/value table */ for( i = gap = 0, maxValue = LDT_DSAr_GetSize(&g_arLinkAssocTable), pData = g_arLinkAssocTable.pData; ipLink->dwFlags)) >= Level ) { free( pData[i]); gap++; } else pData[i-gap] = pData[i]; } LDT_DSAr_SetSize(&g_arLinkAssocTable, maxValue - gap); /* adjust the size of the array */ /* delete the not needed links from the links hash table */ for(HashDimension = g_HashLinks.pfnDispersion( NULL ) - 1 ; HashDimension>=0; HashDimension--) { pCrtAr = g_HashLinks.pData + HashDimension; pData = pCrtAr->pData; for( i = gap = 0, maxValue = LDT_DSAr_GetSize(pCrtAr); idwFlags)) >= Level ) { g_HashLinks.pfnDelete( pData[i]); gap++; } else pData[i-gap] = pData[i]; } LDT_DSAr_SetSize(pCrtAr, maxValue - gap); /* adjust the size of the array */ } } else { /* Total clean-up. The normal operation */ /*------------------------------- delete the existing links and the related data ----------------------*/ /* close the link/value table(deleting all stored associations) */ for( i = LDT_DSAr_GetUpperBound(&g_arLinkAssocTable), pData = g_arLinkAssocTable.pData; i>=0; i--) free( pData[i]); LDT_DSAr_RemoveAll( &g_arLinkAssocTable ); /* close the string array (deleting all stored strings) */ for( i = LDT_DSAr_GetUpperBound(&g_ArFilenames), pData = g_ArFilenames.pData; i>=0; i--) free( pData[i]); LDT_DSAr_RemoveAll( &g_ArFilenames ); LDT_DSHs_RemoveAll( &g_HashLinks, 1); } } /*------------------------------------------------------------------------------ DESC. : Reference solving function - performs loading & deletes the linktable afterwards OUTPUT : zero on error, nonzero if successful; CREATED : 98/05/24 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ int LDT_FlushAndForget(unsigned short Level) { int ERR = LDT_Flush(); LDT_Forget( Level ); return ERR; } /*------------------------------------------------------------------------------ DESC. : Reference solving function - performs the loading OUTPUT : zero on error, nonzero if successful; CREATED : 98/05/24 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ extern unsigned char* g_ulPos; int LDT_Flush() { static int FlushLaunched = 0; int OK = 1, i; #ifdef LDT_LOG_STATISTICS unsigned CurrentLinks = 0; TimerStruct FlushTime = TotalFlushtime; TimerStruct SolveTime = Totalsolvetime; TimerStruct Readtime = Totalreadtime; TimerStruct Postprtime = TotalPostprtime ; unsigned FileCount = TotalFileCount; double FileSize = TotalFileSize; { /* count the number of links */ int HashDimension = g_HashLinks.pfnDispersion( NULL ) - 1 ; for( ; HashDimension>=0; HashDimension--) CurrentLinks += LDT_DSAr_GetSize( g_HashLinks.pData + HashDimension ); } #endif if(FlushLaunched) { #if defined(LDT_ERROR_TREATMENT) ERRoR(0, NULL, 0, "Recursive call to LDT_Flush() not allowed. Call aborted. "); #endif return 0; } FlushLaunched = 1; /* sentinel */ #ifdef LDT_LOG_STATISTICS StartTimer(&TotalFlushtime); #endif do { if(g_pFileToProcess) { #ifdef LDT_MULTITHREADED unsigned thrdaddr; /* the read thread */ HANDLE Hthrd; /* the read thread */ GReadCount = CreateSemaphore( NULL, 0, LONG_MAX, NULL ); /* the number of files read from disk */ GFileLimit = CreateSemaphore( NULL, g_ArRefs.nSize, LONG_MAX, NULL ); /* the number of available files */ GReadLimit = CreateSemaphore( NULL, MAX_FILE_NO, LONG_MAX, NULL ); /* the maximum number of files read in advance */ InitializeCriticalSection( &GReadExclusion ); Hthrd = (void*)_beginthreadex(NULL, 0, DiskRead, NULL, 0, &thrdaddr); /* start the thread that reads files from disk */ #endif /* processing */ for(;g_pFileToProcess;) { #ifdef LDT_MULTITHREADED WaitForSingleObject( GReadCount, INFINITE); // SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST ); #endif #ifdef LDT_LOG_STATISTICS StartTimer(&Totalsolvetime); #endif if( Solve(g_pFileToProcess) ) /* the effective loading */ { #if defined(LDT_ERROR_TREATMENT) && ( LDT_WARNING_LEVEL >= 2 || LDT_ERROR_LEVEL >= 2) ERRoR(2, NULL, 0, "Unable to satisfy all loading requests for the previous file."); #endif OK = 0; /* Error encountered */ } #ifdef LDT_LOG_STATISTICS StopTimer(&Totalsolvetime); #endif LDT_DSAr_RemoveAll(&g_pFileToProcess->Links); #ifdef LDT_MULTITHREADED // SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL ); ReleaseSemaphore( GReadLimit, 1, NULL); /* signal that the file was processed */ #endif { LDT_tdst_Refs * pRefs = g_pFileToProcess; g_pFileToProcess = g_pFileToProcess->p_NextReferencedFile; free( LDT_DSAr_RemoveAt( &g_ArRefs, LDT_DSAr_Index(&g_ArRefs, pRefs, NULL) ) ); } } #ifdef LDT_MULTITHREADED ReleaseSemaphore( GReadLimit, 1, NULL ); /* allow the file reading thread to advance */ ReleaseSemaphore( GFileLimit, 1, NULL ); /* allow the file reading thread to advance */ WaitForSingleObject( Hthrd, INFINITE ); CloseHandle( Hthrd ); CloseHandle( GReadCount ); CloseHandle( GFileLimit ); CloseHandle( GReadLimit ); GFileLimit = NULL; #endif } #ifdef LDT_LOG_STATISTICS StartTimer(&TotalPostprtime); #endif /* post-process */ for( i=0; iSolve( pSolver->hRef ); } #ifdef LDT_LOG_STATISTICS StopTimer(&TotalPostprtime); #endif } while(g_pFileToProcess); #ifdef LDT_LOG_STATISTICS StopTimer(&TotalFlushtime); { /* count the number of links */ TimerStruct TempTimer; FILE* file = fopen("LDT.log", LogFileOpened++?"a+":"w"); time_t strTime; struct tm *newtime; unsigned NumLinks = 0; int HashDimension = g_HashLinks.pfnDispersion( NULL ) - 1 ; for( ; HashDimension>=0; HashDimension--) NumLinks += LDT_DSAr_GetSize( g_HashLinks.pData + HashDimension ); TotalNumLinks += NumLinks - CurrentLinks; FlushTime.TimeCounter = TotalFlushtime.TimeCounter - FlushTime.TimeCounter; SolveTime.TimeCounter = Totalsolvetime.TimeCounter - SolveTime.TimeCounter; Readtime.TimeCounter = Totalreadtime.TimeCounter - Readtime.TimeCounter; Postprtime.TimeCounter = TotalPostprtime.TimeCounter - Postprtime.TimeCounter; FileCount = TotalFileCount - FileCount; FileSize = TotalFileSize - FileSize; time( &strTime ); newtime = localtime( &strTime ); fprintf(file, "-------------------------------------------\n" ); fprintf(file, "Flush Stats:\n\n" ); fprintf(file, "Flush Time:\t\t%.3f\n", ReadTimer(&FlushTime) ); fprintf(file, "Read Time:\t\t%.3f\n", ReadTimer(&Readtime) ); #ifdef LDT_MULTITHREADED fprintf(file, "Process Time:\t\t%.3f\n", ReadTimer(&SolveTime) ); #else TempTimer.TimeCounter = SolveTime.TimeCounter - Readtime.TimeCounter; fprintf(file, "Process Time:\t\t%.3f\n", ReadTimer(&TempTimer)); #endif fprintf(file, "Postprocess Time:\t%.3f\n", ReadTimer(&Postprtime) ); #ifdef LDT_MULTITHREADED { TempTimer.TimeCounter = Postprtime.TimeCounter + SolveTime.TimeCounter + Readtime.TimeCounter; fprintf(file, "\nMultithreaded disk read performance:\n"); fprintf(file, "Useful Time:\t\t%.3f\n", ReadTimer(&TempTimer)); fprintf(file, "Absloute Time Gain:\t%.3f\n", ReadTimer(&TempTimer) - ReadTimer(&FlushTime)); TempTimer.TimeCounter -= FlushTime.TimeCounter; fprintf(file, "Disk Read Savings: \t%.1f%%\n", (ReadTimer(&TempTimer))*100/ReadTimer(&Readtime)); } #endif fprintf(file, "\nSections:\t\t%u", NumLinks - CurrentLinks ); fprintf(file, "\nFiles:\t\t\t%u", FileCount ); fprintf(file, "\nRead:\t\t\t%.3f MB\n\n", FileSize/1024/1024 ); fprintf(file, "-------------------------------------------\n" ); fprintf(file, "\n\n\n"); fclose(file); } #endif /* LDT_LOG_STATISTICS */ FlushLaunched = 0; /* sentinel removal */ return OK; /* return the error code */ } /* In-callback link manipulation functions -------------------------------------*/ void LDT_SetVolatileSubsection( LDT_tdst_Link* Link) { Link->dwFlags |= LDT_LF_VOLATILE; }