void MDatabaseCache::FreeCachedContact(MCONTACT contactID) { mir_cslock lck(m_cs); int index = m_lContacts.getIndex((DBCachedContact*)&contactID); if (index == -1) return; DBCachedContact *cc = m_lContacts[index]; DBCachedContactValue* V = cc->first; while (V != NULL) { DBCachedContactValue* V1 = V->next; FreeCachedVariant(&V->value); HeapFree(m_hCacheHeap, 0, V); V = V1; } mir_free(cc->pSubs); HeapFree(m_hCacheHeap, 0, cc); m_lContacts.remove(index); }
static DBVARIANT* GetCachedValuePtr( HANDLE hContact, char* szSetting, int bAllocate ) { int index; if ( hContact == 0 ) { DBCachedGlobalValue Vtemp, *V; Vtemp.name = szSetting; if ( li.List_GetIndex(&lGlobalSettings,&Vtemp,&index)) { V = (DBCachedGlobalValue*)lGlobalSettings.items[index]; if ( bAllocate == -1 ) { FreeCachedVariant( &V->value ); li.List_Remove(&lGlobalSettings,index); HeapFree(hCacheHeap,0,V); return NULL; } } else { if ( bAllocate != 1 ) return NULL; V = (DBCachedGlobalValue*)HeapAlloc(hCacheHeap,HEAP_ZERO_MEMORY,sizeof(DBCachedGlobalValue)); V->name = szSetting; li.List_Insert(&lGlobalSettings,V,index); } return &V->value; } else { DBCachedContactValue *V, *V1; DBCachedContactValueList VLtemp,*VL; if (hLastCachedContact==hContact && LastVL) { VL = LastVL; } else { VLtemp.hContact=hContact; if ( !li.List_GetIndex(&lContacts,&VLtemp,&index)) { if ( bAllocate != 1 ) return NULL; VL = AddToCachedContactList(hContact,index); } else VL = (DBCachedContactValueList*)lContacts.items[index]; LastVL = VL; 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 = HeapAlloc(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 ) { 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(hCacheHeap,0,V); return NULL; } return &V->value; } }
STDMETHODIMP_(DBVARIANT*) MDatabaseCache::GetCachedValuePtr(MCONTACT contactID, char *szSetting, int bAllocate) { // a global setting if (contactID == 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.contactID = contactID; int index = m_lContacts.getIndex(&VLtemp); if (index == -1) { if ( bAllocate != 1 ) return NULL; VL = AddContactToCache(contactID); } 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; }
static INT_PTR DeleteContact(WPARAM wParam,LPARAM lParam) { struct DBContact *dbc,*dbcPrev; DWORD ofsThis,ofsNext,ofsFirstEvent; struct DBContactSettings *dbcs; struct DBEvent *dbe; int index; if((HANDLE)wParam==NULL) return 1; EnterCriticalSection(&csDbAccess); dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); if(dbc->signature!=DBCONTACT_SIGNATURE) { LeaveCriticalSection(&csDbAccess); return 1; } if ( (HANDLE)wParam == (HANDLE)dbHeader.ofsUser ) { LeaveCriticalSection(&csDbAccess); log0("FATAL: del of user chain attempted."); return 1; } log0("del contact"); LeaveCriticalSection(&csDbAccess); //call notifier while outside mutex NotifyEventHooks(hContactDeletedEvent,wParam,0); //get back in EnterCriticalSection(&csDbAccess); { DBCachedContactValueList VLtemp; VLtemp.hContact = (HANDLE)wParam; if ( li.List_GetIndex(&lContacts,&VLtemp,&index)) { DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index]; DBCachedContactValue* V = VL->first; while ( V != NULL ) { DBCachedContactValue* V1 = V->next; FreeCachedVariant(&V->value); HeapFree( hCacheHeap, 0, V ); V = V1; } HeapFree( hCacheHeap, 0, VL ); if (VLtemp.hContact == hLastCachedContact) hLastCachedContact = NULL; li.List_Remove(&lContacts,index); } } dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); //delete settings chain ofsThis=dbc->ofsFirstSettings; ofsFirstEvent=dbc->ofsFirstEvent; while(ofsThis) { dbcs=(struct DBContactSettings*)DBRead(ofsThis,sizeof(struct DBContactSettings),NULL); ofsNext=dbcs->ofsNext; DeleteSpace(ofsThis,offsetof(struct DBContactSettings,blob)+dbcs->cbBlob); ofsThis=ofsNext; } //delete event chain ofsThis=ofsFirstEvent; while(ofsThis) { dbe=(struct DBEvent*)DBRead(ofsThis,sizeof(struct DBEvent),NULL); ofsNext=dbe->ofsNext; DeleteSpace(ofsThis,offsetof(struct DBEvent,blob)+dbe->cbBlob); ofsThis=ofsNext; } //find previous contact in chain and change ofsNext dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); if(dbHeader.ofsFirstContact==wParam) { dbHeader.ofsFirstContact=dbc->ofsNext; DBWrite(0,&dbHeader,sizeof(dbHeader)); } else { ofsNext=dbc->ofsNext; ofsThis=dbHeader.ofsFirstContact; dbcPrev=(struct DBContact*)DBRead(ofsThis,sizeof(struct DBContact),NULL); while(dbcPrev->ofsNext!=wParam) { if(dbcPrev->ofsNext==0) DatabaseCorruption(NULL); ofsThis=dbcPrev->ofsNext; dbcPrev=(struct DBContact*)DBRead(ofsThis,sizeof(struct DBContact),NULL); } dbcPrev->ofsNext=ofsNext; DBWrite(ofsThis,dbcPrev,sizeof(struct DBContact)); { DBCachedContactValueList VLtemp; VLtemp.hContact = (HANDLE)ofsThis; if ( li.List_GetIndex(&lContacts,&VLtemp,&index)) { DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index]; VL->hNext = ( HANDLE )ofsNext; } } } //delete contact DeleteSpace(wParam,sizeof(struct DBContact)); //decrement contact count dbHeader.contactCount--; DBWrite(0,&dbHeader,sizeof(dbHeader)); DBFlush(0); //quit LeaveCriticalSection(&csDbAccess); return 0; }