Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix to ensure that the log file is always deleted following a successful system shutdown. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3d1dacff87ff9b11f471ab493d1a5533 |
User & Date: | dan 2012-09-27 16:09:46.153 |
Context
2012-09-27
| ||
20:04 | Mark blocks as free more aggressively. check-in: eb4ae342c5 user: dan tags: trunk | |
16:09 | Fix to ensure that the log file is always deleted following a successful system shutdown. check-in: 3d1dacff87 user: dan tags: trunk | |
04:59 | Fix a deadlock in multi-threaded test code. check-in: e16b04ca69 user: dan tags: trunk | |
Changes
Changes to lsm-test/lsmtest_tdb3.c.
︙ | ︙ | |||
929 930 931 932 933 934 935 | static void *worker_main(void *pArg){ LsmWorker *p = (LsmWorker *)pArg; lsm_db *pWorker; /* Connection to access db through */ pthread_mutex_lock(&p->worker_mutex); while( (pWorker = p->pWorker) ){ int rc = LSM_OK; | < < < < | < | | > > > | 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | static void *worker_main(void *pArg){ LsmWorker *p = (LsmWorker *)pArg; lsm_db *pWorker; /* Connection to access db through */ pthread_mutex_lock(&p->worker_mutex); while( (pWorker = p->pWorker) ){ int rc = LSM_OK; int nCkpt = -1; /* Do some work. If an error occurs, exit. */ pthread_mutex_unlock(&p->worker_mutex); if( p->bCkpt ){ rc = lsm_checkpoint(pWorker, 0); }else{ int nWrite = 0; /* Pages written by lsm_work() call */ int nAuto = -1; /* Configured AUTOCHECKPOINT value */ int nLimit = -1; /* Configured WRITE_BUFFER value */ lsm_config(pWorker, LSM_CONFIG_WRITE_BUFFER, &nLimit); lsm_config(pWorker, LSM_CONFIG_AUTOCHECKPOINT, &nAuto); do { int nSleep = 0; lsm_ckpt_size(pWorker, &nCkpt); while( nAuto==0 && nCkpt>(nLimit*4) ){ usleep(1000); mt_signal_worker(p->pDb, 1); |
︙ | ︙ |
Changes to src/lsm_file.c.
︙ | ︙ | |||
313 314 315 316 317 318 319 320 | } /* ** Close the log file. Then delete it from the file-system. This function ** is called during database shutdown only. */ int lsmFsCloseAndDeleteLog(FileSystem *pFS){ if( pFS->fdLog ){ | > > > > > > | | < | | < < | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 | } /* ** Close the log file. Then delete it from the file-system. This function ** is called during database shutdown only. */ int lsmFsCloseAndDeleteLog(FileSystem *pFS){ char *zDel; if( pFS->fdLog ){ lsmEnvClose(pFS->pEnv, pFS->fdLog ); pFS->fdLog = 0; } zDel = lsmMallocPrintf(pFS->pEnv, "%s-log", pFS->zDb); if( zDel ){ lsmEnvUnlink(pFS->pEnv, zDel); lsmFree(pFS->pEnv, zDel); } return LSM_OK; } /* ** Given that there are currently nHash slots in the hash table, return ** the hash key for file iFile, page iPg. |
︙ | ︙ |
Changes to src/lsm_shared.c.
︙ | ︙ | |||
171 172 173 174 175 176 177 | ** connection to the database. In this case flush the contents of the ** in-memory tree to disk and write a checkpoint. */ rc = lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_EXCL, 0); if( rc==LSM_OK ){ /* Flush the in-memory tree, if required. If there is data to flush, ** this will create a new client snapshot in Database.pClient. The ** checkpoint (serialization) of this snapshot may be written to disk | | > > > > > < < < < | < < | < < | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | ** connection to the database. In this case flush the contents of the ** in-memory tree to disk and write a checkpoint. */ rc = lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_EXCL, 0); if( rc==LSM_OK ){ /* Flush the in-memory tree, if required. If there is data to flush, ** this will create a new client snapshot in Database.pClient. The ** checkpoint (serialization) of this snapshot may be written to disk ** by the following block. ** ** There is no need to mess around with WRITER locks or anything at ** this point. The lock on DMS2 guarantees that pDb has exclusive ** access to the db at this point. */ rc = lsmTreeLoadHeader(pDb, 0); if( rc==LSM_OK && (lsmTreeHasOld(pDb) || lsmTreeSize(pDb)>0) ){ rc = lsmFlushTreeToDisk(pDb); } /* Write a checkpoint to disk. */ if( rc==LSM_OK ){ rc = lsmCheckpointWrite(pDb, 0); } /* If the checkpoint was written successfully, delete the log file */ if( rc==LSM_OK ){ Database *p = pDb->pDatabase; lsmFsCloseAndDeleteLog(pDb->pFS); if( p->pFile ) lsmEnvShmUnmap(pDb->pEnv, p->pFile, 1); } } } |
︙ | ︙ |
Changes to src/lsm_sorted.c.
︙ | ︙ | |||
1984 1985 1986 1987 1988 1989 1990 1991 1992 | if( rc==LSM_OK ) pCsr->nSegCsr++; } } return rc; } /* | > > > | < < < | | > > > > > | | < | < | | | | | < < < > | | | | | 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 | if( rc==LSM_OK ) pCsr->nSegCsr++; } } return rc; } #define TREE_NONE 0 #define TREE_OLD 1 #define TREE_BOTH 2 /* ** Parameter eTree must be set to TREE_NONE, OLD or BOTH. */ static int multiCursorNew( lsm_db *pDb, /* Database handle */ Snapshot *pSnap, /* Snapshot to use for this cursor */ int eTree, /* One of the TREE_XXX values above */ int bUserOnly, /* If true, ignore all system data */ MultiCursor **ppCsr /* OUT: Allocated cursor */ ){ int rc = LSM_OK; /* Return Code */ MultiCursor *pCsr = *ppCsr; /* Allocated multi-cursor */ assert( eTree==TREE_NONE || eTree==TREE_OLD || eTree==TREE_BOTH ); if( pCsr==0 ){ pCsr = (MultiCursor *)lsmMallocZeroRc(pDb->pEnv, sizeof(MultiCursor), &rc); if( pCsr ){ pCsr->pNext = pDb->pCsr; pDb->pCsr = pCsr; if( bUserOnly ) pCsr->flags |= CURSOR_IGNORE_SYSTEM; pCsr->pDb = pDb; pCsr->pSnap = pSnap; pCsr->xCmp = pDb->xCmp; } } /* Add a tree cursor on the 'old' tree, if required. */ if( rc==LSM_OK && eTree!=TREE_NONE && lsmTreeHasOld(pDb) && pDb->treehdr.iOldLog!=pSnap->iLogOff ){ rc = lsmTreeCursorNew(pDb, 1, &pCsr->apTreeCsr[1]); } /* Add a tree cursor on the 'current' tree, if required. */ if( rc==LSM_OK && eTree==TREE_BOTH ){ rc = lsmTreeCursorNew(pDb, 0, &pCsr->apTreeCsr[0]); } if( rc!=LSM_OK ){ lsmMCursorClose(pCsr); pCsr = 0; } *ppCsr = pCsr; return rc; } |
︙ | ︙ | |||
2102 2103 2104 2105 2106 2107 2108 | MultiCursor *pCsr = *ppCsr; /* Allocated multi-cursor */ Level *p; /* Level iterator */ Snapshot *pSnap; /* Snapshot to use for cursor */ pSnap = (bSystem ? pDb->pWorker : pDb->pClient); assert( pSnap ); | | > > > | 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 | MultiCursor *pCsr = *ppCsr; /* Allocated multi-cursor */ Level *p; /* Level iterator */ Snapshot *pSnap; /* Snapshot to use for cursor */ pSnap = (bSystem ? pDb->pWorker : pDb->pClient); assert( pSnap ); rc = multiCursorNew(pDb, pSnap, (bSystem ? TREE_NONE : TREE_BOTH), !bSystem, &pCsr ); multiCursorIgnoreDelete(pCsr); for(p=lsmDbSnapshotLevel(pSnap); p && rc==LSM_OK; p=p->pNext){ rc = multiCursorAddLevel(pCsr, p, MULTICURSOR_ADDLEVEL_ALL); } if( rc!=LSM_OK ){ lsmMCursorClose(pCsr); |
︙ | ︙ | |||
3506 3507 3508 3509 3510 3511 3512 | if( pDb->xWork ){ pDb->xWork(pDb, pDb->pWorkCtx); } } static int sortedNewToplevel( lsm_db *pDb, /* Connection handle */ | | | 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 | if( pDb->xWork ){ pDb->xWork(pDb, pDb->pWorkCtx); } } static int sortedNewToplevel( lsm_db *pDb, /* Connection handle */ int eTree, /* One of the TREE_XXX constants */ int *pnOvfl, /* OUT: Number of free-list entries stored */ int *pnWrite /* OUT: Number of database pages written */ ){ int rc = LSM_OK; /* Return Code */ MultiCursor *pCsr = 0; Level *pNext = 0; /* The current top level */ Level *pNew; /* The new level itself */ |
︙ | ︙ | |||
3528 3529 3530 3531 3532 3533 3534 | pNext = lsmDbSnapshotLevel(pDb->pWorker); pNew = (Level *)lsmMallocZeroRc(pDb->pEnv, sizeof(Level), &rc); /* Create a cursor to gather the data required by the new segment. The new ** segment contains everything in the tree and pointers to the next segment ** in the database (if any). */ if( rc==LSM_OK ){ | | | 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 | pNext = lsmDbSnapshotLevel(pDb->pWorker); pNew = (Level *)lsmMallocZeroRc(pDb->pEnv, sizeof(Level), &rc); /* Create a cursor to gather the data required by the new segment. The new ** segment contains everything in the tree and pointers to the next segment ** in the database (if any). */ if( rc==LSM_OK ){ rc = multiCursorNew(pDb, pDb->pWorker, eTree, 0, &pCsr); if( rc==LSM_OK ){ pNew->pNext = pNext; lsmDbSnapshotSetLevel(pDb->pWorker, pNew); } if( rc==LSM_OK ){ if( pNext ){ assert( pNext->pMerge==0 || pNext->nRight>0 ); |
︙ | ︙ | |||
3749 3750 3751 3752 3753 3754 3755 | ** 1. Records from LHS of each of the nMerge levels being merged. ** 2. Separators from either the last level being merged, or the ** separators attached to the LHS of the following level, or neither. ** ** If the new level is the lowest (oldest) in the db, discard any ** delete keys. Key annihilation. */ | | | 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 | ** 1. Records from LHS of each of the nMerge levels being merged. ** 2. Separators from either the last level being merged, or the ** separators attached to the LHS of the following level, or neither. ** ** If the new level is the lowest (oldest) in the db, discard any ** delete keys. Key annihilation. */ rc = multiCursorNew(pDb, pDb->pWorker, TREE_NONE, 0, &pCsr); if( rc==LSM_OK ){ rc = multiCursorAddLevel(pCsr, pLevel, MULTICURSOR_ADDLEVEL_RHS); } if( rc==LSM_OK && pLevel->pNext ){ if( pMerge->nInput > pLevel->nRight ){ Level *pNext = pLevel->pNext; rc = multiCursorAddLevel(pCsr, pNext, MULTICURSOR_ADDLEVEL_LHS_SEP); |
︙ | ︙ | |||
4148 4149 4150 4151 4152 4153 4154 | nRem -= nPg; assert( rc!=LSM_OK || nRem<=0 || !sortedDbIsFull(pDb) ); bToplevel = 1; } if( rc==LSM_OK && nRem>0 ){ int nPg = 0; | | | 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 | nRem -= nPg; assert( rc!=LSM_OK || nRem<=0 || !sortedDbIsFull(pDb) ); bToplevel = 1; } if( rc==LSM_OK && nRem>0 ){ int nPg = 0; rc = sortedNewToplevel(pDb, TREE_OLD, &nOvfl, &nPg); nRem -= nPg; if( rc==LSM_OK && pDb->nTransOpen>0 ){ lsmTreeDiscardOld(pDb); } bFlush = 1; bToplevel = 0; } |
︙ | ︙ | |||
4177 4178 4179 4180 4181 4182 4183 | if( rc==LSM_OK && bToplevel && lsmCheckpointOverflowRequired(pDb) ){ while( rc==LSM_OK && sortedDbIsFull(pDb) ){ int nPg = 0; rc = sortedWork(pDb, 16, 0, 1, &nPg); } if( rc==LSM_OK && lsmCheckpointOverflowRequired(pDb) ){ | | | 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 | if( rc==LSM_OK && bToplevel && lsmCheckpointOverflowRequired(pDb) ){ while( rc==LSM_OK && sortedDbIsFull(pDb) ){ int nPg = 0; rc = sortedWork(pDb, 16, 0, 1, &nPg); } if( rc==LSM_OK && lsmCheckpointOverflowRequired(pDb) ){ rc = sortedNewToplevel(pDb, TREE_NONE, &nOvfl, 0); } } if( rc==LSM_OK && (nRem!=nMax) ){ rc = lsmSortedFlushDb(pDb); lsmFinishWork(pDb, bFlush, nOvfl, &rc); }else{ |
︙ | ︙ | |||
4301 4302 4303 4304 4305 4306 4307 4308 4309 | #if 0 lsmLogMessage(pDb, 0, "auto-work: %d pages", nWrite); #endif return rc; } int lsmFlushTreeToDisk(lsm_db *pDb){ int rc; | > > > > > | > > > > > | < > | 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 | #if 0 lsmLogMessage(pDb, 0, "auto-work: %d pages", nWrite); #endif return rc; } /* ** This function is only called during system shutdown. The contents of ** any in-memory trees present (old or current) are written out to disk. */ int lsmFlushTreeToDisk(lsm_db *pDb){ int rc; int nOvfl = 0; rc = lsmBeginWork(pDb); while( rc==LSM_OK && sortedDbIsFull(pDb) ){ rc = sortedWork(pDb, 256, 0, 1, 0); } if( rc==LSM_OK ){ rc = sortedNewToplevel(pDb, TREE_BOTH, &nOvfl, 0); } lsmFinishWork(pDb, 1, nOvfl, &rc); return rc; } /* ** Return a string representation of the segment passed as the only argument. ** Space for the returned string is allocated using lsmMalloc(), and should ** be freed by the caller using lsmFree(). |
︙ | ︙ |
Changes to tool/lsmperf.tcl.
︙ | ︙ | |||
164 165 166 167 168 169 170 | append script $data2 append script $data3 append script "pause -1\n" exec_gnuplot_script $script $zPng } | | > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | append script $data2 append script $data3 append script "pause -1\n" exec_gnuplot_script $script $zPng } do_write_test x.png 120 50000 0 30 { lsm-mt "mmap=1 multi_proc=0 threads=3 autowork=0 autocheckpoint=0" leveldb leveldb } # lsm-mt "mmap=1 multi_proc=0 threads=2 autowork=0 autocheckpoint=8192000" # lsm-mt "mmap=1 multi_proc=0 safety=1 threads=3 autowork=0" # lsm-st "mmap=1 multi_proc=0 safety=1 threads=1 autowork=1" # lsm-mt "mmap=1 multi_proc=0 safety=1 threads=3 autowork=0" # lsm-mt "mmap=1 multi_proc=0 safety=1 threads=3 autowork=0" # LevelDB leveldb # lsm-st "mmap=1 multi_proc=0 safety=1 threads=1 autowork=1" |
︙ | ︙ |