From 8cb2a99e08a3f8fadc3b39f00228efa7d2b20050 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 3 Oct 2012 18:27:17 +0000 Subject: database cache migration, phase 1 git-svn-id: http://svn.miranda-ng.org/main/trunk@1772 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- include/m_db_int.h | 57 ++++++++ plugins/Db3x_mmap/src/dbcontacts.cpp | 81 +++-------- plugins/Db3x_mmap/src/dbintf.cpp | 34 ++--- plugins/Db3x_mmap/src/dbintf.h | 47 +------ plugins/Db3x_mmap/src/dbsettings.cpp | 189 +++----------------------- plugins/Dbx_tree/DataBase.cpp | 9 +- src/miranda32_10.vcxproj | 4 + src/miranda32_10.vcxproj.filters | 6 + src/modules/database/database.h | 49 +++++++ src/modules/database/dbintf.cpp | 22 +++ src/modules/database/mdatabasecache.cpp | 233 ++++++++++++++++++++++++++++++++ 11 files changed, 425 insertions(+), 306 deletions(-) create mode 100644 src/modules/database/database.h create mode 100644 src/modules/database/mdatabasecache.cpp diff --git a/include/m_db_int.h b/include/m_db_int.h index df6671a486..cd498c5330 100644 --- a/include/m_db_int.h +++ b/include/m_db_int.h @@ -31,8 +31,43 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /////////////////////////////////////////////////////////////////////////////// // basic database interface +struct DBCachedGlobalValue +{ + char* name; + DBVARIANT value; +}; + +struct DBCachedContactValue +{ + char* name; + DBVARIANT value; + DBCachedContactValue* next; +}; + +struct DBCachedContact +{ + HANDLE hContact; + HANDLE hNext; + DBCachedContactValue* first; + DBCachedContactValue* last; +}; + +interface MIDatabaseCache +{ + STDMETHOD_(DBCachedContact*,AddContactToCache)(HANDLE hContact) PURE; + STDMETHOD_(DBCachedContact*,GetCachedContact)(HANDLE hContact) PURE; + STDMETHOD_(void,FreeCachedContact)(HANDLE hContact) PURE; + + STDMETHOD_(char*,InsertCachedSetting)(const char *szName, int) PURE; + STDMETHOD_(char*,GetCachedSetting)(const char *szModuleName, const char *szSettingName, int, int) PURE; + STDMETHOD_(void,SetCachedVariant)(DBVARIANT *s, DBVARIANT *d) PURE; + STDMETHOD_(DBVARIANT*,GetCachedValuePtr)(HANDLE hContact, char *szSetting, int bAllocate) PURE; +}; + interface MIDatabase { + MIDatabaseCache* m_cache; + STDMETHOD_(void,SetCacheSafetyMode)(BOOL) PURE; STDMETHOD_(LONG,GetContactCount)(void) PURE; @@ -194,4 +229,26 @@ __forceinline MIDatabase* GetCurrentDatabase(void) { return (MIDatabase*)CallService(MS_DB_GET_CURRENT, 0, 0); } +// MS_DB_INIT_INSTANCE : initializes a database instance +// wParam : 0 (unused) +// lParam : MIDatabase* = pointer to a database instance +// returns 0 + +#define MS_DB_INIT_INSTANCE "DB/InitDbInstance" + +__forceinline void InitDbInstance(MIDatabase* pDatabase) +{ CallService(MS_DB_INIT_INSTANCE, 0, (LPARAM)pDatabase); +} + +// MS_DB_DESTROY_INSTANCE : destroys a database instance +// wParam : 0 (unused) +// lParam : MIDatabase* = pointer to a database instance +// returns 0 + +#define MS_DB_DESTROY_INSTANCE "DB/DestroyDbInstance" + +__forceinline void DestroyDbInstance(MIDatabase* pDatabase) +{ CallService(MS_DB_DESTROY_INSTANCE, 0, (LPARAM)pDatabase); +} + #endif // M_DB_INT_H__ diff --git a/plugins/Db3x_mmap/src/dbcontacts.cpp b/plugins/Db3x_mmap/src/dbcontacts.cpp index 7dcbdc6206..c8be49a189 100644 --- a/plugins/Db3x_mmap/src/dbcontacts.cpp +++ b/plugins/Db3x_mmap/src/dbcontacts.cpp @@ -23,34 +23,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "commonheaders.h" -DBCachedContactValueList* CDb3Base::AddToCachedContactList(HANDLE hContact, int index) -{ - DBCachedContactValueList* VL = (DBCachedContactValueList*)HeapAlloc(m_hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList)); - VL->hContact = hContact; - if (index == -1) - m_lContacts.insert(VL); - else - m_lContacts.insert(VL,index); - return VL; -} - -#define proto_module "Protocol" -#define proto_setting "p" - int CDb3Base::CheckProto(HANDLE hContact, const char *proto) { char protobuf[MAX_PATH] = {0}; DBVARIANT dbv; - DBCONTACTGETSETTING sVal = {proto_module,proto_setting,&dbv}; + DBCONTACTGETSETTING sVal = { "Protocol", "p", &dbv }; dbv.type = DBVT_ASCIIZ; dbv.pszVal = protobuf; dbv.cchVal = sizeof(protobuf); - if (GetContactSettingStatic(hContact, &sVal) != 0 || (dbv.type != DBVT_ASCIIZ)) + if ( GetContactSettingStatic(hContact, &sVal) != 0 || (dbv.type != DBVT_ASCIIZ)) return 0; - return !strcmp(protobuf,proto); + return !strcmp(protobuf, proto); } STDMETHODIMP_(LONG) CDb3Base::GetContactCount(void) @@ -70,34 +56,30 @@ STDMETHODIMP_(HANDLE) CDb3Base::FindFirstContact(const char *szProto) STDMETHODIMP_(HANDLE) CDb3Base::FindNextContact(HANDLE hContact, const char *szProto) { - DBCachedContactValueList VLtemp, *VL = NULL; - VLtemp.hContact = hContact; - mir_cslock lck(m_csDbAccess); - while (VLtemp.hContact) { - int index; - if (( index = m_lContacts.getIndex(&VLtemp)) != -1) { - VL = m_lContacts[index]; + while (hContact) { + DBCachedContact *VL = m_cache->GetCachedContact(hContact); + if (VL != NULL) { if (VL->hNext != NULL) { if (!szProto || CheckProto(VL->hNext, szProto)) return VL->hNext; - VLtemp.hContact = VL->hNext; + hContact = VL->hNext; continue; } } - DBContact *dbc = (DBContact*)DBRead(VLtemp.hContact,sizeof(DBContact),NULL); + DBContact *dbc = (DBContact*)DBRead(hContact, sizeof(DBContact), NULL); if (dbc->signature != DBCONTACT_SIGNATURE) break; - if ( VL == NULL ) - VL = AddToCachedContactList(VLtemp.hContact,index); + if (VL == NULL) + VL = m_cache->AddContactToCache(hContact); VL->hNext = (HANDLE)dbc->ofsNext; if (VL->hNext != NULL && (!szProto || CheckProto(VL->hNext, szProto))) return VL->hNext; - VLtemp.hContact = VL->hNext; + hContact = VL->hNext; } return NULL; @@ -127,24 +109,9 @@ STDMETHODIMP_(LONG) CDb3Base::DeleteContact(HANDLE hContact) // get back in lck.lock(); - DBCachedContactValueList VLtemp; - VLtemp.hContact = hContact; - int index; - if ((index = m_lContacts.getIndex(&VLtemp)) != -1) { - DBCachedContactValueList *VL = m_lContacts[index]; - DBCachedContactValue* V = VL->first; - while ( V != NULL ) { - DBCachedContactValue* V1 = V->next; - FreeCachedVariant(&V->value); - HeapFree( m_hCacheHeap, 0, V ); - V = V1; - } - HeapFree( m_hCacheHeap, 0, VL ); - - if (VLtemp.hContact == m_hLastCachedContact) - m_hLastCachedContact = NULL; - m_lContacts.remove(index); - } + m_cache->FreeCachedContact(hContact); + if (hContact == m_hLastCachedContact) + m_hLastCachedContact = NULL; dbc = (DBContact*)DBRead(hContact, sizeof(DBContact), NULL); //delete settings chain @@ -182,12 +149,9 @@ STDMETHODIMP_(LONG) CDb3Base::DeleteContact(HANDLE hContact) dbcPrev->ofsNext = ofsNext; DBWrite(ofsThis,dbcPrev,sizeof(DBContact)); - DBCachedContactValueList VLtemp; - VLtemp.hContact = (HANDLE)ofsThis; - if ((index = m_lContacts.getIndex(&VLtemp)) != -1) { - DBCachedContactValueList *VL = m_lContacts[index]; + DBCachedContact *VL = m_cache->GetCachedContact((HANDLE)ofsThis); + if (VL) VL->hNext = (HANDLE)ofsNext; - } } //delete contact @@ -215,9 +179,8 @@ STDMETHODIMP_(HANDLE) CDb3Base::AddContact() DBWrite(ofsNew,&dbc,sizeof(DBContact)); DBWrite(0,&m_dbHeader,sizeof(m_dbHeader)); DBFlush(0); - - AddToCachedContactList((HANDLE)ofsNew, -1); } + m_cache->AddContactToCache((HANDLE)ofsNew); NotifyEventHooks(hContactAddedEvent,(WPARAM)ofsNew,0); return (HANDLE)ofsNew; @@ -225,17 +188,13 @@ STDMETHODIMP_(HANDLE) CDb3Base::AddContact() STDMETHODIMP_(BOOL) CDb3Base::IsDbContact(HANDLE hContact) { - mir_cslock lck(m_csDbAccess); - - DBCachedContactValueList VLtemp; - VLtemp.hContact = hContact; - int index = m_lContacts.getIndex(&VLtemp); - if (index != -1) + if (m_cache->GetCachedContact(hContact)) return TRUE; + mir_cslock lck(m_csDbAccess); DBContact *dbc = (DBContact*)DBRead(hContact,sizeof(DBContact),NULL); if (dbc->signature == DBCONTACT_SIGNATURE) { - AddToCachedContactList(hContact, index); + m_cache->AddContactToCache(hContact); return TRUE; } diff --git a/plugins/Db3x_mmap/src/dbintf.cpp b/plugins/Db3x_mmap/src/dbintf.cpp index 34a34ab6ab..be56756d35 100644 --- a/plugins/Db3x_mmap/src/dbintf.cpp +++ b/plugins/Db3x_mmap/src/dbintf.cpp @@ -25,21 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. DBSignature dbSignature = {"Miranda ICQ DB",0x1A}; -static int stringCompare(const char* p1, const char* p2) -{ - return strcmp(p1+1, p2+1); -} - -static int stringCompare2(const char* p1, const char* p2) -{ - return strcmp(p1, p2); -} - -static int compareGlobals(const DBCachedGlobalValue* p1, const DBCachedGlobalValue* p2) -{ - return strcmp(p1->name, p2->name); -} - static int ModCompare(const ModuleName *mn1, const ModuleName *mn2 ) { return strcmp( mn1->name, mn2->name ); @@ -50,18 +35,20 @@ static int OfsCompare(const ModuleName *mn1, const ModuleName *mn2 ) return ( mn1->ofs - mn2->ofs ); } +static int stringCompare2(const char* p1, const char* p2) +{ return strcmp(p1, p2); +} + CDb3Base::CDb3Base(const TCHAR* tszFileName) : m_hDbFile(INVALID_HANDLE_VALUE), m_safetyMode(true), m_bReadOnly(true), - m_lSettings(100, stringCompare), - m_lContacts(50, LIST::FTSortFunc(HandleKeySort)), - m_lGlobalSettings(50, compareGlobals), - m_lResidentSettings(50, stringCompare2), m_lMods(50, ModCompare), - m_lOfs(50, OfsCompare) + m_lOfs(50, OfsCompare), + m_lResidentSettings(50, stringCompare2) { m_tszProfileName = mir_tstrdup(tszFileName); + InitDbInstance(this); InitializeCriticalSection(&m_csDbAccess); @@ -70,17 +57,11 @@ CDb3Base::CDb3Base(const TCHAR* tszFileName) : m_ChunkSize = sinf.dwAllocationGranularity; m_codePage = CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); - m_hCacheHeap = HeapCreate(0, 0, 0); m_hModHeap = HeapCreate(0,0,0); } CDb3Base::~CDb3Base() { - // destroy settings - HeapDestroy(m_hCacheHeap); - m_lContacts.destroy(); - m_lSettings.destroy(); - m_lGlobalSettings.destroy(); m_lResidentSettings.destroy(); // destroy modules @@ -108,6 +89,7 @@ CDb3Base::~CDb3Base() DeleteCriticalSection(&m_csDbAccess); + DestroyDbInstance(this); mir_free(m_tszProfileName); } diff --git a/plugins/Db3x_mmap/src/dbintf.h b/plugins/Db3x_mmap/src/dbintf.h index d5bef059ef..a810b36876 100644 --- a/plugins/Db3x_mmap/src/dbintf.h +++ b/plugins/Db3x_mmap/src/dbintf.h @@ -136,27 +136,6 @@ struct DBEvent #include -struct DBCachedGlobalValue -{ - char* name; - DBVARIANT value; -}; - -struct DBCachedContactValue -{ - char* name; - DBVARIANT value; - DBCachedContactValue* next; -}; - -struct DBCachedContactValueList -{ - HANDLE hContact; - HANDLE hNext; - DBCachedContactValue* first; - DBCachedContactValue* last; -}; - #define MAXCACHEDREADSIZE 65536 struct CDb3Base : public MIDatabase, public MIDatabaseChecker, public MZeroedObject @@ -255,6 +234,7 @@ public: protected: DWORD m_dwFileSize; + HANDLE hSettingChangeEvent, hContactDeletedEvent, hContactAddedEvent; CRITICAL_SECTION m_csDbAccess; @@ -272,34 +252,14 @@ protected: int m_codePage; - HANDLE m_hCacheHeap; - HANDLE m_hLastCachedContact; - char* m_lastSetting; - DBCachedContactValueList *m_lastVL; - - LIST m_lContacts; - LIST m_lGlobalSettings; - LIST m_lSettings, m_lResidentSettings; - HANDLE hSettingChangeEvent, hContactDeletedEvent, hContactAddedEvent; - - char* InsertCachedSetting(const char* szName, size_t cbNameLen); - char* GetCachedSetting(const char *szModuleName,const char *szSettingName, int moduleNameLen, int settingNameLen); - void SetCachedVariant(DBVARIANT* s, DBVARIANT* d); - void FreeCachedVariant(DBVARIANT* V); - DBVARIANT* GetCachedValuePtr(HANDLE hContact, char* szSetting, int bAllocate); - int GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs,int isStatic); - - //////////////////////////////////////////////////////////////////////////// - // contacts - - DBCachedContactValueList* AddToCachedContactList(HANDLE hContact, int index); - //////////////////////////////////////////////////////////////////////////// // modules HANDLE m_hModHeap; LIST m_lMods, m_lOfs; + LIST m_lResidentSettings; HANDLE hEventAddedEvent, hEventDeletedEvent, hEventFilterAddedEvent; + HANDLE m_hLastCachedContact; ModuleName *m_lastmn; void AddToList(char *name, DWORD len, DWORD ofs); @@ -320,6 +280,7 @@ protected: DWORD ConvertModuleNameOfs(DWORD ofsOld); void ConvertOldEvent(DBEvent*& dbei); + int GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs,int isStatic); int WorkSettingsChain(DWORD ofsContact, DBContact *dbc, int firstTime); int WorkEventChain(DWORD ofsContact, DBContact *dbc, int firstTime); diff --git a/plugins/Db3x_mmap/src/dbsettings.cpp b/plugins/Db3x_mmap/src/dbsettings.cpp index fedc5f60d2..872d482e27 100644 --- a/plugins/Db3x_mmap/src/dbsettings.cpp +++ b/plugins/Db3x_mmap/src/dbsettings.cpp @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "commonheaders.h" DWORD GetModuleNameOfs(const char *szName); -DBCachedContactValueList* AddToCachedContactList(HANDLE hContact, int index); +DBCachedContact* AddToCachedContactList(HANDLE hContact, int index); int DBPreset_QuerySetting(const char *szModule, const char *szSetting, DBVARIANT *dbv, BOOL isStatic); @@ -35,154 +35,6 @@ DWORD __forceinline GetSettingValueLength(PBYTE pSetting) return pSetting[0]; } -char* CDb3Base::InsertCachedSetting(const char* szName, size_t cbNameLen) -{ - char* newValue = (char*)HeapAlloc(m_hCacheHeap, 0, cbNameLen); - *newValue = 0; - strcpy(newValue+1, szName+1); - m_lSettings.insert(newValue); - return newValue; -} - -char* CDb3Base::GetCachedSetting(const char *szModuleName,const char *szSettingName, int moduleNameLen, int settingNameLen) -{ - char szFullName[512]; - strcpy(szFullName+1,szModuleName); - szFullName[moduleNameLen+1] = '/'; - strcpy(szFullName+moduleNameLen+2,szSettingName); - - if (m_lastSetting && strcmp(szFullName+1, m_lastSetting) == 0) - return m_lastSetting; - - int index = m_lSettings.getIndex(szFullName); - if (index != -1) - m_lastSetting = m_lSettings[index]+1; - else - m_lastSetting = InsertCachedSetting( szFullName, settingNameLen+moduleNameLen+3)+1; - - return m_lastSetting; -} - -void CDb3Base::SetCachedVariant( DBVARIANT* s /* new */, DBVARIANT* d /* cached */ ) -{ - char* szSave = ( d->type == DBVT_UTF8 || d->type == DBVT_ASCIIZ ) ? d->pszVal : NULL; - - memcpy( d, s, sizeof( DBVARIANT )); - if (( s->type == DBVT_UTF8 || s->type == DBVT_ASCIIZ ) && s->pszVal != NULL ) { - if ( szSave != NULL ) - d->pszVal = (char*)HeapReAlloc(m_hCacheHeap,0,szSave,strlen(s->pszVal)+1); - else - d->pszVal = (char*)HeapAlloc(m_hCacheHeap,0,strlen(s->pszVal)+1); - strcpy(d->pszVal,s->pszVal); - } - else if ( szSave != NULL ) - HeapFree(m_hCacheHeap,0,szSave); - -#ifdef DBLOGGING - switch( d->type ) { - case DBVT_BYTE: log1( "set cached byte: %d", d->bVal ); break; - case DBVT_WORD: log1( "set cached word: %d", d->wVal ); break; - case DBVT_DWORD: log1( "set cached dword: %d", d->dVal ); break; - case DBVT_UTF8: - case DBVT_ASCIIZ: log1( "set cached string: '%s'", d->pszVal ); break; - default: log1( "set cached crap: %d", d->type ); break; - } -#endif -} - -void CDb3Base::FreeCachedVariant( DBVARIANT* V ) -{ - if (( V->type == DBVT_ASCIIZ || V->type == DBVT_UTF8 ) && V->pszVal != NULL ) - HeapFree(m_hCacheHeap,0,V->pszVal); -} - -DBVARIANT* CDb3Base::GetCachedValuePtr( HANDLE hContact, char* szSetting, int bAllocate ) -{ - if ( hContact == 0 ) { - DBCachedGlobalValue Vtemp, *V; - Vtemp.name = szSetting; - int index = m_lGlobalSettings.getIndex(&Vtemp); - if (index != -1) { - V = m_lGlobalSettings[index]; - if ( bAllocate == -1 ) { - FreeCachedVariant( &V->value ); - m_lGlobalSettings.remove(index); - HeapFree(m_hCacheHeap,0,V); - return NULL; - } - } - else { - if ( bAllocate != 1 ) - return NULL; - - V = (DBCachedGlobalValue*)HeapAlloc(m_hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedGlobalValue)); - V->name = szSetting; - m_lGlobalSettings.insert(V); - } - - return &V->value; - } - else { - DBCachedContactValue *V, *V1; - DBCachedContactValueList VLtemp,*VL; - - if (m_hLastCachedContact == hContact && m_lastVL) - VL = m_lastVL; - else { - VLtemp.hContact = hContact; - - int index = m_lContacts.getIndex(&VLtemp); - if (index == -1) { - if ( bAllocate != 1 ) - return NULL; - - VL = AddToCachedContactList(hContact, index); - } - else VL = m_lContacts[index]; - - m_lastVL = VL; - m_hLastCachedContact = hContact; - } - - for ( V = VL->first; V != NULL; V = V->next) - if (V->name == szSetting) - break; - - if ( V == NULL ) { - if ( bAllocate != 1 ) - return NULL; - - V = (DBCachedContactValue *)HeapAlloc(m_hCacheHeap, HEAP_ZERO_MEMORY, sizeof(DBCachedContactValue)); - if (VL->last) - VL->last->next = V; - else - VL->first = V; - VL->last = V; - V->name = szSetting; - } - else if ( bAllocate == -1 ) { - m_lastVL = NULL; - FreeCachedVariant(&V->value); - if ( VL->first == V ) { - VL->first = V->next; - if (VL->last == V) - VL->last = V->next; // NULL - } - else - for ( V1 = VL->first; V1 != NULL; V1 = V1->next ) - if ( V1->next == V ) { - V1->next = V->next; - if (VL->last == V) - VL->last = V1; - break; - } - HeapFree(m_hCacheHeap,0,V); - return NULL; - } - - return &V->value; -} } - #define NeedBytes(n) if (bytesRemaining<(n)) pBlob = (PBYTE)DBRead(ofsBlobPtr,(n),&bytesRemaining) #define MoveAlong(n) {int x = n; pBlob += (x); ofsBlobPtr += (x); bytesRemaining -= (x);} #define VLT(n) ((n == DBVT_UTF8)?DBVT_ASCIIZ:n) @@ -219,9 +71,9 @@ int CDb3Base::GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs log3("get [%08p] %s/%s",hContact,dbcgs->szModule,dbcgs->szSetting); - szCachedSettingName = GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,moduleNameLen,settingNameLen); + szCachedSettingName = m_cache->GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,moduleNameLen,settingNameLen); { - DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 0 ); + DBVARIANT* pCachedValue = m_cache->GetCachedValuePtr(hContact, szCachedSettingName, 0); if ( pCachedValue != NULL ) { if ( pCachedValue->type == DBVT_ASCIIZ || pCachedValue->type == DBVT_UTF8 ) { int cbOrigLen = dbcgs->pValue->cchVal; @@ -320,9 +172,9 @@ int CDb3Base::GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs /**** add to cache **********************/ if ( dbcgs->pValue->type != DBVT_BLOB ) { - DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 1 ); + DBVARIANT* pCachedValue = m_cache->GetCachedValuePtr( hContact, szCachedSettingName, 1 ); if ( pCachedValue != NULL ) - SetCachedVariant(dbcgs->pValue,pCachedValue); + m_cache->SetCachedVariant(dbcgs->pValue, pCachedValue); } logg(); @@ -351,7 +203,7 @@ int CDb3Base::GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs /**** add missing setting to cache **********************/ if ( dbcgs->pValue->type != DBVT_BLOB ) { - DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 1 ); + DBVARIANT* pCachedValue = m_cache->GetCachedValuePtr( hContact, szCachedSettingName, 1 ); if ( pCachedValue != NULL ) pCachedValue->type = DBVT_DELETED; } @@ -479,22 +331,13 @@ STDMETHODIMP_(BOOL) CDb3Base::FreeVariant(DBVARIANT *dbv) STDMETHODIMP_(BOOL) CDb3Base::SetSettingResident(BOOL bIsResident, const char *pszSettingName) { - size_t cbSettingNameLen = strlen(pszSettingName) + 2; + int cbSettingNameLen = (int)strlen(pszSettingName) + 2; if (cbSettingNameLen < 512) { - char* szSetting; - char szTemp[512]; - strcpy( szTemp+1, pszSettingName); - - mir_cslock lck(m_csDbAccess); - int idx = m_lSettings.getIndex(szTemp); - if (idx == -1) - szSetting = InsertCachedSetting( szTemp, cbSettingNameLen); - else - szSetting = m_lSettings[idx]; - + char *szSetting = m_cache->InsertCachedSetting(pszSettingName, cbSettingNameLen); *szSetting = (char)bIsResident; - idx = m_lResidentSettings.getIndex(szSetting+1); + mir_cslock lck(m_csDbAccess); + int idx = m_lResidentSettings.getIndex(szSetting+1); if (idx == -1) { if (bIsResident) m_lResidentSettings.insert(szSetting+1); @@ -574,9 +417,9 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT mir_cslockfull lck(m_csDbAccess); - char* szCachedSettingName = GetCachedSetting(tmp.szModule, tmp.szSetting, moduleNameLen, settingNameLen); + char* szCachedSettingName = m_cache->GetCachedSetting(tmp.szModule, tmp.szSetting, moduleNameLen, settingNameLen); if ( tmp.value.type != DBVT_BLOB ) { - DBVARIANT* pCachedValue = GetCachedValuePtr(hContact, szCachedSettingName, 1); + DBVARIANT* pCachedValue = m_cache->GetCachedValuePtr(hContact, szCachedSettingName, 1); if ( pCachedValue != NULL ) { BOOL bIsIdentical = FALSE; if ( pCachedValue->type == tmp.value.type ) { @@ -590,7 +433,7 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT if ( bIsIdentical ) return 0; } - SetCachedVariant(&tmp.value, pCachedValue); + m_cache->SetCachedVariant(&tmp.value, pCachedValue); } if ( szCachedSettingName[-1] != 0 ) { lck.unlock(); @@ -598,7 +441,7 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT return 0; } } - else GetCachedValuePtr(hContact, szCachedSettingName, -1); + else m_cache->GetCachedValuePtr(hContact, szCachedSettingName, -1); ofsModuleName = GetModuleNameOfs(tmp.szModule); if (hContact == 0) ofsContact = m_dbHeader.ofsUser; @@ -851,8 +694,8 @@ STDMETHODIMP_(BOOL) CDb3Base::DeleteContactSetting(HANDLE hContact, DBCONTACTGET } DBMoveChunk(ofsSettingToCut,ofsSettingToCut+nameLen+valLen,ofsBlobPtr+1-ofsSettingToCut); - szCachedSettingName = GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,moduleNameLen,settingNameLen); - GetCachedValuePtr((HANDLE)saveWparam, szCachedSettingName, -1 ); + szCachedSettingName = m_cache->GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,moduleNameLen,settingNameLen); + m_cache->GetCachedValuePtr((HANDLE)saveWparam, szCachedSettingName, -1 ); //quit DBFlush(1); diff --git a/plugins/Dbx_tree/DataBase.cpp b/plugins/Dbx_tree/DataBase.cpp index 033e472c9d..50fe494b3c 100644 --- a/plugins/Dbx_tree/DataBase.cpp +++ b/plugins/Dbx_tree/DataBase.cpp @@ -31,12 +31,13 @@ CDataBase *gDataBase = NULL; CDataBase::CDataBase(const TCHAR *FileName) { - int len = _tcslen(FileName); + InitDbInstance(this); + + size_t len = _tcslen(FileName); m_FileName[0] = new TCHAR[len + 1]; _tcsncpy_s(m_FileName[0], len + 1, FileName, len); m_FileName[0][len] = 0; - TCHAR * tmp = _tcsrchr(m_FileName[0], '.'); if (tmp) { @@ -62,6 +63,7 @@ CDataBase::CDataBase(const TCHAR *FileName) m_Entities = NULL; m_Settings = NULL; m_Events = NULL; + } CDataBase::~CDataBase() { @@ -85,8 +87,9 @@ CDataBase::~CDataBase() delete [] (m_FileName[i]); } - + DestroyDbInstance(this); } + int CDataBase::CreateDB() { /// TODO: create and show wizard diff --git a/src/miranda32_10.vcxproj b/src/miranda32_10.vcxproj index ca0f8ffa35..5707d30e91 100644 --- a/src/miranda32_10.vcxproj +++ b/src/miranda32_10.vcxproj @@ -244,6 +244,7 @@ + @@ -299,6 +300,9 @@ ..\..\core\commonheaders.h + + ..\..\core\commonheaders.h + ..\..\core\commonheaders.h diff --git a/src/miranda32_10.vcxproj.filters b/src/miranda32_10.vcxproj.filters index dd95088c4f..fb7f03cd6e 100644 --- a/src/miranda32_10.vcxproj.filters +++ b/src/miranda32_10.vcxproj.filters @@ -270,6 +270,9 @@ Modules\database + + Modules\database + @@ -572,6 +575,9 @@ Modules\clist + + Modules\database + diff --git a/src/modules/database/database.h b/src/modules/database/database.h new file mode 100644 index 0000000000..b0b5717e0b --- /dev/null +++ b/src/modules/database/database.h @@ -0,0 +1,49 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright 2012 Miranda NG project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +class MDatabaseCache : public MIDatabaseCache, public MZeroedObject +{ + HANDLE m_hCacheHeap; + char* m_lastSetting; + DBCachedContact *m_lastVL; + + LIST m_lContacts; + LIST m_lGlobalSettings; + LIST m_lSettings; + + void FreeCachedVariant(DBVARIANT* V); + +public: + MDatabaseCache(); + ~MDatabaseCache(); + +protected: + STDMETHODIMP_(DBCachedContact*) AddContactToCache(HANDLE hContact); + STDMETHODIMP_(DBCachedContact*) GetCachedContact(HANDLE hContact); + STDMETHODIMP_(void) FreeCachedContact(HANDLE hContact); + + STDMETHODIMP_(char*) InsertCachedSetting(const char *szName, int); + STDMETHODIMP_(char*) GetCachedSetting(const char *szModuleName, const char *szSettingName, int, int); + STDMETHODIMP_(void) SetCachedVariant(DBVARIANT *s, DBVARIANT *d); + STDMETHODIMP_(DBVARIANT*) GetCachedValuePtr(HANDLE hContact, char *szSetting, int bAllocate); +}; diff --git a/src/modules/database/dbintf.cpp b/src/modules/database/dbintf.cpp index 6c6371e6ec..da83e284d2 100644 --- a/src/modules/database/dbintf.cpp +++ b/src/modules/database/dbintf.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "..\..\core\commonheaders.h" +#include "database.h" MIDatabase *currDb = NULL; DATABASELINK *currDblink = NULL; @@ -191,6 +192,24 @@ static INT_PTR srvGetCurrentDb(WPARAM wParam,LPARAM lParam) return (INT_PTR)currDb; } +static INT_PTR srvInitInstance(WPARAM wParam,LPARAM lParam) +{ + MIDatabase* pDb = (MIDatabase*)lParam; + if (pDb != NULL) + pDb->m_cache = new MDatabaseCache(); + return 0; +} + +static INT_PTR srvDestroyInstance(WPARAM wParam,LPARAM lParam) +{ + MIDatabase* pDb = (MIDatabase*)lParam; + if (pDb != NULL) { + delete pDb->m_cache; + pDb->m_cache = NULL; + } + return 0; +} + /////////////////////////////////////////////////////////////////////////////// int LoadDbintfModule() @@ -232,5 +251,8 @@ int LoadDbintfModule() CreateServiceFunction(MS_DB_REGISTER_PLUGIN, srvRegisterPlugin); CreateServiceFunction(MS_DB_FIND_PLUGIN, srvFindPlugin); CreateServiceFunction(MS_DB_GET_CURRENT, srvGetCurrentDb); + + CreateServiceFunction(MS_DB_INIT_INSTANCE, srvInitInstance); + CreateServiceFunction(MS_DB_DESTROY_INSTANCE, srvDestroyInstance); return 0; } diff --git a/src/modules/database/mdatabasecache.cpp b/src/modules/database/mdatabasecache.cpp new file mode 100644 index 0000000000..abb24dd0fe --- /dev/null +++ b/src/modules/database/mdatabasecache.cpp @@ -0,0 +1,233 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "..\..\core\commonheaders.h" +#include "database.h" + +static int stringCompare(const char* p1, const char* p2) +{ return strcmp(p1+1, p2+1); +} + +static int compareGlobals(const DBCachedGlobalValue* p1, const DBCachedGlobalValue* p2) +{ return strcmp(p1->name, p2->name); +} + +MDatabaseCache::MDatabaseCache() : + m_lSettings(100, stringCompare), + m_lContacts(50, LIST::FTSortFunc(HandleKeySort)), + m_lGlobalSettings(50, compareGlobals) +{ + m_hCacheHeap = HeapCreate(0, 0, 0); +} + +MDatabaseCache::~MDatabaseCache() +{ + HeapDestroy(m_hCacheHeap); + m_lContacts.destroy(); + m_lSettings.destroy(); + m_lGlobalSettings.destroy(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +DBCachedContact* MDatabaseCache::AddContactToCache(HANDLE hContact) +{ + DBCachedContact* VL = (DBCachedContact*)HeapAlloc(m_hCacheHeap, HEAP_ZERO_MEMORY, sizeof(DBCachedContact)); + VL->hContact = hContact; + m_lContacts.insert(VL); + return VL; +} + +DBCachedContact* MDatabaseCache::GetCachedContact(HANDLE hContact) +{ + DBCachedContact VLtemp = { hContact }; + int index = m_lContacts.getIndex(&VLtemp); + return (index == -1) ? NULL : m_lContacts[index]; +} + +void MDatabaseCache::FreeCachedContact(HANDLE hContact) +{ + DBCachedContact VLtemp = { hContact }; + int index = m_lContacts.getIndex(&VLtemp); + if (index == -1) + return; + + DBCachedContact* VL = m_lContacts[index]; + DBCachedContactValue* V = VL->first; + while (V != NULL) { + DBCachedContactValue* V1 = V->next; + FreeCachedVariant(&V->value); + HeapFree( m_hCacheHeap, 0, V ); + V = V1; + } + HeapFree( m_hCacheHeap, 0, VL ); + + m_lContacts.remove(index); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +char* MDatabaseCache::InsertCachedSetting(const char* szName, int cbLen) +{ + char* newValue = (char*)HeapAlloc(m_hCacheHeap, 0, cbLen); + *newValue = 0; + strcpy(newValue+1, szName+1); + m_lSettings.insert(newValue); + return newValue; +} + +char* MDatabaseCache::GetCachedSetting(const char *szModuleName,const char *szSettingName, int moduleNameLen, int settingNameLen) +{ + char szFullName[512]; + strcpy(szFullName+1,szModuleName); + szFullName[moduleNameLen+1] = '/'; + strcpy(szFullName+moduleNameLen+2,szSettingName); + + if (m_lastSetting && strcmp(szFullName+1, m_lastSetting) == 0) + return m_lastSetting; + + int index = m_lSettings.getIndex(szFullName); + if (index != -1) + m_lastSetting = m_lSettings[index]+1; + else + m_lastSetting = InsertCachedSetting( szFullName, settingNameLen+moduleNameLen+3)+1; + + return m_lastSetting; +} + +void MDatabaseCache::SetCachedVariant(DBVARIANT* s /* new */, DBVARIANT* d /* cached */ ) +{ + char* szSave = ( d->type == DBVT_UTF8 || d->type == DBVT_ASCIIZ ) ? d->pszVal : NULL; + + memcpy( d, s, sizeof( DBVARIANT )); + if (( s->type == DBVT_UTF8 || s->type == DBVT_ASCIIZ ) && s->pszVal != NULL ) { + if ( szSave != NULL ) + d->pszVal = (char*)HeapReAlloc(m_hCacheHeap,0,szSave,strlen(s->pszVal)+1); + else + d->pszVal = (char*)HeapAlloc(m_hCacheHeap,0,strlen(s->pszVal)+1); + strcpy(d->pszVal,s->pszVal); + } + else if ( szSave != NULL ) + HeapFree(m_hCacheHeap,0,szSave); + +#ifdef DBLOGGING + switch( d->type ) { + case DBVT_BYTE: log1( "set cached byte: %d", d->bVal ); break; + case DBVT_WORD: log1( "set cached word: %d", d->wVal ); break; + case DBVT_DWORD: log1( "set cached dword: %d", d->dVal ); break; + case DBVT_UTF8: + case DBVT_ASCIIZ: log1( "set cached string: '%s'", d->pszVal ); break; + default: log1( "set cached crap: %d", d->type ); break; + } +#endif +} + +void MDatabaseCache::FreeCachedVariant(DBVARIANT* V) +{ + if (( V->type == DBVT_ASCIIZ || V->type == DBVT_UTF8 ) && V->pszVal != NULL ) + HeapFree(m_hCacheHeap,0,V->pszVal); +} + +STDMETHODIMP_(DBVARIANT*) MDatabaseCache::GetCachedValuePtr(HANDLE hContact, char *szSetting, int bAllocate) +{ + // a global setting + if ( hContact == 0 ) { + DBCachedGlobalValue Vtemp, *V; + Vtemp.name = szSetting; + int index = m_lGlobalSettings.getIndex(&Vtemp); + if (index != -1) { + V = m_lGlobalSettings[index]; + if ( bAllocate == -1 ) { + FreeCachedVariant( &V->value ); + m_lGlobalSettings.remove(index); + HeapFree(m_hCacheHeap,0,V); + return NULL; + } + } + else { + if ( bAllocate != 1 ) + return NULL; + + V = (DBCachedGlobalValue*)HeapAlloc(m_hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedGlobalValue)); + V->name = szSetting; + m_lGlobalSettings.insert(V); + } + + return &V->value; + } + + // a contact setting + DBCachedContactValue *V, *V1; + DBCachedContact VLtemp,*VL; + + VLtemp.hContact = hContact; + + int index = m_lContacts.getIndex(&VLtemp); + if (index == -1) { + if ( bAllocate != 1 ) + return NULL; + + VL = AddContactToCache(hContact); + } + else VL = m_lContacts[index]; + + m_lastVL = VL; + + for ( V = VL->first; V != NULL; V = V->next) + if (V->name == szSetting) + break; + + if ( V == NULL ) { + if ( bAllocate != 1 ) + return NULL; + + V = (DBCachedContactValue *)HeapAlloc(m_hCacheHeap, HEAP_ZERO_MEMORY, sizeof(DBCachedContactValue)); + if (VL->last) + VL->last->next = V; + else + VL->first = V; + VL->last = V; + V->name = szSetting; + } + else if ( bAllocate == -1 ) { + m_lastVL = NULL; + FreeCachedVariant(&V->value); + if ( VL->first == V ) { + VL->first = V->next; + if (VL->last == V) + VL->last = V->next; // NULL + } + else + for ( V1 = VL->first; V1 != NULL; V1 = V1->next ) + if ( V1->next == V ) { + V1->next = V->next; + if (VL->last == V) + VL->last = V1; + break; + } + HeapFree(m_hCacheHeap,0,V); + return NULL; + } + + return &V->value; +} -- cgit v1.2.3