/* ** Open a new cursor handle. ** ** If there are currently no other open cursor handles, and no open write ** transaction, open a read transaction here. */ int lsm_csr_open(lsm_db *pDb, lsm_cursor **ppCsr){ int rc = LSM_OK; /* Return code */ MultiCursor *pCsr = 0; /* New cursor object */ /* Open a read transaction if one is not already open. */ assert_db_state(pDb); if( pDb->pShmhdr==0 ){ assert( pDb->bReadonly ); rc = lsmBeginRoTrans(pDb); }else if( pDb->iReader<0 ){ rc = lsmBeginReadTrans(pDb); } /* Allocate the multi-cursor. */ if( rc==LSM_OK ){ rc = lsmMCursorNew(pDb, &pCsr); } /* If an error has occured, set the output to NULL and delete any partially ** allocated cursor. If this means there are no open cursors, release the ** client snapshot. */ if( rc!=LSM_OK ){ lsmMCursorClose(pCsr, 0); dbReleaseClientSnapshot(pDb); } assert_db_state(pDb); *ppCsr = (lsm_cursor *)pCsr; return rc; }
/* ** Close a cursor opened using lsm_csr_open(). */ int lsm_csr_close(lsm_cursor *p){ if( p ){ lsm_db *pDb = lsmMCursorDb((MultiCursor *)p); assert_db_state(pDb); lsmMCursorClose((MultiCursor *)p, 1); dbReleaseClientSnapshot(pDb); assert_db_state(pDb); } return LSM_OK; }
int lsm_close(lsm_db *pDb){ int rc = LSM_OK; if( pDb ){ assert_db_state(pDb); if( pDb->pCsr || pDb->nTransOpen ){ rc = LSM_MISUSE_BKPT; }else{ lsmMCursorFreeCache(pDb); lsmFreeSnapshot(pDb->pEnv, pDb->pClient); pDb->pClient = 0; assertRwclientLockValue(pDb); lsmDbDatabaseRelease(pDb); lsmLogClose(pDb); lsmFsClose(pDb->pFS); assert( pDb->mLock==0 ); /* Invoke any destructors registered for the compression or ** compression factory callbacks. */ if( pDb->factory.xFree ) pDb->factory.xFree(pDb->factory.pCtx); if( pDb->compress.xFree ) pDb->compress.xFree(pDb->compress.pCtx); lsmFree(pDb->pEnv, pDb->rollback.aArray); lsmFree(pDb->pEnv, pDb->aTrans); lsmFree(pDb->pEnv, pDb->apShm); lsmFree(pDb->pEnv, pDb); } } return rc; }
int lsm_commit(lsm_db *pDb, int iLevel){ int rc = LSM_OK; assert_db_state( pDb ); /* A value less than zero means close the innermost nested transaction. */ if( iLevel<0 ) iLevel = LSM_MAX(0, pDb->nTransOpen - 1); if( iLevel<pDb->nTransOpen ){ if( iLevel==0 ){ /* Commit the transaction to disk. */ if( pDb->pTV && lsmTreeSize(pDb->pTV)>pDb->nTreeLimit ){ rc = lsmFlushToDisk(pDb); } if( rc==LSM_OK ) rc = lsmLogCommit(pDb); if( rc==LSM_OK && pDb->eSafety==LSM_SAFETY_FULL ){ rc = lsmFsSyncLog(pDb->pFS); } lsmFinishWriteTrans(pDb, (rc==LSM_OK)); } pDb->nTransOpen = iLevel; } dbReleaseClientSnapshot(pDb); return rc; }
int lsm_get_user_version(lsm_db *pDb, unsigned int *piUsr){ int rc = LSM_OK; /* Return code */ /* Open a read transaction if one is not already open. */ assert_db_state(pDb); if( pDb->pShmhdr==0 ){ assert( pDb->bReadonly ); rc = lsmBeginRoTrans(pDb); }else if( pDb->iReader<0 ){ rc = lsmBeginReadTrans(pDb); } /* Allocate the multi-cursor. */ if( rc==LSM_OK ){ *piUsr = pDb->treehdr.iUsrVersion; } dbReleaseClientSnapshot(pDb); assert_db_state(pDb); return rc; }
int lsm_close(lsm_db *pDb){ int rc = LSM_OK; if( pDb ){ assert_db_state(pDb); if( pDb->pCsr || pDb->nTransOpen ){ rc = LSM_MISUSE_BKPT; }else{ assert( pDb->pWorker==0 && pDb->pTV==0 ); lsmDbDatabaseRelease(pDb); lsmFsClose(pDb->pFS); lsmFree(pDb->pEnv, pDb->aTrans); lsmFree(pDb->pEnv, pDb); } } return rc; }
int lsm_begin(lsm_db *pDb, int iLevel){ int rc; assert_db_state( pDb ); rc = (pDb->bReadonly ? LSM_READONLY : LSM_OK); /* A value less than zero means open one more transaction. */ if( iLevel<0 ) iLevel = pDb->nTransOpen + 1; if( iLevel>pDb->nTransOpen ){ int i; /* Extend the pDb->aTrans[] array if required. */ if( rc==LSM_OK && pDb->nTransAlloc<iLevel ){ TransMark *aNew; /* New allocation */ int nByte = sizeof(TransMark) * (iLevel+1); aNew = (TransMark *)lsmRealloc(pDb->pEnv, pDb->aTrans, nByte); if( !aNew ){ rc = LSM_NOMEM; }else{ nByte = sizeof(TransMark) * (iLevel+1 - pDb->nTransAlloc); memset(&aNew[pDb->nTransAlloc], 0, nByte); pDb->nTransAlloc = iLevel+1; pDb->aTrans = aNew; } } if( rc==LSM_OK && pDb->nTransOpen==0 ){ rc = lsmBeginWriteTrans(pDb); } if( rc==LSM_OK ){ for(i=pDb->nTransOpen; i<iLevel; i++){ lsmTreeMark(pDb, &pDb->aTrans[i].tree); lsmLogTell(pDb, &pDb->aTrans[i].log); } pDb->nTransOpen = iLevel; } } return rc; }
int lsm_rollback(lsm_db *pDb, int iLevel){ int rc = LSM_OK; assert_db_state( pDb ); if( pDb->nTransOpen ){ /* A value less than zero means close the innermost nested transaction. */ if( iLevel<0 ) iLevel = LSM_MAX(0, pDb->nTransOpen - 1); if( iLevel<=pDb->nTransOpen ){ TransMark *pMark = &pDb->aTrans[(iLevel==0 ? 0 : iLevel-1)]; lsmTreeRollback(pDb, &pMark->tree); if( iLevel ) lsmLogSeek(pDb, &pMark->log); pDb->nTransOpen = iLevel; } if( pDb->nTransOpen==0 ){ lsmFinishWriteTrans(pDb, 0); } dbReleaseClientSnapshot(pDb); } return rc; }