void removeRecentEntryInternal(uint64_t repoID, uint projectID, bool isLocal) { sqlite3 *database = getPtrRecentDB(); if(database == NULL) return; sqlite3_stmt * request = createRequest(database, "DELETE FROM "PROJECT_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3");; if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) repoID); sqlite3_bind_int(request, 2, (int32_t) projectID); sqlite3_bind_int(request, 3, isLocal); sqlite3_step(request); } destroyRequest(request); request = createRequest(database, "DELETE FROM "STATE_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3");; if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) repoID); sqlite3_bind_int(request, 2, (int32_t) projectID); sqlite3_bind_int(request, 3, isLocal); sqlite3_step(request); } destroyRequest(request); closeRecentDB(database); }
uint checkRecentDBValid(sqlite3 * DB) { uint retValue = RECENT_CHECK_RETVAL_OK; sqlite3_stmt * request = createRequest(DB, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='"PROJECT_TABLE"';"); if(request == NULL || sqlite3_step(request) != SQLITE_ROW || sqlite3_column_int(request, 0) != 1) retValue |= RECENT_CHECK_RETVAL_INVALID_PROJ; else { destroyRequest(request); request = createRequest(DB, "pragma table_info ("PROJECT_TABLE");"); if(request != NULL) { uint count = 0; while(sqlite3_step(request) == SQLITE_ROW) count += 1; if(count != PROJECT_TABLE_SIZE) retValue |= RECENT_CHECK_RETVAL_INVALID_PROJ; } } destroyRequest(request); request = createRequest(DB, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='"STATE_TABLE"';"); if(request == NULL || sqlite3_step(request) != SQLITE_ROW || sqlite3_column_int(request, 0) != 1) retValue |= RECENT_CHECK_RETVAL_INVALID_STATE; else { destroyRequest(request); request = createRequest(DB, "pragma table_info ("STATE_TABLE");"); if(request != NULL) { uint count = 0; while(sqlite3_step(request) == SQLITE_ROW) count += 1; if(count != STATE_TABLE_SIZE) retValue |= RECENT_CHECK_RETVAL_INVALID_STATE; } } destroyRequest(request); return retValue; }
double getSavedZoomForProject(PROJECT_DATA project, bool isTome) { double zoom = 1.0; sqlite3 * database = getPtrRecentDB(); if(database != NULL) { sqlite3_stmt * request = createRequest(database, "SELECT "DBNAMETOID(RDB_REC_lastZoom)" FROM "STATE_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3 AND "DBNAMETOID(RDB_REC_lastIsTome)" = ?4;"); if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) getRepoID(project.repo)); sqlite3_bind_int(request, 2, (int32_t) project.projectID); sqlite3_bind_int(request, 3, project.locale); sqlite3_bind_int(request, 4, isTome); if(sqlite3_step(request) == SQLITE_ROW) zoom = sqlite3_column_double(request, 0) - 1.0; destroyRequest(request); } closeRecentDB(database); } return zoom; }
uint getSavedIDForProject(void * database, PROJECT_DATA project, bool isTome) { uint ID = INVALID_VALUE; bool needFreeDB; if(database == NULL) { database = getPtrRecentDB(); needFreeDB = true; } else needFreeDB = false; if(database != NULL) { sqlite3_stmt * request = createRequest(database, "SELECT "DBNAMETOID(RDB_REC_lastZoom)" FROM "STATE_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3 AND "DBNAMETOID(RDB_REC_lastIsTome)" = ?4;"); if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) getRepoID(project.repo)); sqlite3_bind_int(request, 2, (int32_t) project.projectID); sqlite3_bind_int(request, 3, project.locale); sqlite3_bind_int(request, 4, isTome); if(sqlite3_step(request) == SQLITE_ROW) ID = (uint) sqlite3_column_int(request, 0); destroyRequest(request); } if(needFreeDB) closeRecentDB(database); } return ID; }
charType * getNameForRequestAndCode(sqlite3_stmt * request, uint32_t code) { sqlite3_bind_int(request, 1, (int32_t) code); if(sqlite3_step(request) != SQLITE_ROW) { destroyRequest(request); return L"Unknown"; } charType * output = getStringFromUTF8(sqlite3_column_text(request, 0)); destroyRequest(request); return output; }
bool lastReadAsTome(void * database, PROJECT_DATA project) { bool needFreeDB, isTome = false; if(database == NULL) { database = getPtrRecentDB(); needFreeDB = true; } else needFreeDB = false; if(database != NULL) { sqlite3_stmt * request = createRequest(database, "SELECT "DBNAMETOID(RDB_REC_lastIsTome)" FROM "STATE_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3 ORDER BY "DBNAMETOID(RDB_REC_lastChange)" DESC LIMIT 1;"); if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) getRepoID(project.repo)); sqlite3_bind_int(request, 2, (int32_t) project.projectID); sqlite3_bind_int(request, 3, project.locale); if(sqlite3_step(request) == SQLITE_ROW) isTome = (uint) sqlite3_column_int(request, 0); destroyRequest(request); } if(needFreeDB) closeRecentDB(database); } return isTome; }
STATE_DUMP _recoverStateForProject(PROJECT_DATA project, bool haveTome, bool isTome) { STATE_DUMP output = getEmptyRecoverState(); output.cacheDBID = project.cacheDBID; sqlite3 * database = getPtrRecentDB(); if(database != NULL) { sqlite3_stmt * request; if(haveTome) { request = createRequest(database, "SELECT "DBNAMETOID(RDB_REC_lastIsTome)", "DBNAMETOID(RDB_REC_lastCTID)", "DBNAMETOID(RDB_REC_lastPage)", "DBNAMETOID(RDB_REC_wasLastPageOfCT)", "DBNAMETOID(RDB_REC_lastZoom)", "DBNAMETOID(RDB_REC_lastScrollerX)", "DBNAMETOID(RDB_REC_lastScrollerY)" FROM "STATE_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3 AND "DBNAMETOID(RDB_REC_lastIsTome)" = ?4 ORDER BY "DBNAMETOID(RDB_REC_lastChange)" DESC LIMIT 1;"); } else { request = createRequest(database, "SELECT "DBNAMETOID(RDB_REC_lastIsTome)", "DBNAMETOID(RDB_REC_lastCTID)", "DBNAMETOID(RDB_REC_lastPage)", "DBNAMETOID(RDB_REC_wasLastPageOfCT)", "DBNAMETOID(RDB_REC_lastZoom)", "DBNAMETOID(RDB_REC_lastScrollerX)", "DBNAMETOID(RDB_REC_lastScrollerY)" FROM "STATE_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3 ORDER BY "DBNAMETOID(RDB_REC_lastChange)" DESC LIMIT 1;"); } if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) getRepoID(project.repo)); sqlite3_bind_int(request, 2, (int32_t) project.projectID); sqlite3_bind_int(request, 3, project.locale); if(haveTome) sqlite3_bind_int(request, 4, isTome); if(sqlite3_step(request) == SQLITE_ROW) { output.isTome = sqlite3_column_int(request, 0); output.CTID = (uint32_t) sqlite3_column_int(request, 1); output.page = (uint32_t) sqlite3_column_int(request, 2); output.wasLastPage = (uint32_t) sqlite3_column_int(request, 3); output.zoom = sqlite3_column_double(request, 4) - 1.0; output.scrollerX = sqlite3_column_double(request, 5) - 1.0; output.scrollerY = sqlite3_column_double(request, 6) - 1.0; output.isInitialized = true; } destroyRequest(request); } closeRecentDB(database); } return output; }
void updateTagDBVersion(uint newDBVersion) { if(cache == NULL && immatureCache == NULL) return; sqlite3_stmt * request = createRequest(cache != NULL ? cache : immatureCache, "INSERT OR REPLACE INTO "TABLE_TAG_VERSION" (`"VERSION_COLUMN_NAME"`) VALUES(?1);"); if(request == NULL) return; sqlite3_bind_int(request, 1, (int32_t) newDBVersion); sqlite3_step(request); destroyRequest(request); }
uint getTagDBVersion() { sqlite3_stmt * request = NULL; uint output; if((cache == NULL && immatureCache == NULL) || (request = createRequest(cache != NULL ? cache : immatureCache, "SELECT `"VERSION_COLUMN_NAME"` FROM "TABLE_TAG_VERSION" LIMIT 1")) == NULL || sqlite3_step(request) != SQLITE_ROW) { output = DEFAULT_TAG_VERSION; } else output = (uint32_t) sqlite3_column_int(request, 0); destroyRequest(request); return output; }
uint getRootCategoryIDForID(uint32_t categoryID) { sqlite3_stmt * request = NULL; uint output; if(categoryID == CAT_NO_VALUE) return CAT_NO_VALUE; else if((request = createRequest(cache != NULL ? cache : immatureCache, "SELECT "DBNAMETOID(RDB_CAT_rootID)" FROM "TABLE_CATEGORY" WHERE "DBNAMETOID(RDB_CAT_ID)" = ?1;")) == NULL || sqlite3_step(request) != SQLITE_ROW) output = (uint32_t) sqlite3_column_int(request, 0); else output = CAT_NO_VALUE; destroyRequest(request); return output; }
void tagUpdateCachedEntryWithRequest(sqlite3_stmt * request, TAG_VERBOSE * newData, uint nbData) { for(uint i = 0; i < nbData; i++) { //We get a UTF8 version of the name size_t length = wstrlen((charType *) newData[i].name); char utf8[4 * length + 1]; length = wchar_to_utf8((charType *) newData[i].name, length, utf8, 4 * length + 1, 0); //We submit the data to the request, then run and clean it sqlite3_bind_int(request, 1, (int32_t) newData[i].ID); sqlite3_bind_text(request, 2, utf8, (int32_t) length, SQLITE_STATIC); sqlite3_step(request); sqlite3_reset(request); } destroyRequest(request); }
bool doesTagOfIDExist(uint32_t tagID) { if(cache == NULL && immatureCache == NULL) return false; if(tagID == CAT_NO_VALUE) return true; sqlite3_stmt * request; if((request = createRequest(cache == NULL ? immatureCache : cache, "SELECT COUNT() FROM "TABLE_TAGS" WHERE "DBNAMETOID(RDB_tagID)" = ?1")) == NULL) return false; sqlite3_bind_int(request, 1, (int32_t) tagID); bool retValue = (sqlite3_step(request) == SQLITE_ROW && sqlite3_column_int(request, 0) != 0); destroyRequest(request); return retValue; }
void *prefetch_thread(void *ignored) { char guessed_filename[1024]; struct request* req; char* data; intmax_t filesize; fprintf(stderr, "prefetch_thread: Starting up\n"); while (global_exit == 0) { pthread_mutex_lock(&prefetch_mutex); assert ( prefetch_size >= 0 ); if (prefetch_size == 0) pthread_cond_wait(&prefetch_get_cond, &prefetch_mutex); req = prefetch_getRequest(); assert ( req != NULL ); fprintf(stderr, "prefetch_thread: Processing request with filename %s\n", req->filename); pthread_mutex_unlock(&prefetch_mutex); if ( guess_next( req->filename, guessed_filename ) == 0 ) { data = getFile(guessed_filename); filesize = getFileSize(guessed_filename); pthread_mutex_lock(&cache_mutex); cache_putEntry( createCacheEntry( guessed_filename, data, filesize ) ); pthread_mutex_unlock(&cache_mutex); } destroyRequest(req); } fprintf(stderr, "prefetch_thread: Shutting down\n"); return NULL; }
bool createTagsTable(sqlite3 * mainCache) { if(mainCache == NULL) { logR("Initialization is incomplete!"); return false; } sqlite3_stmt * request = createRequest(mainCache, "CREATE TABLE "TABLE_TAGS" ("DBNAMETOID(RDB_tagID)" INTEGER PRIMARY KEY NOT NULL, "DBNAMETOID(RDB_tagName)" TEXT NOT NULL); CREATE INDEX hopperIsGud ON "TABLE_TAGS"("DBNAMETOID(RDB_tagID)");"); if(request == NULL || sqlite3_step(request) != SQLITE_DONE) { logR("Initialization error small"); destroyRequest(request); return false; } destroyRequest(request); if((request = createRequest(mainCache, "CREATE TABLE "TABLE_CATEGORY" ("DBNAMETOID(RDB_CAT_ID)" INTEGER PRIMARY KEY NOT NULL, "DBNAMETOID(RDB_CAT_rootID)" INTEGER, "DBNAMETOID(RDB_CAT_name)" TEXT NOT NULL); CREATE INDEX gdbOverlldb ON "TABLE_CATEGORY"("DBNAMETOID(RDB_CAT_ID)", "DBNAMETOID(RDB_CAT_rootID)");")) == NULL || sqlite3_step(request) != SQLITE_DONE) { logR("Initialization error big"); destroyRequest(request); return false; } destroyRequest(request); if((request = createRequest(mainCache, "CREATE TABLE "TABLE_TAG_VERSION" (`"VERSION_COLUMN_NAME"` INTEGER);")) == NULL || sqlite3_step(request) != SQLITE_DONE) { logR("Initialization error WTF"); destroyRequest(request); return false; } destroyRequest(request); return true; }
bool insertCurrentState(PROJECT_DATA project, STATE_DUMP state) { bool success = false; if(!state.isInitialized) return success; sqlite3 * database = getPtrRecentDB(); if(database != NULL) { sqlite3_stmt * request = createRequest(database, "INSERT OR REPLACE INTO "STATE_TABLE" ("DBNAMETOID(RDB_REC_repo)", "DBNAMETOID(RDB_REC_projectID)", "DBNAMETOID(RDB_isLocal)", "DBNAMETOID(RDB_REC_lastIsTome)", "DBNAMETOID(RDB_REC_lastCTID)", "DBNAMETOID(RDB_REC_lastPage)", "DBNAMETOID(RDB_REC_wasLastPageOfCT)", "DBNAMETOID(RDB_REC_lastZoom)", "DBNAMETOID(RDB_REC_lastScrollerX)", "DBNAMETOID(RDB_REC_lastScrollerY)", "DBNAMETOID(RDB_REC_lastChange)") values(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11);"); if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) getRepoID(project.repo)); sqlite3_bind_int(request, 2, (int32_t) project.projectID); sqlite3_bind_int(request, 3, project.locale); sqlite3_bind_int(request, 4, state.isTome); sqlite3_bind_int(request, 5, (int32_t) state.CTID); sqlite3_bind_int(request, 6, (int32_t) state.page); sqlite3_bind_int(request, 7, (int32_t) state.wasLastPage); sqlite3_bind_double(request, 8, state.zoom + 1.0); sqlite3_bind_double(request, 9, state.scrollerX + 1.0); sqlite3_bind_double(request, 10, state.scrollerY + 1.0); sqlite3_bind_int(request, 11, time(NULL)); success = sqlite3_step(request) == SQLITE_DONE; destroyRequest(request); } closeRecentDB(database); } return success; }
sqlite3* getPtrRecentDB() { sqlite3 * internalDB = NULL; bool initialCheckRequired = !recentMutexInitialized; if(!recentMutexInitialized) { MUTEX_CREATE(recentMutex); recentMutexInitialized = true; } MUTEX_LOCK(recentMutex); if(sqlite3_open("recent.db", &internalDB) != SQLITE_OK) { logR("Couldn't open the recent database, abort :("); internalDB = NULL; } else if(initialCheckRequired) { uint retValue = checkRecentDBValid(internalDB); if(retValue != RECENT_CHECK_RETVAL_OK) { if(retValue & RECENT_CHECK_RETVAL_INVALID_PROJ) { //On la détruit, et on recrée sqlite3_stmt * request = createRequest(internalDB, "DROP TABLE IF EXISTS `"PROJECT_TABLE"`"); sqlite3_step(request); destroyRequest(request); request = createRequest(internalDB, "CREATE TABLE "PROJECT_TABLE" ("DBNAMETOID(RDB_REC_lastRead)" INTEGER, "DBNAMETOID(RDB_REC_lastDL)" INTEGER, "DBNAMETOID(RDB_REC_repo)" INTEGER, "DBNAMETOID(RDB_REC_projectID)" INTEGER, "DBNAMETOID(RDB_isLocal)" INTEGER);"); if(request == NULL || sqlite3_step(request) != SQLITE_DONE) { destroyRequest(request); sqlite3_close(internalDB); internalDB = NULL; } else destroyRequest(request); } if(internalDB != NULL && retValue & RECENT_CHECK_RETVAL_INVALID_STATE) { //On la détruit, et on recrée sqlite3_stmt * request = createRequest(internalDB, "DROP TABLE IF EXISTS `"STATE_TABLE"`"); sqlite3_step(request); destroyRequest(request); request = createRequest(internalDB, "CREATE TABLE "STATE_TABLE" ("DBNAMETOID(RDB_REC_repo)" INTEGER, "DBNAMETOID(RDB_REC_projectID)" INTEGER, "DBNAMETOID(RDB_isLocal)" INTEGER, "DBNAMETOID(RDB_REC_lastIsTome)" INTEGER, "DBNAMETOID(RDB_REC_lastCTID)" INTEGER, "DBNAMETOID(RDB_REC_lastPage)" INTEGER, "DBNAMETOID(RDB_REC_wasLastPageOfCT)" INTEGER, "DBNAMETOID(RDB_REC_lastZoom)" FLOAT, "DBNAMETOID(RDB_REC_lastScrollerX)" FLOAT, "DBNAMETOID(RDB_REC_lastScrollerY)" FLOAT, "DBNAMETOID(RDB_REC_lastChange)" INTEGER, PRIMARY KEY("DBNAMETOID(RDB_REC_repo)", "DBNAMETOID(RDB_REC_projectID)", "DBNAMETOID(RDB_isLocal)", "DBNAMETOID(RDB_REC_lastIsTome)")) WITHOUT ROWID;"); if(request == NULL || sqlite3_step(request) != SQLITE_DONE) { destroyRequest(request); sqlite3_close(internalDB); internalDB = NULL; } else destroyRequest(request); } } } if(internalDB == NULL) MUTEX_UNLOCK(recentMutex); return internalDB; }
bool getCopyOfTagsOrCat(bool wantTag, void ** newData, uint * nbData) { //Check data sanity, create request... if(newData == NULL || nbData == NULL) return false; *newData = NULL; *nbData = 0; sqlite3_stmt * request; if(wantTag) request = createRequest(cache, "SELECT * FROM "TABLE_TAGS" ORDER BY "DBNAMETOID(RDB_tagName)" COLLATE "SORT_FUNC" ASC;"); else request = createRequest(cache, "SELECT "DBNAMETOID(RDB_CAT_ID)", "DBNAMETOID(RDB_CAT_name)" FROM "TABLE_CATEGORY" ORDER BY "DBNAMETOID(RDB_CAT_name)" COLLATE "SORT_FUNC" ASC;"); if(request == NULL) return false; uint currentSize = 1023, currentPos = 0, dataSize = wantTag ? sizeof(TAG_VERBOSE) : sizeof(CATEGORY_VERBOSE); void * buffer = malloc(currentSize * dataSize); if(buffer == NULL) { destroyRequest(request); return false; } //Main loop while(sqlite3_step(request) == SQLITE_ROW) { //We increase our buffer size if needed if(currentPos == currentSize) { currentSize += 1024; void * tmp = realloc(buffer, currentSize * dataSize); if(tmp == NULL) { if(wantTag) { while(currentPos-- > 0) free(((TAG_VERBOSE *) buffer)[currentPos].name); } else { while(currentPos-- > 0) free(((CATEGORY_VERBOSE *) buffer)[currentPos].name); } free(buffer); destroyRequest(request); return false; } else buffer = tmp; } if(wantTag) { ((TAG_VERBOSE *) buffer)[currentPos].ID = (uint) sqlite3_column_int(request, 0); ((TAG_VERBOSE *) buffer)[currentPos].name = getStringFromUTF8(sqlite3_column_text(request, 1)); if(((TAG_VERBOSE *) buffer)[currentPos].name != NULL) currentPos++; } else { ((CATEGORY_VERBOSE *) buffer)[currentPos].ID = (uint) sqlite3_column_int(request, 0); ((CATEGORY_VERBOSE *) buffer)[currentPos].rootID = CAT_NO_VALUE; ((CATEGORY_VERBOSE *) buffer)[currentPos].name = getStringFromUTF8(sqlite3_column_text(request, 1)); if(((CATEGORY_VERBOSE *) buffer)[currentPos].name != NULL) currentPos++; } } //We reduce the allocated memory to the minimum if(currentPos == 0) { free(buffer); buffer = NULL; } else if(currentPos < currentSize) { void * tmp = realloc(buffer, currentPos * dataSize); if(tmp != NULL) buffer = tmp; } *newData = buffer; *nbData = currentPos; return true; }
void initializeTags(void * mainCache) { MUTEX_CREATE(concurentColdUpdate); sqlite3 * coldDB = NULL; //Create the tables in the main cache createTagsTable(mainCache); if((!checkFileExist(TAG_DB) || sqlite3_open(TAG_DB , &coldDB) != SQLITE_OK) && (!checkFileExist(WIP_TAG_DB) || sqlite3_open(WIP_TAG_DB, &coldDB) != SQLITE_OK)) { //Error, we should reset it with the version we ship with then trigger an update resetTagsToLocal(); if(!checkFileExist(TAG_DB) || sqlite3_open(TAG_DB , &coldDB) != SQLITE_OK) { alertExit("We have significant issues setting up our environment, this may be caused by permission issues, please contact us at [email protected]"); } } sqlite3_stmt * requestRead, *requestWrite; //Build the tag base if((requestRead = createRequest(coldDB, "SELECT "DBNAMETOID(RDB_tagID)", "DBNAMETOID(RDB_tagName)" FROM "TABLE_TAGS)) != NULL) { requestWrite = tagUpdateQuery(mainCache, false); if(requestWrite != NULL) { while(sqlite3_step(requestRead) == SQLITE_ROW) { sqlite3_bind_int(requestWrite, 1, sqlite3_column_int(requestRead, 0)); sqlite3_bind_text(requestWrite, 2, (void *) sqlite3_column_text(requestRead, 1), -1, SQLITE_STATIC); if(sqlite3_step(requestWrite) != SQLITE_DONE) { #ifdef EXTENSIVE_LOGGING uint ID = (uint32_t) sqlite3_column_int(requestRead, 0); const unsigned char * text = sqlite3_column_text(requestRead, 1); if(text == NULL) logR("Error building the tag DB for ID %d: no text!", ID); else logR("Error building the tag DB for ID %d of text %s!", ID, text); #endif } sqlite3_reset(requestWrite); } destroyRequest(requestWrite); } destroyRequest(requestRead); } //Build the category base if((requestRead = createRequest(coldDB, "SELECT "DBNAMETOID(RDB_CAT_ID)", "DBNAMETOID(RDB_CAT_rootID)", "DBNAMETOID(RDB_CAT_name)" FROM "TABLE_CATEGORY)) != NULL) { requestWrite = catUpdateQuery(mainCache, false); if(requestWrite != NULL) { while(sqlite3_step(requestRead) == SQLITE_ROW) { sqlite3_bind_int(requestWrite, 1, sqlite3_column_int(requestRead, 0)); sqlite3_bind_int(requestWrite, 2, sqlite3_column_int(requestRead, 1)); sqlite3_bind_text(requestWrite, 3, (void *) sqlite3_column_text(requestRead, 2), -1, SQLITE_STATIC); for(byte i = 0; i < 32; i++) { sqlite3_bind_int(requestWrite, i + 4, sqlite3_column_int(requestRead, i + 3)); } if(sqlite3_step(requestWrite) != SQLITE_DONE) { #ifdef EXTENSIVE_LOGGING uint ID = (uint32_t) sqlite3_column_int(requestRead, 0); const unsigned char * text = sqlite3_column_text(requestRead, 2); if(text == NULL) logR("Error building the category DB for ID %d: no text!", ID); else logR("Error building the category DB for ID %d of text %s!", ID, text); #endif } sqlite3_reset(requestWrite); } destroyRequest(requestWrite); } destroyRequest(requestRead); } sqlite3_close(coldDB); }
void *worker_thread(void * id) { struct request_bundle bundle; int thread_id = *((int*)id); int requests_handled = 0; int cache_hit; const char* error; fprintf(stderr, "worker_thread: Starting up\n"); while (global_exit == 0) { fprintf(stderr, "worker_thread: Iterating\n"); pthread_mutex_lock(&queue_mutex); fprintf(stderr, "worker_thread: Queue lock acquired\n"); assert (queue_size >= 0); if (queue_size == 0) { fprintf(stderr, "worker_thread: Queue empty, waiting for condition 'queue get' and releasing queue lock\n"); pthread_cond_wait(&queue_get_cond, &queue_mutex); fprintf(stderr, "worker_thread: Condition 'queue get' fufilled, queue lock reacquired\n"); } pthread_mutex_lock(&cache_mutex); fprintf(stderr, "worker_thread: Cache lock acquired\n"); assert ( getRequest != NULL ); bundle = (*getRequest)(); fprintf(stderr, "worker_thread: Got request for connection %d with filename %s\n", bundle.req->fd, bundle.req->filename); pthread_cond_signal(&queue_put_cond); pthread_mutex_unlock(&queue_mutex); error = process_request(&bundle, &cache_hit); fprintf(stderr, "worker_thread: Done processing request\n"); ++requests_handled; pthread_mutex_lock(&log_mutex); logRequest(bundle, thread_id, requests_handled, cache_hit, error); pthread_mutex_unlock(&log_mutex); pthread_mutex_unlock(&cache_mutex); // bundle.ent should NOT be used after this point if (prefetch_size < max_prefetch_size) { pthread_mutex_lock(&prefetch_mutex); prefetch_putRequest(bundle.req); pthread_cond_signal(&prefetch_get_cond); pthread_mutex_unlock(&prefetch_mutex); } else { destroyRequest(bundle.req); } } fprintf(stderr, "worker_thread: Should exit, starting to empty request queue\n"); while (queue_size > 0) { pthread_mutex_lock(&queue_mutex); pthread_mutex_lock(&cache_mutex); bundle = (*getRequest)(); pthread_mutex_unlock(&queue_mutex); error = process_request(&bundle, &cache_hit); pthread_mutex_unlock(&cache_mutex); ++requests_handled; pthread_mutex_lock(&log_mutex); logRequest(bundle, thread_id, requests_handled, cache_hit, error); pthread_mutex_unlock(&log_mutex); destroyRequest(bundle.req); } fprintf(stderr, "worker_thread: Shutting down\n"); return NULL; }
bool updateRecentEntry(sqlite3 *database, PROJECT_DATA data, time_t timestamp, bool wasItADL) { bool output = false, haveToUpdate = false, localDB = true; if(database == NULL) database = getPtrRecentDB(); else localDB = false; if(database == NULL) return false; sqlite3_stmt * request = createRequest(database, "BEGIN EXCLUSIVE TRANSACTION"); if(request == NULL || sqlite3_step(request) != SQLITE_DONE) { destroyRequest(request); if(localDB) closeRecentDB(database); return false; } destroyRequest(request); //We check if the element exist request = createRequest(database, "SELECT count(*) FROM "PROJECT_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3;"); if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) getRepoID(data.repo)); sqlite3_bind_int(request, 2, (int32_t) data.projectID); sqlite3_bind_int(request, 3, data.locale); if(sqlite3_step(request) == SQLITE_ROW) { //We'll inject the data now uint nbOccurence = (uint) sqlite3_column_int(request, 0); char requestString[200]; time_t recentRead = wasItADL ? 0 : timestamp, recentDL = wasItADL ? timestamp : 0; destroyRequest(request); haveToUpdate = true; if(nbOccurence != 0) { byte value = wasItADL ? RDB_REC_lastDL : RDB_REC_lastRead; snprintf(requestString, sizeof(requestString), "SELECT count(*) FROM "PROJECT_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3 AND `%d` = (SELECT MAX(`%d`) FROM "PROJECT_TABLE");", value, value); request = createRequest(database, requestString); if(request != NULL) { sqlite3_bind_int64(request, 1, (int64_t) getRepoID(data.repo)); sqlite3_bind_int(request, 2, (int32_t) data.projectID); sqlite3_bind_int(request, 3, data.locale); if(sqlite3_step(request) == SQLITE_ROW) { if(sqlite3_column_int(request, 0) == 0) haveToUpdate = true; else //We have the maximal value. However, if everything was zero, we would want to update the UI anyway { destroyRequest(request); snprintf(requestString, sizeof(requestString), "SELECT `%d` FROM "PROJECT_TABLE" WHERE "DBNAMETOID(RDB_REC_repo)" = ?1 AND "DBNAMETOID(RDB_REC_projectID)" = ?2 AND "DBNAMETOID(RDB_isLocal)" = ?3;", value); if((request = createRequest(database, requestString)) != NULL) { sqlite3_bind_int64(request, 1, (int64_t) getRepoID(data.repo)); sqlite3_bind_int(request, 2, (int32_t) data.projectID); sqlite3_bind_int(request, 3, data.locale); if(sqlite3_step(request) == SQLITE_ROW && sqlite3_column_int(request, 0) == 0) { haveToUpdate = true; } } else request = NULL; //Prevent a crash with the following destroyRequest } } destroyRequest(request); } } //We craft the request if(nbOccurence == 0) snprintf(requestString, sizeof(requestString), "INSERT INTO "PROJECT_TABLE"("DBNAMETOID(RDB_REC_lastRead)", "DBNAMETOID(RDB_REC_lastDL)", "DBNAMETOID(RDB_REC_repo)", "DBNAMETOID(RDB_REC_projectID)", "DBNAMETOID(RDB_isLocal)") values(?1, ?2, ?3, ?4, ?5);"); else snprintf(requestString, sizeof(requestString), "UPDATE "PROJECT_TABLE" SET `%d` = ?%d WHERE "DBNAMETOID(RDB_REC_repo)" = ?3 AND "DBNAMETOID(RDB_REC_projectID)" = ?4 AND "DBNAMETOID(RDB_isLocal)" = ?5;", wasItADL ? RDB_REC_lastDL : RDB_REC_lastRead, wasItADL ? 2 : 1); //Setup the handler request = createRequest(database, requestString); if(request != NULL) { if(!nbOccurence || !wasItADL) sqlite3_bind_int64(request, 1, recentRead); if(!nbOccurence || wasItADL) sqlite3_bind_int64(request, 2, recentDL); sqlite3_bind_int64(request, 3, (int64_t) getRepoID(data.repo)); sqlite3_bind_int(request, 4, (int32_t) data.projectID); sqlite3_bind_int(request, 5, data.locale); output = sqlite3_step(request) == SQLITE_DONE; } } } destroyRequest(request); request = createRequest(database, "END TRANSACTION"); sqlite3_step(request); destroyRequest(request); if(localDB) closeRecentDB(database); if(haveToUpdate) updateRecentSeries(); return output; }