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 --- src/modules/database/database.h | 49 +++++++ src/modules/database/dbintf.cpp | 22 +++ src/modules/database/mdatabasecache.cpp | 233 ++++++++++++++++++++++++++++++++ 3 files changed, 304 insertions(+) create mode 100644 src/modules/database/database.h create mode 100644 src/modules/database/mdatabasecache.cpp (limited to 'src/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