reman3/Rayman_X/cpa/tempgrp/ldt/Src/Interface.c

933 lines
30 KiB
C
Raw Blame History

/*------------------------------------------------------------------------------
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 */
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/* 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; i<maxValue; i++)
{
if(((short)(((LDT_tdst_LinkValue*)pData[i])->pLink->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); i<maxValue; i++)
{
if(((short)(((LDT_tdst_Link*)pData[i])->dwFlags)) >= 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; i<g_ArSolvers.nSize; i++ )
{
tdst_Solver *pSolver=(tdst_Solver *)LDT_DSAr_GetAt( &g_ArSolvers, i );
pSolver->Solve( 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;
}