933 lines
30 KiB
C
933 lines
30 KiB
C
/*------------------------------------------------------------------------------
|
||
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;
|
||
}
|