|
|
//+--------------------------------------------------------------------------
//
// Copyright (c) 1997-1999 Microsoft Corporation
//
// File: wkspace.cpp
//
// Contents: DB workspace
//
// History:
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#include "TLSdef.h"
#include "server.h"
#include "wkspace.h"
#include "utils.h"
#include "globals.h"
/////////////////////////////////////////////////////////////
//
// Try to save some memory
//
//
JBInstance __TlsDbWorkSpace::g_JbInstance; static TLSDbWorkSpacePool g_WorkSpacePool;
typedef map<PVOID, PVOID> ACQUIREDHANDLELIST;
CCriticalSection AcquiredHandleListLock; ACQUIREDHANDLELIST AcquiredHandleList;
LONG g_lWorkSpacePoolDeleted = 0;
#if DBG
DWORD g_dwNumWorkSpaceAllocated = 0; #endif
//-----------------------------------------------
//
// Table for work item storage,
//
//
JBSession g_WkItemSession(__TlsDbWorkSpace::g_JbInstance); JBDatabase g_WkItemDatabase(g_WkItemSession); WorkItemTable g_WkItemTable(g_WkItemDatabase);
//--------------------------------------------------------
BOOL TLSGetESEError( const JET_ERR jetErrCode, LPTSTR* pszString ) /*++
--*/ { JBError jbError;
return jbError.GetJBErrString( jetErrCode, pszString ); }
//--------------------------------------------------------
WorkItemTable* GetWorkItemStorageTable() { BOOL bSuccess = TRUE;
//
// verify session and database is correct.
//
if(g_WkItemSession.IsValid() == FALSE) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; }
if(g_WkItemDatabase.IsValid() == FALSE) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; }
if(g_WkItemTable.IsValid() == FALSE) { bSuccess = g_WkItemTable.OpenTable( TRUE, JET_bitTableUpdatable );
if(bSuccess == FALSE) { LPTSTR pString = NULL;
SetLastError(SET_JB_ERROR(g_WkItemTable.GetLastJetError())); TLSGetESEError(g_WkItemTable.GetLastJetError(), &pString);
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_SERVICEINIT, TLS_E_JB_OPENTABLE, g_WkItemTable.GetTableName(), g_WkItemTable.GetLastJetError(), (pString != NULL) ? pString : _TEXT("") );
if(pString != NULL) { LocalFree(pString); } } }
return (bSuccess == TRUE) ? &g_WkItemTable : NULL; }
//--------------------------------------------------------
DWORD CloseWorkSpacePool() { DWORD dwNumWkSpace = g_WorkSpacePool.GetNumberAvailable(); TLSDbWorkSpace* jbWkSpace=NULL; DWORD dwErrCode=ERROR_SUCCESS;
//
// Mark workspace pool deleted, this is for backup/restore
// that it will close entire workspace pool but RPC context
// rundown might happen after we close the workspace pool
//
InterlockedExchange( &g_lWorkSpacePoolDeleted, 1 );
#if DBG
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_HANDLEPOOL, DBGLEVEL_FUNCTION_TRACE, _TEXT("CloseWorkSpace() - Total %d, Num Available %d\n"), g_dwNumWorkSpaceAllocated, dwNumWkSpace ); #endif
while(dwNumWkSpace) { jbWkSpace = NULL; dwErrCode=g_WorkSpacePool.AcquireHandle( &jbWkSpace, INFINITE );
if(jbWkSpace) delete jbWkSpace;
dwNumWkSpace--;
#if DBG
g_dwNumWorkSpaceAllocated--; #endif
}
AcquiredHandleListLock.Lock();
if(AcquiredHandleList.empty() != TRUE) { ACQUIREDHANDLELIST::iterator it;
for(it = AcquiredHandleList.begin(); it != AcquiredHandleList.end(); it++) { if((*it).second != NULL) { jbWkSpace = (TLSDbWorkSpace*) (*it).second; delete jbWkSpace;
#if DBG
g_dwNumWorkSpaceAllocated--;
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_HANDLEPOOL, DBGLEVEL_FUNCTION_TRACE, _TEXT("Close Allocated WorkSpace()...\n") ); #endif
} else { TLSASSERT(FALSE); } }
AcquiredHandleList.erase(AcquiredHandleList.begin(), AcquiredHandleList.end()); } AcquiredHandleListLock.UnLock(); g_WkItemTable.CloseTable(); g_WkItemDatabase.CloseDatabase(); g_WkItemSession.EndSession();
#if DBG
if( 0 != g_dwNumWorkSpaceAllocated ) { TLSASSERT(FALSE); } #endif
//
// Delete log file so that to prevent long database recovery
//
__TlsDbWorkSpace::g_JbInstance.JBTerminate( JET_bitTermComplete, TRUE ); return ERROR_SUCCESS; }
//--------------------------------------------------------
BOOL IsValidAllocatedWorkspace( PTLSDbWorkSpace p ) /*++
Abstract:
Verify an allocated workspace handle is in our allocated list.
--*/ { BOOL bSuccess = TRUE;
ACQUIREDHANDLELIST::iterator it;
AcquiredHandleListLock.Lock();
it = AcquiredHandleList.find(p); bSuccess = (it != AcquiredHandleList.end()); AcquiredHandleListLock.UnLock();
return bSuccess; }
//--------------------------------------------------------
void ReleaseWorkSpace( PTLSDbWorkSpace *p ) /*
*/ { if( g_lWorkSpacePoolDeleted == 1 ) { //
// DB workspace pool has been deleted, acquired workspace
// handle will be deleted via AcquireHandleList
//
// overactive assert here... there is a race condition possible,
// this assert is to verify that this if statement handles it.
TLSASSERT(FALSE); return; }
TLSASSERT(p != NULL && *p != NULL);
if(p != NULL) { ACQUIREDHANDLELIST::iterator it;
AcquiredHandleListLock.Lock();
it = AcquiredHandleList.find(*p); if(it != AcquiredHandleList.end()) { AcquiredHandleList.erase(it); } else { TLSASSERT(FALSE); }
AcquiredHandleListLock.UnLock(); }
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_HANDLEPOOL, DBGLEVEL_FUNCTION_TRACE, _TEXT("Releasing workspace 0x%08x...\n"), *p );
if(*p) { (*p)->Cleanup(); g_WorkSpacePool.ReleaseHandle(*p); *p = NULL; } }
//--------------------------------------------------------
TLSDbWorkSpace* AllocateWorkSpace( DWORD dwWaitTime /* INFINITE */ ) /*
*/ { TLSDbWorkSpace* jbWkSpace=NULL; BOOL bSuccess;
DBGPrintf( DBG_INFORMATION, DBG_FACILITY_HANDLEPOOL, DBGLEVEL_FUNCTION_TRACE, _TEXT("Allocating a workspace...\n") ); bSuccess = g_WorkSpacePool.AcquireHandleEx( GetServiceShutdownHandle(), &jbWkSpace, dwWaitTime );
if(bSuccess == TRUE) { DBGPrintf( DBG_INFORMATION, DBG_FACILITY_HANDLEPOOL, DBGLEVEL_FUNCTION_TRACE, _TEXT("Allocated 0x%08x...\n"), jbWkSpace );
AcquiredHandleListLock.Lock(); AcquiredHandleList[jbWkSpace] = jbWkSpace; AcquiredHandleListLock.UnLock(); } else { DBGPrintf( DBG_INFORMATION, DBG_FACILITY_HANDLEPOOL, DBGLEVEL_FUNCTION_TRACE, _TEXT("Can't allocate workspace - %d are in use...\n"), AcquiredHandleList.size() ); }
return jbWkSpace; }
//--------------------------------------------------------
DWORD GetNumberOfWorkSpaceHandle() { return g_WorkSpacePool.GetNumberAvailable(); }
//--------------------------------------------------------
BOOL TLSJbInitDatabaseEngine( IN JBSession& jbSession, IN JBDatabase& jbDatabase, IN LPCTSTR szDatabaseFile, IN LPCTSTR szUserName, IN LPCTSTR szPassword ) /*++
--*/ { BOOL bSuccess = TRUE; DWORD dwErrCode;
if(jbSession.IsValid() == FALSE) { bSuccess = jbSession.BeginSession( szUserName, szPassword ); if(bSuccess == FALSE) { LPTSTR pString = NULL;
TLSGetESEError(jbSession.GetLastJetError(), &pString); TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_DBGENERAL, TLS_E_JB_BEGINSESSION, jbSession.GetLastJetError(), (pString != NULL) ? pString : _TEXT("") );
if(pString != NULL) { LocalFree(pString); }
DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("Error : Initialize JetBlue session - error code %d\n"), jbSession.GetLastJetError() );
dwErrCode = SET_JB_ERROR(jbSession.GetLastJetError()); SetLastError(dwErrCode); TLSASSERT(FALSE);
goto cleanup; } }
//
// Open Database
if(jbDatabase.IsValid() == FALSE) { bSuccess = jbDatabase.OpenDatabase(szDatabaseFile); if(bSuccess == FALSE) { JET_ERR errCode = jbDatabase.GetLastJetError();
if(errCode != JET_errFileNotFound) { if(errCode == JET_errDatabaseCorrupted) { TLSLogErrorEvent(TLS_E_CORRUPT_DATABASE); } else { LPTSTR pString = NULL;
TLSGetESEError(errCode, &pString);
//
// other type of error
//
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_DBGENERAL, TLS_E_JB_OPENDATABASE, szDatabaseFile, errCode, (pString != NULL) ? pString : _TEXT("") );
if(pString != NULL) { LocalFree(pString); } }
DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("Error : Can't create database because OpenDatabase failed with %d\n"), errCode );
dwErrCode = SET_JB_ERROR(errCode); SetLastError(dwErrCode); TLSASSERT(FALSE);
return FALSE; }
// create a new database file
bSuccess = jbDatabase.CreateDatabase(szDatabaseFile);
if(bSuccess == FALSE) { LPTSTR pString = NULL;
TLSGetESEError(jbDatabase.GetLastJetError(), &pString);
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_DBGENERAL, TLS_E_JB_CREATEDATABASE, szDatabaseFile, jbDatabase.GetLastJetError(), (pString != NULL) ? pString : _TEXT("") );
if(pString != NULL) { LocalFree(pString); }
DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("Error : can't create new database - error code %d\n"), jbDatabase.GetLastJetError() );
dwErrCode = SET_JB_ERROR(jbDatabase.GetLastJetError()); SetLastError(dwErrCode); } } }
cleanup:
return bSuccess; }
//--------------------------------------------------------
BOOL InitializeWorkSpacePool( IN int num_workspace, IN LPCTSTR szDatabaseFile, IN LPCTSTR szUserName, IN LPCTSTR szPassword, IN LPCTSTR szChkPointDirPath, IN LPCTSTR szTempDirPath, IN LPCTSTR szLogDirPath, IN BOOL bUpdatable ) /*
*/ { DWORD dwErrCode=ERROR_SUCCESS; int index=0; BOOL bSuccess=TRUE; BOOL bWkItemSuccess = TRUE;
DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("InitializeWorkSpacePool()... %d\n"), num_workspace );
if(__TlsDbWorkSpace::g_JbInstance.IsValid() == FALSE) { bSuccess = TLSJbInstanceInit( __TlsDbWorkSpace::g_JbInstance, szChkPointDirPath, szTempDirPath, szLogDirPath );
if(bSuccess != TRUE) { TLSASSERT(FALSE); goto cleanup; } }
if(g_WkItemTable.IsValid() == FALSE) { //
// Initialize session for WorkItemTable, critical
// error if this failed
//
bWkItemSuccess = TLSJbInitDatabaseEngine( g_WkItemSession, g_WkItemDatabase, szDatabaseFile, szUserName, szPassword );
if(bWkItemSuccess == FALSE) { TLSASSERT(FALSE); goto cleanup; } }
//
// Allocate number of workspace
//
for(index=0; index < num_workspace; index++) { PTLSDbWorkSpace pJbWkSpace=NULL;
pJbWkSpace = new TLSDbWorkSpace(); if(pJbWkSpace == NULL) { break; }
if(pJbWkSpace->InitWorkSpace( TRUE, szDatabaseFile, szUserName, szPassword, NULL, NULL, bUpdatable) == FALSE) { delete pJbWkSpace; break; } g_WorkSpacePool.ReleaseHandle(pJbWkSpace);
#if DBG
g_dwNumWorkSpaceAllocated++; #endif
}
//
// WorkSpace pool has been initialized
//
InterlockedExchange( &g_lWorkSpacePoolDeleted, 0 );
cleanup: if(bWkItemSuccess == FALSE) { // critical error, can't initialize session for workitem table.
SetLastError(TLS_E_INIT_WORKSPACE); return FALSE; }
//
// We need at least 3 workspace, one for update/insert
// and two for enumeration
//
if(index < num_workspace) { SetLastError(TLS_E_INIT_WORKSPACE); }
return index >= num_workspace; }
//--------------------------------------------------------
//
// Initialize DB workspace...
//
//--------------------------------------------------------
BOOL TLSJbInstanceInit( IN OUT JBInstance& jbInstance, IN LPCTSTR szChkPointDirPath, IN LPCTSTR szTempDirPath, IN LPCTSTR szLogDirPath ) /*
*/ { //
// Setup system parameters
//
BOOL bSuccess=TRUE; DWORD dwErrCode;
if(jbInstance.IsValid() == TRUE) { jbInstance.SetLastJetError(JET_errAlreadyInitialized); goto cleanup; }
//
// Set JetBlue parameter and initialize it
//
if(szChkPointDirPath != NULL) { bSuccess = jbInstance.SetSystemParameter( 0, JET_paramSystemPath, 0, (unsigned char *)szChkPointDirPath );
if(bSuccess == FALSE) { dwErrCode = SET_JB_ERROR(jbInstance.GetLastJetError()); SetLastError(dwErrCode); goto cleanup; } }
if(szTempDirPath != NULL) { bSuccess = jbInstance.SetSystemParameter( 0, JET_paramTempPath, 0, (unsigned char *)szTempDirPath );
if(bSuccess == FALSE) { dwErrCode = SET_JB_ERROR(jbInstance.GetLastJetError()); SetLastError(dwErrCode); goto cleanup; } }
if(szLogDirPath != NULL) { bSuccess = jbInstance.SetSystemParameter( 0, JET_paramLogFilePath, 0, (unsigned char *)szLogDirPath );
if(bSuccess == FALSE) { dwErrCode = SET_JB_ERROR(jbInstance.GetLastJetError()); SetLastError(dwErrCode); goto cleanup; } } if( g_EsentMaxCacheSize != LSERVER_PARAMETERS_USE_ESENTDEFAULT ) { //
// Adjust memory usage, ESENT will failed on invalid parameter
//
bSuccess = jbInstance.SetSystemParameter( 0, JET_paramCacheSizeMax, g_EsentMaxCacheSize, NULL );
if(bSuccess == TRUE) { bSuccess = jbInstance.SetSystemParameter( 0, JET_paramStartFlushThreshold, g_EsentStartFlushThreshold, NULL );
if( bSuccess == TRUE ) { bSuccess = jbInstance.SetSystemParameter( 0, JET_paramStopFlushThreshold, g_EsentStopFlushThreadhold, NULL ); } }
#if DBG
//
// check build, assert.
//
if(bSuccess == FALSE) { dwErrCode = SET_JB_ERROR(jbInstance.GetLastJetError()); TLSASSERT(FALSE); } #endif
}
bSuccess = jbInstance.SetSystemParameter( 0, JET_paramDeleteOutOfRangeLogs, 1, NULL);
if(bSuccess == FALSE) { dwErrCode = SET_JB_ERROR(jbInstance.GetLastJetError()); SetLastError(dwErrCode); goto cleanup; }
//
// We only use single instance for all the work space.
//
if(jbInstance.JBInitJetInstance() == FALSE) { LPTSTR pString = NULL;
TLSGetESEError(jbInstance.GetLastJetError(), &pString); TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_DBGENERAL, TLS_E_INIT_JETBLUE, jbInstance.GetLastJetError(), (pString != NULL) ? pString : _TEXT("") );
if(pString != NULL) { LocalFree(pString); } DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("Init. JetBlue Instance return error code %d\n"), jbInstance.GetLastJetError() );
SetLastError(SET_JB_ERROR(jbInstance.GetLastJetError())); }
cleanup: return jbInstance.IsSuccess(); }
//--------------------------------------------------------
//
// TLSDbWorkSpace implementation
//
//--------------------------------------------------------
BOOL __TlsDbWorkSpace::InitWorkSpace( BOOL bCreateIfNotExist, LPCTSTR szDatabaseFile, LPCTSTR szUserName, LPCTSTR szPassword, IN LPCTSTR szChkPointDirPath, IN LPCTSTR szTempDirPath, IN BOOL bUpdatable ) /*
*/ { BOOL bSuccess; DWORD dwErrCode;
//
// Initialize JetBlue Instance
if(g_JbInstance.IsValid() == FALSE) { SetLastError(TLS_E_INTERNAL); bSuccess = FALSE; goto cleanup; }
DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("InitWorkSpace()...\n") );
bSuccess = TLSJbInitDatabaseEngine( m_JetSession, m_JetDatabase, szDatabaseFile, szUserName, szPassword );
if(bSuccess == FALSE) { goto cleanup; }
//
// Open all table we need
//
bSuccess = m_LicPackTable.OpenTable( TRUE, (bUpdatable) ? JET_bitTableUpdatable : JET_bitTableReadOnly );
if(bSuccess == FALSE) { SetLastError(SET_JB_ERROR(m_LicPackTable.GetLastJetError()));
LPTSTR pString = NULL;
TLSGetESEError(m_LicPackTable.GetLastJetError(), &pString);
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_DBGENERAL, TLS_E_JB_OPENTABLE, m_LicPackTable.GetTableName(), m_LicPackTable.GetLastJetError(), (pString != NULL) ? pString : _TEXT("") );
if(pString != NULL) { LocalFree(pString); }
DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("Can't open table %s, error code %d\n"), m_LicPackTable.GetTableName(), m_LicPackTable.GetLastJetError() );
goto cleanup; }
bSuccess = m_LicPackDescTable.OpenTable( TRUE, (bUpdatable) ? JET_bitTableUpdatable : JET_bitTableReadOnly );
if(bSuccess == FALSE) { SetLastError(SET_JB_ERROR(m_LicPackDescTable.GetLastJetError()));
LPTSTR pString = NULL; TLSGetESEError(m_LicPackDescTable.GetLastJetError(), &pString);
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_DBGENERAL, TLS_E_JB_OPENTABLE, m_LicPackDescTable.GetTableName(), m_LicPackDescTable.GetLastJetError(), (pString != NULL) ? pString : _TEXT("") );
if(pString != NULL) { LocalFree(pString); }
DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("Can't open table %s, error code %d\n"), m_LicPackDescTable.GetTableName(), m_LicPackDescTable.GetLastJetError() );
goto cleanup; }
bSuccess = m_LicensedTable.OpenTable( TRUE, (bUpdatable) ? JET_bitTableUpdatable : JET_bitTableReadOnly );
if(bSuccess == FALSE) { SetLastError(SET_JB_ERROR(m_LicensedTable.GetLastJetError()));
LPTSTR pString = NULL;
TLSGetESEError(m_LicensedTable.GetLastJetError(), &pString);
TLSLogEvent( EVENTLOG_ERROR_TYPE, TLS_E_DBGENERAL, TLS_E_JB_OPENTABLE, m_LicensedTable.GetTableName(), m_LicensedTable.GetLastJetError(), (pString != NULL) ? pString : _TEXT("") );
if(pString != NULL) { LocalFree(pString); }
DBGPrintf( DBG_ERROR, DBG_FACILITY_JETBLUE, DBGLEVEL_FUNCTION_ERROR, _TEXT("Can't open table %s, error code %d\n"), m_LicensedTable.GetTableName(), m_LicensedTable.GetLastJetError() );
goto cleanup; }
cleanup: return bSuccess; }
|