From f920ef497f3299ae24fe783ce03bdd93b419f764 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Fri, 18 May 2012 22:02:50 +0000 Subject: plugins folders renaming git-svn-id: http://svn.miranda-ng.org/main/trunk@60 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Dbrw/events.c | 461 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 461 insertions(+) create mode 100644 plugins/Dbrw/events.c (limited to 'plugins/Dbrw/events.c') diff --git a/plugins/Dbrw/events.c b/plugins/Dbrw/events.c new file mode 100644 index 0000000000..8b494a10b1 --- /dev/null +++ b/plugins/Dbrw/events.c @@ -0,0 +1,461 @@ +/* +dbRW + +Copyright (c) 2005-2009 Robert Rainwater + +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 "dbrw.h" + +static CRITICAL_SECTION csEventsDb; +static HANDLE hEventsThread = 0, hEventsEvent = 0, hHeap; +static SortedList sModuleNames; + +static int events_cmpModuleNames(void *p1, void *p2); +static unsigned __stdcall events_timerProcThread(void *arg); + +typedef struct { + char *name; + DWORD nameHash; +} DBCachedModuleName; + +enum { + SQL_EVT_STMT_COUNT=0, + SQL_EVT_STMT_ADD, + SQL_EVT_STMT_DELETE, + SQL_EVT_STMT_BLOBSIZE, + SQL_EVT_STMT_BLOBSIZE_CACHE, + SQL_EVT_STMT_GET, + SQL_EVT_STMT_GET_CACHE, + SQL_EVT_STMT_GETFLAGS, + SQL_EVT_STMT_SETFLAGS, + SQL_EVT_STMT_GETCONTACT, + SQL_EVT_STMT_GETCONTACT_CACHE, + SQL_EVT_STMT_FINDFIRST, + SQL_EVT_STMT_FINDFIRSTUNREAD, + SQL_EVT_STMT_FINDLAST, + SQL_EVT_STMT_FINDNEXT, + SQL_EVT_STMT_FINDPREV, + SQL_EVT_STMT_CREATETEMPTABLE, + SQL_EVT_STMT_DROPTEMPTABLE, + SQL_EVT_STMT_DELETECONTACT, + SQL_EVT_STMT_NUM +}; +static char *evt_stmts[SQL_EVT_STMT_NUM] = { + "SELECT count(*) FROM dbrw_events where contactid = ?;", + "INSERT INTO dbrw_events VALUES(NULL,?,?,?,?,?,?,?,?);", + "DELETE FROM dbrw_events where id = ? AND contactid = ?;", + "SELECT blobsize FROM dbrw_events where id = ? LIMIT 1;", + "SELECT blobsize FROM temp_dbrw_events where id = ? LIMIT 1;", + "SELECT * FROM dbrw_events where id = ? LIMIT 1;", + "SELECT * FROM temp_dbrw_events where id = ? LIMIT 1;", + "SELECT flags FROM dbrw_events where id = ? LIMIT 1;", + "UPDATE dbrw_events SET flags = ? WHERE id = ?;", + "SELECT contactid FROM dbrw_events where id = ? LIMIT 1;", + "SELECT contactid FROM temp_dbrw_events where id = ? LIMIT 1;", + "SELECT id FROM dbrw_events where contactid = ? ORDER by id;", + "SELECT flags,id FROM dbrw_events where contactid = ? ORDER by id;", + "SELECT id FROM dbrw_events where contactid = ? ORDER by id DESC;", + "SELECT id FROM dbrw_events where contactid = ? AND id > ? ORDER by id LIMIT 1;", + "SELECT id FROM dbrw_events where contactid = ? AND id < ? ORDER by id DESC LIMIT 1;", + "create temp table temp_dbrw_events (id integer primary key,eventtime integer,flags integer,eventtype integer, blob any, blobsize integer, contactid integer,modulename varchar(255),inserttime integer);" + "create temp trigger insert_new_temp_event1 after insert on dbrw_events begin replace into temp_dbrw_events values(new.id,new.eventtime,new.flags,new.eventtype,new.blob,new.blobsize,new.contactid,new.modulename,new.inserttime); end;" + "create temp trigger insert_new_temp_event2 after update on dbrw_events begin replace into temp_dbrw_events values(new.id,new.eventtime,new.flags,new.eventtype,new.blob,new.blobsize,new.contactid,new.modulename,new.inserttime); end;" + "create temp trigger delete_temp_event after delete on dbrw_events begin delete from temp_dbrw_events where id=old.id and contactid=old.id; end;", + "drop trigger insert_new_temp_event1;" + "drop trigger insert_new_temp_event2;" + "drop trigger delete_temp_event;" + "drop table temp_dbrw_events;", + "DELETE FROM dbrw_events WHERE contactid = ?;" +}; +static sqlite3_stmt *evt_stmts_prep[SQL_EVT_STMT_NUM] = {0}; + +void events_init() { + InitializeCriticalSection(&csEventsDb); + hHeap = HeapCreate(0, 0, 0); + ZeroMemory(&sModuleNames, sizeof(sModuleNames)); + sModuleNames.increment = 100; + sModuleNames.sortFunc = events_cmpModuleNames; + sql_prepare_add(evt_stmts, evt_stmts_prep, SQL_EVT_STMT_NUM); + sql_exec(g_sqlite, "BEGIN TRANSACTION;"); + sql_exec(g_sqlite, "create temp table temp_dbrw_events (id integer primary key,eventtime integer,flags integer,eventtype integer, blob any, blobsize integer, contactid integer,modulename varchar(255),inserttime integer);" + "create temp trigger insert_new_temp_event1 after insert on dbrw_events begin replace into temp_dbrw_events values(new.id,new.eventtime,new.flags,new.eventtype,new.blob,new.blobsize,new.contactid,new.modulename,new.inserttime); end;" + "create temp trigger insert_new_temp_event2 after update on dbrw_events begin replace into temp_dbrw_events values(new.id,new.eventtime,new.flags,new.eventtype,new.blob,new.blobsize,new.contactid,new.modulename,new.inserttime); end;" + "create temp trigger delete_temp_event after delete on dbrw_events begin delete from temp_dbrw_events where id=old.id and contactid=old.id; end;"); + sql_exec(g_sqlite, "COMMIT;"); + hEventsEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + hEventsThread = (HANDLE)mir_forkthreadex(events_timerProcThread, 0, 0, 0); +} + +void events_destroy() { + if (hEventsEvent) { + SetEvent(hEventsEvent); + WaitForSingleObjectEx(hEventsThread, INFINITE, FALSE); + CloseHandle(hEventsThread); + } + HeapDestroy(hHeap); + li.List_Destroy(&sModuleNames); + DeleteCriticalSection(&csEventsDb); +} + +static int events_cmpModuleNames(void *p1, void *p2) { + DBCachedModuleName *v1 = (DBCachedModuleName*)p1; + DBCachedModuleName *v2 = (DBCachedModuleName*)p2; + + if (v1->nameHash!=v2->nameHash) + return v1->nameHash-v2->nameHash; + return strcmp(v1->name, v2->name); +} + +static char *events_moduleCacheAdd(char *szModule) { + if (!szModule) + return 0; + { + int idx = 0; + size_t nameLen; + DBCachedModuleName Vtemp, *V; + + Vtemp.name = szModule; + Vtemp.nameHash = utils_hashString(szModule); + if (li.List_GetIndex(&sModuleNames, &Vtemp, &idx)) { + V = (DBCachedModuleName*)sModuleNames.items[idx]; + return V->name; + } + V = (DBCachedModuleName*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(DBCachedModuleName)); + nameLen = strlen(szModule)+1; + V->name = (char*)HeapAlloc(hHeap, 0, nameLen); + mir_snprintf(V->name, nameLen, "%s", szModule); + V->nameHash = utils_hashString(szModule); + li.List_Insert(&sModuleNames, V, idx); + return V->name; + } +} + +static unsigned __stdcall events_timerProcThread(void *arg) { + DWORD dwWait; + + for(;;) { + dwWait = WaitForSingleObjectEx(hEventsEvent, DBRW_EVENTS_FLUSHCACHE, TRUE); + + if (dwWait==WAIT_OBJECT_0) + break; + else if(dwWait == WAIT_TIMEOUT) { + EnterCriticalSection(&csEventsDb); + sql_stmt_begin(); + sql_step(evt_stmts_prep[SQL_EVT_STMT_DROPTEMPTABLE]); + sql_step(evt_stmts_prep[SQL_EVT_STMT_CREATETEMPTABLE]); + sql_stmt_end(); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_DROPTEMPTABLE]); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_CREATETEMPTABLE]); + LeaveCriticalSection(&csEventsDb); + } + else if (dwWait == WAIT_IO_COMPLETION) + if (Miranda_Terminated()) + break; + } + CloseHandle(hEventsEvent); + hEventsEvent = NULL; + return 0; +} + +INT_PTR events_getCount(WPARAM wParam, LPARAM lParam) { + int rc = 0; + + EnterCriticalSection(&csEventsDb); + if (!contacts_isContact(wParam, 0)) { + LeaveCriticalSection(&csEventsDb); + return -1; + } + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_COUNT], 1, (int)wParam); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_COUNT])==SQLITE_ROW) + rc = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_COUNT], 0); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_COUNT]); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +INT_PTR events_add(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + DBEVENTINFO *dbei = (DBEVENTINFO*)lParam; + int rc = 0; + + if (dbei==NULL|| + dbei->cbSize!=sizeof(DBEVENTINFO)|| + dbei->timestamp==0|| + NotifyEventHooks(hEventFilterAddedEvent, wParam, lParam)) { + log1("Attempt to add invalid event for contact(%d)", (int)hContact); + return 0; + } + EnterCriticalSection(&csEventsDb); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_ADD], 1, (int)dbei->timestamp); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_ADD], 2, (int)dbei->flags); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_ADD], 3, (int)dbei->eventType); + sqlite3_bind_blob(evt_stmts_prep[SQL_EVT_STMT_ADD], 4, dbei->pBlob, (int)dbei->cbBlob, SQLITE_STATIC); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_ADD], 5, (int)dbei->cbBlob); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_ADD], 6, (int)hContact); + sqlite3_bind_text(evt_stmts_prep[SQL_EVT_STMT_ADD], 7, dbei->szModule?dbei->szModule:NULL, -1, SQLITE_STATIC); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_ADD], 8, time(NULL)); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_ADD])==SQLITE_DONE) { + rc = (int)sqlite3_last_insert_rowid(g_sqlite); + } + else { + log2("Error adding event(#%d,%s)", sqlite3_errcode(g_sqlite), sqlite3_errmsg(g_sqlite)); + } + sql_reset(evt_stmts_prep[SQL_EVT_STMT_ADD]); + LeaveCriticalSection(&csEventsDb); + if (rc) { + NotifyEventHooks(hEventAddedEvent,wParam,(LPARAM)rc); + } + return rc; +} + +INT_PTR events_delete(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam, hContactFind; + HANDLE hDbEvent = (HANDLE)lParam; + int rc = 1; + + hContactFind = (HANDLE)events_getContact((WPARAM)hDbEvent, 0); + if ((int)hContactFind==-1||hContact!=hContactFind) + return rc; + NotifyEventHooks(hEventDeletedEvent, wParam, lParam); + EnterCriticalSection(&csEventsDb); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_DELETE], 1, (int)hDbEvent); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_DELETE], 2, (int)hContact); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_DELETE])==SQLITE_DONE) { + log1("Deleted event(%d)", (int)hDbEvent); + rc = 0; + } + sql_reset(evt_stmts_prep[SQL_EVT_STMT_DELETE]); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +static int events_getBlobSizeConditional(HANDLE hDbEvent, int cache) { + int rc = -1; + sqlite3_stmt* stmt; + + EnterCriticalSection(&csEventsDb); + stmt = cache?evt_stmts_prep[SQL_EVT_STMT_BLOBSIZE_CACHE]:evt_stmts_prep[SQL_EVT_STMT_BLOBSIZE]; + sqlite3_bind_int(stmt, 1, (int)hDbEvent); + if (sql_step(stmt)==SQLITE_ROW) + rc = sqlite3_column_int(stmt, 0); + sql_reset(stmt); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +INT_PTR events_getBlobSize(WPARAM wParam, LPARAM lParam) { + HANDLE hDbEvent = (HANDLE)wParam; + int rc = events_getBlobSizeConditional(hDbEvent, 1); + + if (rc!=-1) + return rc; + return events_getBlobSizeConditional(hDbEvent, 0);; +} + +static int events_getConditional(HANDLE hDbEvent, DBEVENTINFO *dbei, int cache) { + int rc = 1; + sqlite3_stmt* stmt; + + if(dbei==NULL||dbei->cbSize!=sizeof(DBEVENTINFO)) + return 1; + if(dbei->cbBlob>0&&dbei->pBlob==NULL) { + dbei->cbBlob = 0; + return 1; + } + EnterCriticalSection(&csEventsDb); + stmt = cache?evt_stmts_prep[SQL_EVT_STMT_GET_CACHE]:evt_stmts_prep[SQL_EVT_STMT_GET]; + sqlite3_bind_int(stmt, 1, (int)hDbEvent); + if (sql_step(stmt)==SQLITE_ROW) { + unsigned copySize; + const void *blob = sqlite3_column_blob(stmt, 4); + const unsigned size = sqlite3_column_int(stmt, 5); + + dbei->timestamp = (DWORD)sqlite3_column_int(stmt, 1); + dbei->flags = (DWORD)sqlite3_column_int(stmt, 2); + dbei->eventType = (WORD)sqlite3_column_int(stmt, 3); + dbei->szModule = events_moduleCacheAdd((char*)sqlite3_column_text(stmt, 7)); + copySize = sizecbBlob ? size : dbei->cbBlob; + CopyMemory(dbei->pBlob, blob, copySize); + dbei->cbBlob = copySize; + rc = 0; + } + sql_reset(stmt); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +INT_PTR events_get(WPARAM wParam, LPARAM lParam) { + HANDLE hDbEvent = (HANDLE)wParam; + DBEVENTINFO *dbei = (DBEVENTINFO*)lParam; + int rc = events_getConditional(hDbEvent, dbei, 1); + + if (!rc) + return 0; + return events_getConditional(hDbEvent, dbei, 0); +} + +INT_PTR events_markRead(WPARAM wParam, LPARAM lParam) { + HANDLE hDbEvent = (HANDLE)lParam; + int rc = -1; + + EnterCriticalSection(&csEventsDb); + sql_stmt_begin(); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_GETFLAGS], 1, (int)hDbEvent); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_GETFLAGS])==SQLITE_ROW) { + DWORD flags = (DWORD)sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_GETFLAGS], 0); + + sql_reset(evt_stmts_prep[SQL_EVT_STMT_GETFLAGS]); + rc = flags; + if (!(flags&DBEF_READ)) { + flags|=DBEF_READ; + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_SETFLAGS], 1, (int)flags); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_SETFLAGS], 2, (int)hDbEvent); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_SETFLAGS])!=SQLITE_DONE) { + rc = -1; + } + sql_reset(evt_stmts_prep[SQL_EVT_STMT_SETFLAGS]); + } + } + else sql_reset(evt_stmts_prep[SQL_EVT_STMT_GETFLAGS]); + sql_stmt_end(); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +static int events_getContactConditional(HANDLE hDbEvent, int cache) { + int rc = -1; + sqlite3_stmt* stmt; + + EnterCriticalSection(&csEventsDb); + stmt = cache?evt_stmts_prep[SQL_EVT_STMT_GETCONTACT_CACHE]:evt_stmts_prep[SQL_EVT_STMT_GETCONTACT]; + sqlite3_bind_int(stmt, 1, (int)hDbEvent); + if (sql_step(stmt)==SQLITE_ROW) + rc = sqlite3_column_int(stmt, 0); + sql_reset(stmt); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +INT_PTR events_getContact(WPARAM wParam, LPARAM lParam) { + HANDLE hDbEvent = (HANDLE)wParam; + int rc = events_getContactConditional(hDbEvent, 1); + + if (rc!=-1) + return rc; + return events_getContactConditional(hDbEvent, 0); +} + +INT_PTR events_findFirst(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + int rc = 0; + + EnterCriticalSection(&csEventsDb); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST], 1, (int)hContact); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST])==SQLITE_ROW) { + rc = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST], 0); + } + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST]); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +INT_PTR events_findFirstUnread(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + int rc = 0; + DWORD flags = 0; + + EnterCriticalSection(&csEventsDb); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 1, (int)hContact); + while (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD])==SQLITE_ROW) { + flags = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 0); + if(!(flags&(DBEF_READ|DBEF_SENT))) { + rc = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 1); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD]); + LeaveCriticalSection(&csEventsDb); + return rc; + } + } + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD]); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +INT_PTR events_findLast(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + int rc = 0; + + EnterCriticalSection(&csEventsDb); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDLAST], 1, (int)hContact); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDLAST])==SQLITE_ROW) + rc = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDLAST], 0); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDLAST]); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +INT_PTR events_findNext(WPARAM wParam, LPARAM lParam) { + HANDLE hDbEvent = (HANDLE)wParam; + int hContact = -1, rc = 0; + + if (hDbEvent==NULL) { + return 0; + } + hContact = events_getContact(wParam, 0); + if (hContact==-1) + return 0; + EnterCriticalSection(&csEventsDb); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 1, hContact); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 2, (int)hDbEvent); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT])==SQLITE_ROW) + rc = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 0); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT]); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +INT_PTR events_findPrev(WPARAM wParam, LPARAM lParam) { + HANDLE hDbEvent = (HANDLE)wParam; + int hContact = -1, rc = 0; + + if (hDbEvent==NULL) { + return 0; + } + hContact = events_getContact(wParam, 0); + if (hContact==-1) { + return 0; + } + EnterCriticalSection(&csEventsDb); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 1, hContact); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 2, (int)hDbEvent); + rc = sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDPREV]); + if (rc==SQLITE_ROW) { + rc = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 0); + } + else { + rc = 0; + } + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDPREV]); + LeaveCriticalSection(&csEventsDb); + return rc; +} + +void events_deleteContactData(HANDLE hContact) { + EnterCriticalSection(&csEventsDb); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_DELETECONTACT], 1, (int)hContact); + sql_step(evt_stmts_prep[SQL_EVT_STMT_DELETECONTACT]); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_DELETECONTACT]); + LeaveCriticalSection(&csEventsDb); +} -- cgit v1.2.3