/* Read a page from the write-ahead log, if it is present. */ int sqlite3WalFindFrame(Wal *pWal, Pgno pgno, u32 *piRead) { // db_thread * const thread = enif_tsd_get(g_tsd_thread); #if ATOMIC db_thread *thread = g_tsd_thread; #else db_thread* thread = enif_tsd_get(g_tsd_thread); #endif /*if (thr->isreadonly) { u64 readSafeEvnum, readSafeTerm; #ifndef _TESTAPP_ enif_mutex_lock(pWal->mtx); #endif readSafeEvnum = pWal->rthread->readSafeEvnum; readSafeTerm = pWal->rthread->readSafeTerm; #ifndef _TESTAPP_ enif_mutex_unlock(pWal->mtx); #endif return findframe(pWal->rthread, pWal, pgno, piRead, readSafeTerm, readSafeEvnum, NULL, NULL); } else*/ if (pWal->inProgressTerm > 0 || pWal->inProgressEvnum > 0) return findframe(thread, pWal, pgno, piRead, pWal->inProgressTerm, pWal->inProgressEvnum, NULL, NULL); else return findframe(thread, pWal, pgno, piRead, pWal->lastCompleteTerm, pWal->lastCompleteEvnum, NULL, NULL); }
int main(int argc, char *argv[]) { char *s; fmtinstall('r', errfmt); extern int fmtevent(Fmt*); fmtinstall('E', fmtevent); ARGBEGIN{ default: usage(); }ARGEND; s = EARGF(usage()); if(!getulong(s, &win.xid)) usage(); if(argc) usage(); setlocale(LC_CTYPE, ""); initdisplay(); frame = findframe(&win); getwinsize(&frame); restrut(); sethandler(&frame, &handlers); selectinput(&frame, StructureNotifyMask); running = true; xevent_loop(); XCloseDisplay(display); return 0; }
// return number of bytes written static int wal_iterate(Wal *pWal, iterate_resource *iter, u8 *buf, int bufsize, u8 *hdr, u32 *done) { // db_thread* const thr = enif_tsd_get(g_tsd_thread); #if ATOMIC db_thread *thr = g_tsd_thread; #else db_thread* thr = enif_tsd_get(g_tsd_thread); #endif mdbinf* const mdb = &thr->mdb; u32 mxPage; u64 readSafeEvnum, readSafeTerm; #ifndef _TESTAPP_ enif_mutex_lock(pWal->mtx); #endif readSafeEvnum = pWal->lastCompleteEvnum; readSafeTerm = pWal->lastCompleteTerm; mxPage = pWal->mxPage; #ifndef _TESTAPP_ enif_mutex_unlock(pWal->mtx); #endif if (!iter->started) { if (iter->evnum + iter->evterm == 0) { // If any writes come after iterator started, we must ignore those pages. iter->evnum = readSafeEvnum; iter->evterm = readSafeTerm; iter->pgnoPos = 1; iter->entiredb = 1; iter->mxPage = mxPage; if (pWal->mxPage == 0) { DBG("ERROR: Iterate on empty DB %llu",pWal->lastCompleteEvnum); *done = 1; return 0; } } else { // set mxPage to highest pgno we find. iter->pgnoPos = iter->mxPage = 0; DBG("Iterate rsterm=%llu rsevnum=%llu",readSafeTerm,readSafeEvnum); } iter->started = 1; } // send entire db (without history) if (iter->entiredb) { u32 iRead = 0; findframe(thr, pWal, iter->pgnoPos, &iRead, iter->evterm, iter->evnum, NULL, NULL); if (!iRead) { DBG("Iterate did not find page"); *done = iter->mxPage; return 0; } DBG("Iter pos=%u, mx=%u, safemx=%u",iter->pgnoPos, iter->mxPage, mxPage); if (iter->pgnoPos == iter->mxPage) *done = iter->mxPage; put8byte(hdr, iter->evterm); put8byte(hdr+sizeof(u64), iter->evnum); put4byte(hdr+sizeof(u64)*2, iter->pgnoPos); put4byte(hdr+sizeof(u64)*2+sizeof(u32), *done); iter->pgnoPos++; return fillbuff(thr, pWal, iter, buf, bufsize); } else { MDB_val logKey, logVal; int logop; u8 logKeyBuf[sizeof(u64)*3]; int rc; // ** - Log DB: {<<ActorIndex:64, Evterm:64, Evnum:64>>, <<Pgno:32/unsigned>>} memcpy(logKeyBuf, &pWal->index, sizeof(u64)); memcpy(logKeyBuf + sizeof(u64), &iter->evterm, sizeof(u64)); memcpy(logKeyBuf + sizeof(u64)*2, &iter->evnum, sizeof(u64)); logKey.mv_data = logKeyBuf; logKey.mv_size = sizeof(logKeyBuf); DBG("iterate looking for, matchterm=%llu matchevnum=%llu",iter->evterm,iter->evnum); if (mdb_cursor_get(mdb->cursorLog,&logKey,&logVal,MDB_SET) != MDB_SUCCESS) { // Evterm/evnum combination not found. Check if evnum is there. // If so return evterm. It will mean a node is in conflict. DBG("Key not found in log"); if (readSafeEvnum == iter->evnum) { iter->evterm = readSafeTerm; iter->termMismatch = 1; } else { memcpy(logKeyBuf, &pWal->index, sizeof(u64)); memcpy(logKeyBuf + sizeof(u64), &readSafeTerm, sizeof(u64)); memcpy(logKeyBuf + sizeof(u64)*2, &readSafeEvnum,sizeof(u64)); if (mdb_cursor_get(mdb->cursorLog,&logKey,&logVal,MDB_SET) != MDB_SUCCESS) { DBG("Key not found in log for undo"); *done = 1; return 0; } while (mdb_cursor_get(mdb->cursorLog,&logKey,&logVal,MDB_PREV_NODUP) == MDB_SUCCESS) { u64 aindex, term, evnum; mdb_cursor_get(mdb->cursorLog,&logKey, &logVal, MDB_GET_CURRENT); memcpy(&aindex, logKey.mv_data, sizeof(u64)); memcpy(&term, (u8*)logKey.mv_data+sizeof(u64), sizeof(u64)); memcpy(&evnum, (u8*)logKey.mv_data+sizeof(u64)*2,sizeof(u64)); DBG("Iterate on term=%llu, evnum=%llu, looking for=%llu",term,evnum,iter->evnum); if (aindex != pWal->index) break; if (iter->evnum == evnum) { iter->evterm = term; iter->termMismatch = 1; break; } } } *done = 1; return 0; } // We start iterate from next evnum not current. Input evterm/evnum is match_index and match_term. // It needs next. if (iter->started == 1 && (rc = mdb_cursor_get(mdb->cursorLog,&logKey, &logVal, MDB_NEXT_NODUP)) != MDB_SUCCESS) { *done = 1; return 0; } else { u64 aindex; rc = mdb_cursor_get(mdb->cursorLog,&logKey, &logVal, MDB_GET_CURRENT); if (rc != MDB_SUCCESS) { *done = 1; return 0; } memcpy(&aindex, (u8*)logKey.mv_data, sizeof(u64)); memcpy(&iter->evterm, (u8*)logKey.mv_data+sizeof(u64), sizeof(u64)); memcpy(&iter->evnum, (u8*)logKey.mv_data+sizeof(u64)*2,sizeof(u64)); if (aindex != pWal->index) { *done = 1; return 0; } // To keep from moving iter->evterm/iter->evnum forward more than once. iter->started = 2; } logop = MDB_FIRST_DUP; while ((rc = mdb_cursor_get(mdb->cursorLog,&logKey,&logVal,logop)) == MDB_SUCCESS) { u64 evnum,evterm; u32 pgno; u32 iRead; logop = MDB_NEXT_DUP; mdb_cursor_get(mdb->cursorLog,&logKey, &logVal, MDB_GET_CURRENT); memcpy(&pgno,logVal.mv_data,sizeof(u32)); DBG("iterate at pgno=%u, pgnopos=%u",pgno,iter->pgnoPos); if (pgno <= iter->pgnoPos) continue; findframe(thr, pWal, pgno, &iRead, iter->evterm, iter->evnum, &evterm, &evnum); if (iRead == 0) { DBG("ERROR: Did not find frame for pgno=%u, evterm=%llu, evnum=%llu", pgno, iter->evterm, iter->evnum); *done = 1; return 0; } if (evterm != iter->evterm || evnum != iter->evnum) { DBG("ERROR: Evterm/evnum does not match,looking for: evterm=%llu, evnum=%llu, " "got: evterm=%llu, evnum=%llu", iter->evterm, iter->evnum, evterm, evnum); *done = 1; return 0; } iter->pgnoPos = pgno; if ((rc = mdb_cursor_get(mdb->cursorLog,&logKey,&logVal,logop)) == MDB_SUCCESS) *done = 0; else *done = iter->pgnoPos; DBG( "logcursor get next %d, done=%u",rc,*done); put8byte(hdr, iter->evterm); put8byte(hdr+sizeof(u64), iter->evnum); put4byte(hdr+sizeof(u64)*2, iter->pgnoPos); put4byte(hdr+sizeof(u64)*2+sizeof(u32), *done); return fillbuff(thr, pWal, iter, buf, bufsize); } *done = 1; return 0; } }