├── .classpath ├── .gitattributes ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs └── org.eclipse.jdt.core.prefs ├── README.md ├── src └── tenndb │ ├── IBase.java │ ├── base │ ├── Catalog.java │ ├── Cell.java │ └── TennBase.java │ ├── bstar │ ├── BTreeNode.java │ ├── IdxBlock.java │ ├── IdxOld.java │ ├── InsertVar.java │ ├── RandomInsertBStarTree.java │ └── SplitLeafVar.java │ ├── common │ ├── ByteUtil.java │ ├── DateFormatUtil.java │ ├── FileDeco.java │ ├── FileMgr.java │ ├── FileUtil.java │ ├── GraphFindCycle.java │ ├── SystemTime.java │ └── test │ │ └── TestSystemTime.java │ ├── data │ ├── ByteBufferMgr.java │ ├── Colunm.java │ ├── DBBlock.java │ ├── DBPage.java │ ├── DBPageMgr.java │ ├── Filed.java │ ├── PageBuffer.java │ ├── PageBufferMgr.java │ └── PageUnusedIndex.java │ ├── dist │ ├── DistMgr.java │ └── DistPage.java │ ├── disttest │ ├── DemoThread.java │ ├── Test.java │ ├── TestDist.java │ ├── TestFileName.java │ └── TestRoute.java │ ├── index │ ├── IBTree.java │ ├── IndexMgr.java │ └── IndexPage.java │ ├── log │ ├── CellLogMgr.java │ ├── LogMgr.java │ └── LogRecord.java │ ├── route │ └── RouteMgr.java │ ├── routetest │ └── TestRoute.java │ ├── test │ ├── TestAbortTransException.java │ ├── TestByte.java │ ├── TestCell.java │ ├── TestDBPageMgr.java │ ├── TestFileMgr.java │ ├── TestIndexMgr.java │ ├── TestLogMgr.java │ ├── TestRun.java │ └── TestTennBase.java │ ├── thread │ ├── DistThread.java │ ├── FlushHook.java │ ├── ImportThread.java │ └── ShutdownHook.java │ ├── threadtest │ ├── InsertThread.java │ └── TestTennBase.java │ ├── tx │ ├── AbortTransException.java │ ├── BlkID.java │ ├── Trans.java │ └── TransMgr.java │ └── txtest │ └── TestInsertTx.java └── 简易数据库存储系统的JAVA实现.ppt /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | entries 5 | format 6 | wc.db 7 | wc.db-journal 8 | 9 | # Folder config file 10 | Desktop.ini 11 | 12 | # Recycle Bin used on file shares 13 | $RECYCLE.BIN/ 14 | 15 | # Windows Installer files 16 | *.cab 17 | *.msi 18 | *.msm 19 | *.msp 20 | *.svn-base 21 | *.class 22 | 23 | # Windows shortcuts 24 | *.lnk 25 | 26 | # ========================= 27 | # Operating System Files 28 | # ========================= 29 | 30 | # OSX 31 | # ========================= 32 | 33 | .DS_Store 34 | .AppleDouble 35 | .LSOverride 36 | 37 | # Thumbnails 38 | ._* 39 | 40 | # Files that might appear in the root of a volume 41 | .DocumentRevisions-V100 42 | .fseventsd 43 | .Spotlight-V100 44 | .TemporaryItems 45 | .Trashes 46 | .VolumeIcon.icns 47 | 48 | # Directories potentially created on remote AFP share 49 | .AppleDB 50 | .AppleDesktop 51 | Network Trash Folder 52 | Temporary Items 53 | .apdisk 54 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | TennBase5 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | #Fri Jul 08 08:44:06 CST 2016 2 | eclipse.preferences.version=1 3 | encoding/=UTF-8 4 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Fri Jun 24 14:47:25 CST 2016 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.6 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.source=1.6 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TennBase 2 | a lightweight datastore based on B*tree implements some basic function of hbase. 3 | 4 | thread-safe, simple transaction, reach by b-start tree, append new data to data file in order to insert and update quickly. 5 | 6 | consist of three parts, b-start tree index, data file and logs. 7 | -------------------------------------------------------------------------------- /src/tenndb/IBase.java: -------------------------------------------------------------------------------- 1 | package tenndb; 2 | 3 | import java.util.List; 4 | 5 | import tenndb.data.Colunm; 6 | import tenndb.tx.AbortTransException; 7 | import tenndb.tx.Trans; 8 | 9 | public interface IBase { 10 | 11 | public boolean insert(int key, byte[] buff, int offset, int len); 12 | 13 | public boolean update(int key, byte[] buff, int offset, int len); 14 | 15 | 16 | public boolean insert(int key, Colunm colunm); 17 | 18 | public boolean update(int key, Colunm colunm); 19 | 20 | public boolean delete(int key); 21 | 22 | public Colunm search(int key); 23 | 24 | 25 | public boolean insert(int key, Colunm colunm, Trans tid) throws AbortTransException; 26 | 27 | public boolean update(int key, Colunm colunm, Trans tid) throws AbortTransException; 28 | 29 | public boolean delete(int key, Trans tid) throws AbortTransException; 30 | 31 | public boolean rollback(int key, Trans tid); 32 | 33 | public boolean commit(int key, Trans tid); 34 | 35 | public Colunm search(int key, Trans tid); 36 | 37 | public int count(int fromKey, int toKey); 38 | 39 | public List range(int fromKey, int toKey, boolean isInc); 40 | 41 | public void printTreeNext(); 42 | 43 | public void printTreePrior(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/tenndb/base/Catalog.java: -------------------------------------------------------------------------------- 1 | package tenndb.base; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Hashtable; 5 | import java.util.Map; 6 | import java.util.Set; 7 | import java.util.concurrent.locks.ReadWriteLock; 8 | import java.util.concurrent.locks.ReentrantReadWriteLock; 9 | 10 | import tenndb.common.FileMgr; 11 | import tenndb.data.ByteBufferMgr; 12 | import tenndb.data.DBPage; 13 | import tenndb.log.LogMgr; 14 | import tenndb.tx.BlkID; 15 | import tenndb.tx.Trans; 16 | import tenndb.tx.TransMgr; 17 | 18 | public class Catalog { 19 | 20 | protected final String cataName; 21 | protected final String root; 22 | 23 | protected final FileMgr fileMgr; 24 | protected final LogMgr logMgr; 25 | protected final TransMgr transMgr; 26 | 27 | protected final ByteBufferMgr bufMgr; 28 | protected Map tabNameToCells = null; 29 | protected Map tabIdToCells = null; 30 | 31 | protected final ReadWriteLock lock = new ReentrantReadWriteLock(false); 32 | 33 | public Catalog(String root){ 34 | this.cataName = "tennbase"; 35 | this.root = root; 36 | this.fileMgr = new FileMgr(this.root); 37 | 38 | this.logMgr = new LogMgr(this.cataName, this.root); 39 | this.bufMgr = new ByteBufferMgr(DBPage.PAGE_SIZE); 40 | this.tabNameToCells = new Hashtable(); 41 | this.tabIdToCells = new Hashtable(); 42 | this.transMgr = new TransMgr(); 43 | } 44 | 45 | public Trans beginTrans(){ 46 | Trans trans = new Trans(); 47 | 48 | this.logMgr.logBegin(trans); 49 | this.transMgr.setTransState(trans, Trans.ACTIVE); 50 | 51 | return trans; 52 | } 53 | 54 | public void recover(){ 55 | this.logMgr.recover(this); 56 | } 57 | 58 | public void flush(){ 59 | 60 | try{ 61 | this.lockRead(); 62 | Set set = this.tabNameToCells.keySet(); 63 | for(String dbName : set){ 64 | Cell cell = this.tabNameToCells.get(dbName); 65 | cell.flush(); 66 | } 67 | }catch(Exception e){} 68 | finally{ 69 | this.unLockRead(); 70 | } 71 | } 72 | 73 | public boolean rollback(Trans tid){ 74 | boolean b = false; 75 | 76 | if(null != tid && tid.getTransID() > 0 && null != this.transMgr){ 77 | try{ 78 | this.logMgr.logRollback(tid); 79 | this.lockRead(); 80 | ArrayList blks = this.transMgr.getTransBlks(tid); 81 | if(null != blks && blks.size() > 0){ 82 | 83 | for(int i = blks.size() - 1; i >= 0; --i){ 84 | BlkID blk = blks.get(i); 85 | Cell cell = this.tabNameToCells.get(blk.getDbName()); 86 | if(null != cell){ 87 | cell.rollback(blk.getKey(), tid); 88 | } 89 | } 90 | } 91 | this.transMgr.delTransBlks(tid); 92 | b = true; 93 | }catch(Exception e){} 94 | finally{ 95 | this.unLockRead(); 96 | } 97 | this.logMgr.logTerminated(tid); 98 | } 99 | 100 | return b; 101 | } 102 | 103 | public byte state(Trans tid){ 104 | return this.transMgr.getTransState(tid); 105 | } 106 | 107 | public boolean commit(Trans tid){ 108 | boolean b = false; 109 | 110 | if(null != tid && tid.getTransID() > 0 && null != this.transMgr){ 111 | 112 | if(tid.getState() == Trans.ACTIVE){ 113 | try{ 114 | this.logMgr.logCommit(tid); 115 | 116 | this.lockRead(); 117 | ArrayList blks = this.transMgr.getTransBlks(tid); 118 | if(null != blks && blks.size() > 0){ 119 | 120 | for(int i = blks.size() - 1; i >= 0; --i){ 121 | BlkID blk = blks.get(i); 122 | Cell cell = this.tabNameToCells.get(blk.getDbName()); 123 | if(null != cell){ 124 | cell.commit(blk.getKey(), tid); 125 | } 126 | } 127 | } 128 | this.transMgr.delTransBlks(tid); 129 | b = true; 130 | }catch(Exception e){} 131 | finally{ 132 | this.unLockRead(); 133 | } 134 | this.logMgr.logTerminated(tid); 135 | } 136 | } 137 | 138 | return b; 139 | } 140 | 141 | public boolean addCell(String dbName, int dbID){ 142 | boolean b = false; 143 | if(!tabNameToCells.containsKey(dbName)){ 144 | Cell cell = new Cell(dbName, dbID, this.fileMgr, this.transMgr, this.logMgr); 145 | cell.init(); 146 | // System.out.println("addCell " + dbName); 147 | 148 | try{ 149 | this.lockWrite(); 150 | this.tabNameToCells.put(dbName, cell); 151 | this.tabIdToCells.put(dbID, cell); 152 | b = true; 153 | }catch(Exception e){} 154 | finally{ 155 | this.unLockWrite(); 156 | } 157 | } 158 | return b; 159 | } 160 | 161 | public final Cell getCell(int dbID){ 162 | return this.tabIdToCells.get(dbID); 163 | } 164 | 165 | public final Cell getCell(String dbName){ 166 | return this.tabNameToCells.get(dbName); 167 | } 168 | 169 | protected void lockRead() { this.lock.readLock().lock(); } 170 | 171 | protected void unLockRead() { this.lock.readLock().unlock(); } 172 | 173 | protected void lockWrite() { this.lock.writeLock().lock(); } 174 | 175 | protected void unLockWrite() { this.lock.writeLock().unlock(); } 176 | } 177 | -------------------------------------------------------------------------------- /src/tenndb/base/Cell.java: -------------------------------------------------------------------------------- 1 | package tenndb.base; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.locks.ReadWriteLock; 6 | import java.util.concurrent.locks.ReentrantReadWriteLock; 7 | 8 | import tenndb.IBase; 9 | import tenndb.bstar.IdxBlock; 10 | import tenndb.common.FileMgr; 11 | import tenndb.data.DBBlock; 12 | import tenndb.data.DBPageMgr; 13 | import tenndb.data.Colunm; 14 | import tenndb.index.IBTree; 15 | import tenndb.index.IndexMgr; 16 | import tenndb.log.CellLogMgr; 17 | import tenndb.log.LogMgr; 18 | import tenndb.thread.FlushHook; 19 | import tenndb.tx.AbortTransException; 20 | import tenndb.tx.Trans; 21 | import tenndb.tx.TransMgr; 22 | 23 | 24 | public class Cell implements IBase{ 25 | 26 | protected IBTree index = null; 27 | 28 | protected final IndexMgr indexMgr; 29 | protected final DBPageMgr pageMgr; 30 | 31 | protected final FileMgr fileMgr; 32 | protected final TransMgr transMgr; 33 | protected final CellLogMgr logMgr; 34 | 35 | protected final String dbName; 36 | protected final int tabID; 37 | 38 | protected FlushHook flushHook = null; 39 | 40 | 41 | 42 | protected final ReadWriteLock lock = new ReentrantReadWriteLock(false); 43 | 44 | protected volatile boolean initialized = false; 45 | 46 | 47 | public Cell(String dbName, int tabID, FileMgr fileMgr, TransMgr transMgr, LogMgr logMgr) { 48 | super(); 49 | this.dbName = dbName; 50 | this.tabID = tabID; 51 | this.fileMgr = fileMgr; 52 | this.transMgr = transMgr; 53 | this.logMgr = new CellLogMgr(this.tabID, logMgr); 54 | this.pageMgr = new DBPageMgr(this.dbName, fileMgr); 55 | this.indexMgr = new IndexMgr(this.dbName, fileMgr, transMgr); 56 | } 57 | 58 | public String getDbName() { 59 | return dbName; 60 | } 61 | 62 | public final IBTree getIndex() { 63 | return index; 64 | } 65 | 66 | public void init(){ 67 | if(false == this.initialized){ 68 | try{ 69 | this.lockWrite(); 70 | if(false == this.initialized){ 71 | this.indexMgr.load(); 72 | this.pageMgr.load(); 73 | this.index = this.indexMgr.getBTree(); 74 | 75 | this.flushHook = new FlushHook(this); 76 | this.flushHook.start(); 77 | 78 | this.initialized = true; 79 | } 80 | }catch(Exception e){ 81 | System.out.println(e); 82 | }finally{ 83 | this.unLockWrite(); 84 | } 85 | } 86 | } 87 | 88 | public boolean flushNewPages(){ 89 | return this.indexMgr.flushNewPages(); 90 | } 91 | 92 | public void flush(){ 93 | this.indexMgr.flush(); 94 | this.pageMgr.flush(); 95 | } 96 | 97 | public void print(){ 98 | List strList = new ArrayList(); 99 | this.index.print(strList); 100 | if(null != strList){ 101 | for(String str : strList){ 102 | System.out.println(str); 103 | } 104 | } 105 | } 106 | 107 | @Override 108 | public void printTreePrior(){ 109 | this.index.printTreePrior(); 110 | } 111 | 112 | @Override 113 | public void printTreeNext(){ 114 | this.index.printNext(); 115 | } 116 | 117 | @Override 118 | public boolean insert(int key, byte[] buff, int offset, int len){ 119 | boolean b = false; 120 | if(null != buff && buff.length > 0 && offset >= 0 && len > 0 && (offset + len) <= buff.length){ 121 | 122 | DBBlock bblk = this.pageMgr.nextDBBlock(key, 1, buff, offset, len); 123 | 124 | if(null != bblk){ 125 | 126 | IdxBlock newblk = new IdxBlock(key); 127 | newblk.setPageID(bblk.getPageID()); 128 | newblk.setOffset(bblk.getOffset()); 129 | newblk.setTag(IdxBlock.VALID); 130 | 131 | try { 132 | this.index.insert(key, newblk, null, this.logMgr); 133 | } catch (AbortTransException e) { 134 | e.printStackTrace(); 135 | } 136 | 137 | b = true; 138 | } 139 | } 140 | return b; 141 | } 142 | 143 | @Override 144 | public boolean update(int key, byte[] buff, int offset, int size){ 145 | boolean b = false; 146 | IdxBlock oldblk = null; 147 | 148 | if(null != buff){ 149 | 150 | DBBlock bblk = this.pageMgr.nextDBBlock(key, 0, buff, offset, size); 151 | 152 | if(null != bblk){ 153 | 154 | IdxBlock newblk = new IdxBlock(key); 155 | newblk.setPageID(bblk.getPageID()); 156 | newblk.setOffset(bblk.getOffset()); 157 | 158 | try { 159 | oldblk = this.index.update(key, newblk, null, this.logMgr); 160 | } catch (AbortTransException e) { 161 | e.printStackTrace(); 162 | } 163 | 164 | if(null != oldblk){ 165 | b = true; 166 | } 167 | } 168 | } 169 | 170 | return b; 171 | } 172 | 173 | @Override 174 | public boolean insert(int key, Colunm colunm){ 175 | boolean b = false; 176 | 177 | try { 178 | b = this.insert(key, colunm, null); 179 | } catch (AbortTransException e) { 180 | System.out.println(e); 181 | } 182 | 183 | return b; 184 | } 185 | 186 | @Override 187 | public boolean update(int key, Colunm colunm) { 188 | boolean b = false; 189 | 190 | try { 191 | b = this.update(key, colunm, null); 192 | } catch (AbortTransException e) { 193 | System.out.println(e); 194 | } 195 | 196 | return b; 197 | } 198 | 199 | @Override 200 | public boolean delete(int key){ 201 | boolean b = false; 202 | try { 203 | b = this.delete(key, null); 204 | } catch (AbortTransException e) { 205 | System.out.println(e); 206 | } 207 | return b; 208 | } 209 | 210 | @Override 211 | public Colunm search(int key){ 212 | return this.search(key, null); 213 | } 214 | 215 | @Override 216 | public boolean rollback(int key, Trans tid){ 217 | 218 | return this.index.rollback(key, tid, logMgr); 219 | } 220 | 221 | @Override 222 | public boolean commit(int key, Trans tid){ 223 | 224 | return this.index.commit(key, tid, logMgr); 225 | } 226 | 227 | public boolean recoverDelete(int key){ 228 | boolean b = false; 229 | IdxBlock blk = this.index.search(key, null); 230 | if(null != blk){ 231 | blk.setTag(IdxBlock.INVALID); 232 | b = this.indexMgr.flushBlock(blk); 233 | } 234 | return b; 235 | } 236 | 237 | public boolean recoverInsert(int key, int pageID, int offset){ 238 | boolean b = false; 239 | IdxBlock blk = this.index.search(key, null); 240 | if(null != blk){ 241 | blk.setPageID(pageID); 242 | blk.setOffset(offset); 243 | b = this.indexMgr.flushBlock(blk); 244 | } 245 | return b; 246 | } 247 | 248 | public boolean recoverUpdate(int key, int pageID, int offset){ 249 | boolean b = false; 250 | IdxBlock blk = this.index.search(key, null); 251 | if(null != blk){ 252 | blk.setPageID(pageID); 253 | blk.setOffset(offset); 254 | b = this.indexMgr.flushBlock(blk); 255 | } 256 | return b; 257 | } 258 | 259 | @Override 260 | public boolean insert(int key, Colunm colunm, Trans tid) throws AbortTransException{ 261 | boolean b = false; 262 | if(null != colunm){ 263 | 264 | DBBlock bblk = this.pageMgr.nextDBBlock(colunm); 265 | 266 | if(null != bblk){ 267 | 268 | IdxBlock newblk = new IdxBlock(key); 269 | newblk.setPageID(bblk.getPageID()); 270 | newblk.setOffset(bblk.getOffset()); 271 | newblk.setTag(IdxBlock.VALID); 272 | 273 | this.index.insert(key, newblk, tid, this.logMgr); 274 | 275 | b = true; 276 | } 277 | } 278 | return b; 279 | } 280 | 281 | 282 | @Override 283 | public boolean update(int key, Colunm colunm, Trans tid) throws AbortTransException{ 284 | boolean b = false; 285 | IdxBlock oldblk = null; 286 | 287 | if(null != colunm){ 288 | 289 | DBBlock bblk = this.pageMgr.nextDBBlock(colunm); 290 | 291 | if(null != bblk){ 292 | 293 | IdxBlock newblk = new IdxBlock(key); 294 | newblk.setPageID(bblk.getPageID()); 295 | newblk.setOffset(bblk.getOffset()); 296 | 297 | oldblk = this.index.update(key, newblk, tid, this.logMgr); 298 | 299 | if(null != oldblk){ 300 | b = true; 301 | } 302 | } 303 | } 304 | 305 | return b; 306 | } 307 | 308 | @Override 309 | public boolean delete(int key, Trans tid) throws AbortTransException{ 310 | boolean b = false; 311 | IdxBlock oldblk = null; 312 | 313 | oldblk = this.index.delete(key, tid, this.logMgr); 314 | 315 | if(null != oldblk){ 316 | b = true; 317 | } 318 | 319 | return b; 320 | } 321 | 322 | public IdxBlock getIdxBlock(int key){ 323 | return this.index.search(key, null); 324 | } 325 | 326 | @Override 327 | public Colunm search(int key, Trans tid){ 328 | Colunm colunm = null; 329 | 330 | IdxBlock iblk = this.index.search(key, tid); 331 | if(null != iblk){ 332 | 333 | DBBlock bblk = this.pageMgr.getDBBlock(iblk.getPageID(), iblk.getOffset()); 334 | if(null != bblk){ 335 | colunm = bblk.getColunm(); 336 | colunm.setTime(iblk.getTime()); 337 | } 338 | } 339 | return colunm; 340 | } 341 | 342 | @Override 343 | public int count(int fromKey, int toKey){ 344 | 345 | return this.index.count(fromKey, toKey); 346 | } 347 | 348 | @Override 349 | public List range(int fromKey, int toKey, boolean isInc){ 350 | 351 | List bbList = new ArrayList(); 352 | 353 | List idxBList = this.index.range(fromKey, toKey, isInc); 354 | 355 | if(null != idxBList && idxBList.size() > 0){ 356 | 357 | DBBlock temp = null; 358 | for(int i = 0; i < idxBList.size(); ++i){ 359 | IdxBlock blk = idxBList.get(i); 360 | temp = this.pageMgr.getDBBlock(blk.getPageID(), blk.getOffset()); 361 | if(null != temp){ 362 | bbList.add(temp.getColunm()); 363 | } 364 | } 365 | } 366 | 367 | return bbList; 368 | } 369 | 370 | 371 | protected void lockRead() { this.lock.readLock().lock(); } 372 | 373 | protected void unLockRead() { this.lock.readLock().unlock(); } 374 | 375 | protected void lockWrite() { this.lock.writeLock().lock(); } 376 | 377 | protected void unLockWrite() { this.lock.writeLock().unlock(); } 378 | } 379 | -------------------------------------------------------------------------------- /src/tenndb/base/TennBase.java: -------------------------------------------------------------------------------- 1 | package tenndb.base; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | 5 | import tenndb.thread.ShutdownHook; 6 | 7 | public class TennBase { 8 | 9 | private static AtomicReference _instance = new AtomicReference(new TennBase()); 10 | 11 | protected final Catalog catalog; 12 | protected final ShutdownHook shutdown; 13 | 14 | private TennBase(){ 15 | String root = "J:\\tennbase"; 16 | this.catalog = new Catalog(root); 17 | this.catalog.recover(); 18 | this.shutdown = new ShutdownHook(this.catalog); 19 | Runtime.getRuntime().addShutdownHook(this.shutdown); 20 | } 21 | 22 | public static Catalog getCatalog(){ 23 | return _instance.get().catalog; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/tenndb/bstar/BTreeNode.java: -------------------------------------------------------------------------------- 1 | package tenndb.bstar; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.List; 5 | import java.util.concurrent.locks.ReadWriteLock; 6 | import java.util.concurrent.locks.ReentrantReadWriteLock; 7 | 8 | import tenndb.common.ByteUtil; 9 | import tenndb.common.SystemTime; 10 | import tenndb.data.ByteBufferMgr; 11 | import tenndb.index.IndexPage; 12 | import tenndb.log.CellLogMgr; 13 | import tenndb.tx.AbortTransException; 14 | import tenndb.tx.BlkID; 15 | import tenndb.tx.Trans; 16 | import tenndb.tx.TransMgr; 17 | 18 | 19 | 20 | public class BTreeNode { 21 | 22 | protected final static int NODE_BRANCH = 0; 23 | protected final static int NODE_LEAF = 1; 24 | protected final static int NODE_ROOT = 2; 25 | protected final static int MAX_SIZE = RandomInsertBStarTree.BALANCE_SIZE; 26 | protected int[] keys; 27 | protected BTreeNode[] children; 28 | protected IdxBlock[] values; 29 | 30 | protected int numKeys = 0; 31 | 32 | protected BTreeNode parent = null; 33 | protected BTreeNode next = null; 34 | protected BTreeNode prior = null; 35 | 36 | protected String dbName = null; 37 | 38 | protected boolean isLeaf = false; 39 | 40 | //index page file 41 | // protected int nodeID = -1; 42 | 43 | protected int pageID = -1; 44 | protected int parentID = -1; 45 | protected int priorID = -1; 46 | protected int nextID = -1; 47 | 48 | public int size() { return this.numKeys; } 49 | 50 | public boolean leaf() { return this.isLeaf; } 51 | 52 | public IdxBlock getBlock(int index) { 53 | IdxBlock blk = null; 54 | 55 | if(index < this.numKeys){ 56 | blk = this.values[index]; 57 | } 58 | 59 | return blk; 60 | } 61 | 62 | public static ByteBufferMgr buffMgr = new ByteBufferMgr(IndexPage.PAGE_SIZE); 63 | 64 | protected IndexPage refPage = null; 65 | 66 | protected ReadWriteLock lock = new ReentrantReadWriteLock(false); 67 | 68 | protected void lockRead() { this.lock.readLock().lock(); } 69 | 70 | protected void unLockRead() { this.lock.readLock().unlock(); } 71 | 72 | protected void lockWrite() { this.lock.writeLock().lock(); } 73 | 74 | protected void unLockWrite() { this.lock.writeLock().unlock(); } 75 | 76 | public IndexPage getRefPage() { 77 | return refPage; 78 | } 79 | 80 | public void setRefPage(IndexPage refPage) { 81 | this.refPage = refPage; 82 | } 83 | 84 | public void setPageID(int pageID){ 85 | this.pageID = pageID; 86 | } 87 | 88 | public int getPageID(){ 89 | return this.pageID; 90 | } 91 | 92 | public BTreeNode(String dbName, boolean isLeaf, int num, int[] keys, IdxBlock[] values, BTreeNode[] children, BTreeNode parent, BTreeNode next, BTreeNode prior){ 93 | this.dbName = dbName; 94 | this.isLeaf = isLeaf; 95 | this.numKeys = num; 96 | // System.out.println("num = " + num); 97 | this.keys = new int[MAX_SIZE + 1]; 98 | 99 | for(int i = 0; i < numKeys; ++i){ 100 | this.keys[i] = keys[i]; 101 | } 102 | 103 | if(this.isLeaf){ 104 | this.values = new IdxBlock[MAX_SIZE + 2]; 105 | 106 | for(int i = 0; i < num + 2; ++i){ 107 | if(i < values.length) 108 | this.values[i] = values[i]; 109 | else 110 | this.values[i] = null; 111 | } 112 | }else{ 113 | 114 | this.children = new BTreeNode[MAX_SIZE + 2]; 115 | if(null != children){ 116 | 117 | for(int i = 0; i < num + 2; ++i){ 118 | if(i < children.length) 119 | this.children[i] = children[i]; 120 | else 121 | this.children[i] = null; 122 | } 123 | } 124 | } 125 | 126 | this.parent = parent; 127 | this.next = next; 128 | this.prior = prior; 129 | } 130 | 131 | public void toByteBuffer(ByteBuffer buffer, BTreeNode rootNode){ 132 | buffer.rewind(); 133 | 134 | byte type = (byte)(true == this.isLeaf ? NODE_LEAF : NODE_BRANCH); 135 | 136 | if(this == rootNode){ 137 | type = NODE_ROOT; 138 | } 139 | 140 | buffer.put(type); 141 | 142 | buffer.putInt(this.getPageID()); 143 | if(null != this.parent) 144 | buffer.putInt(this.parent.getPageID()); 145 | else 146 | buffer.putInt(0); 147 | 148 | if(null != this.prior) 149 | buffer.putInt(this.prior.getPageID()); 150 | else 151 | buffer.putInt(0); 152 | 153 | if(null != this.next) 154 | buffer.putInt(this.next.getPageID()); 155 | else 156 | buffer.putInt(0); 157 | 158 | buffer.putInt(this.numKeys); 159 | 160 | if(this.isLeaf){ 161 | 162 | for(int i = 0; i < this.numKeys ; ++i){ 163 | buffer.putInt(this.keys[i]); 164 | buffer.putInt(this.values[i].pageID); 165 | buffer.putInt(this.values[i].offset); 166 | buffer.putInt(this.values[i].time); 167 | buffer.put(this.values[i].tag); 168 | } 169 | 170 | for(int i = this.numKeys ; i < MAX_SIZE + 2; ++i){ 171 | buffer.putInt(0); 172 | buffer.putInt(0); 173 | buffer.putInt(0); 174 | buffer.putInt(0); 175 | buffer.put(IdxBlock.INVALID); 176 | } 177 | 178 | }else{ 179 | 180 | for(int i = 0; i < this.numKeys + 1; ++i){ 181 | if(i < this.numKeys + 1) 182 | buffer.putInt(this.keys[i]); 183 | else 184 | buffer.putInt(0); 185 | buffer.putInt(this.children[i].getPageID()); 186 | buffer.putInt(0); 187 | buffer.putInt(0); 188 | buffer.put(IdxBlock.VALID); 189 | } 190 | 191 | for(int i = this.numKeys + 1; i < MAX_SIZE + 2; ++i){ 192 | buffer.putInt(0); 193 | buffer.putInt(0); 194 | buffer.putInt(0); 195 | buffer.put(IdxBlock.INVALID); 196 | } 197 | 198 | } 199 | } 200 | 201 | ////type + pageid + parentid + priorid + nextid + size + (key + offset) * BALANCE_SIZE 202 | public void toByteBuffer(List list, BTreeNode rootNode){ 203 | 204 | // ByteBuffer buffer = ByteBuffer.allocate(IndexPage.PAGE_SIZE); 205 | ByteBuffer buffer = buffMgr.pinBuffer(); 206 | buffer.rewind(); 207 | 208 | this.lockRead(); 209 | 210 | this.toByteBuffer(buffer, rootNode); 211 | 212 | list.add(buffer); 213 | 214 | if(false == this.isLeaf){ 215 | 216 | if(null != this.children[0]){ 217 | this.children[0].toByteBuffer(list, rootNode); 218 | } 219 | 220 | for(int i = 0; i < this.numKeys ; ++i){ 221 | this.children[i+1].toByteBuffer(list, rootNode); 222 | } 223 | } 224 | 225 | this.unLockRead(); 226 | } 227 | 228 | 229 | public void toString(List list){ 230 | 231 | // this.lockRead(); 232 | 233 | if(!this.isLeaf){ 234 | if(null != children[0]){ 235 | children[0].toString(list); 236 | for( int i = 0; i < numKeys; ++i ){ 237 | children[i+1].toString(list); 238 | } 239 | } 240 | }else{ 241 | String output = "[L"; 242 | for( int i = 0; i < numKeys; ++i ){ 243 | long key = keys[i]; 244 | if(key < 0){ 245 | key += ByteUtil.INT_MAX_VALUE; 246 | } 247 | output += " " + key + ":" + values[i].pageID + ":" + values[i].offset + ", "; 248 | } 249 | 250 | if(null != next){ 251 | long key = next.keys[0]; 252 | if(key < 0){ 253 | key += ByteUtil.INT_MAX_VALUE; 254 | } 255 | output += "next = "+ key +": "; 256 | } 257 | output += "]"; 258 | list.add(output); 259 | } 260 | 261 | // this.unLockRead(); 262 | } 263 | 264 | 265 | public String toString(){ 266 | String output = "[L"; 267 | 268 | // this.lockRead(); 269 | 270 | if(!this.isLeaf){ 271 | if(null != children[0]){ 272 | output += "["+children[0].toString()+"], "; 273 | for( int i = 0; i < numKeys; ++i ){ 274 | output += keys[i] + ":" + children[i+1].toString(); 275 | if( i < numKeys - 1 ) output += ", "; 276 | } 277 | } 278 | }else{ 279 | 280 | for( int i = 0; i < numKeys; ++i ){ 281 | output += " " + keys[i] + ":" + values[i].pageID + ":" + values[i].offset + ", "; 282 | } 283 | 284 | if(null != next) 285 | output += "next = "+ next.keys[0] +": "; 286 | } 287 | 288 | // this.unLockRead(); 289 | 290 | return output + "]"; 291 | } 292 | 293 | public BTreeNode(String dbName, BTreeNode left, BTreeNode right, int key){ 294 | this.dbName = dbName; 295 | this.keys = new int[MAX_SIZE + 1]; 296 | this.keys[0] = key; 297 | this.numKeys = 1; 298 | 299 | this.children = new BTreeNode[MAX_SIZE + 2]; 300 | this.children[0] = left; 301 | this.children[1] = right; 302 | 303 | this.isLeaf = false; 304 | } 305 | 306 | public BTreeNode(String dbName, int key, IdxBlock obj, TransMgr transMgr, Trans tid){ 307 | this.dbName = dbName; 308 | this.keys = new int[MAX_SIZE + 1]; 309 | this.keys[0] = key; 310 | this.numKeys = 1; 311 | 312 | this.values = new IdxBlock[MAX_SIZE + 2]; 313 | this.values[0] = obj; 314 | this.values[0].time = SystemTime.getSystemTime().currentTime(); 315 | this.isLeaf = true; 316 | 317 | if(null != transMgr && null != tid && tid.getTransID() > 0){ 318 | 319 | if(transMgr.lockBlk(new BlkID(this.dbName, key), tid)){ 320 | // System.out.println("addValue.0 " + key); 321 | this.values[0].drity = true; 322 | this.values[0].tid = tid.getTransID(); 323 | this.values[0].tag = IdxBlock.INVALID; 324 | 325 | transMgr.setTransState(tid, Trans.ACTIVE); 326 | }else{ 327 | transMgr.setTransState(tid, Trans.ROLLBACK); 328 | } 329 | } 330 | } 331 | 332 | public boolean isLeaf() { 333 | return isLeaf; 334 | } 335 | 336 | public void setLeaf(boolean isLeaf) { 337 | this.isLeaf = isLeaf; 338 | } 339 | 340 | public int getMiddle(){ 341 | return this.keys[keys.length/2]; 342 | } 343 | 344 | public int lowerBound(){ 345 | return this.keys[0]; 346 | } 347 | 348 | public int upperBound(){ 349 | return this.keys[this.numKeys - 1]; 350 | } 351 | 352 | public BTreeNode splitBranch(int key, BTreeNode node){ 353 | BTreeNode newNode = null; 354 | 355 | try{ 356 | this.lockWrite(); 357 | if(!this.isLeaf){ 358 | 359 | if(this.numKeys == MAX_SIZE){ 360 | 361 | int i = 0; 362 | for(; i < MAX_SIZE;){ 363 | if(key >= this.keys[i]) 364 | ++i; 365 | else 366 | break; 367 | } 368 | 369 | if(this.keys[i] != key){ 370 | for(int t = MAX_SIZE; t > i; --t){ 371 | this.keys[t] = this.keys[t-1]; 372 | this.children[t + 1] = this.children[t]; 373 | } 374 | 375 | this.keys[i] = key; 376 | this.children[i + 1] = node; 377 | 378 | int[] newKeys = new int[MAX_SIZE + 1]; 379 | BTreeNode[] newChildren = new BTreeNode[MAX_SIZE + 2]; 380 | 381 | { 382 | { 383 | int from = (MAX_SIZE + 1)/2 + 1; 384 | int to = MAX_SIZE + 1; 385 | int newLength = to - from; 386 | 387 | for(int t = 0; t < newLength; ++t){ 388 | if( t + from < to ) { 389 | newKeys[t] = this.keys[from+t]; 390 | } 391 | else{ 392 | newKeys[t] = -1; 393 | } 394 | } 395 | } 396 | 397 | { 398 | int from = (MAX_SIZE + 2 + 1)/2; 399 | int to = MAX_SIZE + 2; 400 | int newLength = to - from; 401 | 402 | for(int t = 0; t < newLength; ++t){ 403 | if( t + from < to ) { 404 | newChildren[t] = this.children[from+t]; 405 | }else{ 406 | newChildren[t] = null; 407 | } 408 | } 409 | } 410 | 411 | int newNum = (MAX_SIZE + 1)/2; 412 | newNode = new BTreeNode(this.dbName, false, newNum, newKeys, null, newChildren, this.parent, this.next, this); 413 | for( int t = 0; t <= newNum ; ++t ) { 414 | if(null != newNode.children[t]) 415 | newNode.children[t].parent = newNode; 416 | } 417 | 418 | this.numKeys = (MAX_SIZE + 1)/2; 419 | this.next = newNode; 420 | } 421 | } 422 | } 423 | } 424 | }catch(Exception e){} 425 | finally{ 426 | this.unLockWrite(); 427 | } 428 | 429 | return newNode; 430 | } 431 | 432 | 433 | public SplitLeafVar splitLeaf(int key, IdxBlock value, TransMgr transMgr, Trans tid, CellLogMgr logMgr){ 434 | 435 | SplitLeafVar slVar = new SplitLeafVar(); 436 | 437 | try{ 438 | this.lockWrite(); 439 | if(this.isLeaf){ 440 | 441 | if(key > this.upperBound()){ 442 | int from = MAX_SIZE - 1; 443 | int to = MAX_SIZE; 444 | int newLength = to - from; 445 | 446 | int[] newKeys = new int[MAX_SIZE + 1]; 447 | IdxBlock[] newValues = new IdxBlock[MAX_SIZE + 2]; 448 | 449 | for(int i = 0; i < newLength; ++i){ 450 | if( i + from < to ) { 451 | newKeys[i] = this.keys[from+i]; 452 | newValues[i] = this.values[from+i]; 453 | } 454 | } 455 | 456 | slVar.newRight = new BTreeNode(this.dbName, true, 1, newKeys, newValues, null, this.parent, this.next, this); 457 | this.next = slVar.newRight; 458 | this.numKeys = MAX_SIZE - 1;; 459 | 460 | if(key >= slVar.newRight.lowerBound()){ 461 | slVar.oldVar = slVar.newRight.addValue(key, value, transMgr, tid, logMgr); 462 | }else{ 463 | slVar.oldVar = this.addValue(key, value, transMgr, tid, logMgr); 464 | } 465 | }else{ 466 | int from = MAX_SIZE/2; 467 | int to = MAX_SIZE; 468 | int newLength = to - from; 469 | 470 | int[] newKeys = new int[MAX_SIZE + 1]; 471 | IdxBlock[] newValues = new IdxBlock[MAX_SIZE + 2]; 472 | 473 | for(int i = 0; i < newLength; ++i){ 474 | if( i + from < to ) { 475 | newKeys[i] = this.keys[from+i]; 476 | newValues[i] = this.values[from+i]; 477 | } 478 | } 479 | 480 | slVar.newRight = new BTreeNode(this.dbName, true, MAX_SIZE/2, newKeys, newValues, null, this.parent, this.next, this); 481 | this.next = slVar.newRight; 482 | this.numKeys = MAX_SIZE/2; 483 | 484 | if(key >= slVar.newRight.lowerBound()){ 485 | slVar.oldVar = slVar.newRight.addValue(key, value, transMgr, tid, logMgr); 486 | }else{ 487 | slVar.oldVar = this.addValue(key, value, transMgr, tid, logMgr); 488 | } 489 | } 490 | } 491 | }catch(Exception e){} 492 | finally{ 493 | this.unLockWrite(); 494 | } 495 | 496 | return slVar; 497 | } 498 | 499 | public boolean addChild(int key, BTreeNode node){ 500 | boolean b = false; 501 | 502 | try{ 503 | 504 | this.lockWrite(); 505 | if(!this.isLeaf && this.numKeys < MAX_SIZE){ 506 | int i = 0; 507 | for(; i < this.numKeys; ){ 508 | if(this.keys[i] < key) 509 | ++i; 510 | else 511 | break; 512 | } 513 | 514 | if(i < MAX_SIZE){ 515 | 516 | for(int t = this.numKeys; t > i; --t){ 517 | this.keys[t] = this.keys[t - 1]; 518 | this.children[t+1] = this.children[t]; 519 | } 520 | 521 | this.keys[i] = key; 522 | this.children[i+1] = node; 523 | this.numKeys++; 524 | 525 | b = true; 526 | } 527 | } 528 | }catch(Exception e){} 529 | finally{ 530 | this.unLockWrite(); 531 | } 532 | 533 | return b; 534 | } 535 | 536 | public InsertVar addValue(int key, IdxBlock newValue, TransMgr transMgr, Trans tid, CellLogMgr logMgr){ 537 | 538 | InsertVar var = new InsertVar(); 539 | var.inserted = true; 540 | var.oldValue = null; 541 | 542 | try{ 543 | this.lockWrite(); 544 | 545 | if(this.isLeaf){ 546 | int i = 0; 547 | for(; i < this.numKeys; ){ 548 | if(this.keys[i] < key) 549 | ++i; 550 | else 551 | break; 552 | } 553 | 554 | if(i != this.numKeys && this.keys[i] == key){ 555 | 556 | if(null != transMgr && null != tid && tid.getTransID() > 0){ 557 | BlkID bid = new BlkID(this.dbName, key); 558 | 559 | var.inserted = false; 560 | logMgr.logUpdate(tid, key, newValue, this.values[i]); 561 | if(transMgr.lockBlk(bid, tid)){ 562 | 563 | var.oldValue = this.values[i]; 564 | this.values[i] = newValue; 565 | var.inserted = true; 566 | 567 | this.values[i].drity = true; 568 | this.values[i].tid = tid.getTransID(); 569 | this.values[i].tag = IdxBlock.VALID; 570 | this.values[i].newTag = IdxBlock.VALID; 571 | this.values[i].old = var.oldValue; 572 | this.values[i].time = SystemTime.getSystemTime().currentTime(); 573 | transMgr.setTransState(tid, Trans.ACTIVE); 574 | }else{ 575 | transMgr.setTransState(tid, Trans.ROLLBACK); 576 | var.conflict = true; 577 | } 578 | }else{ 579 | if(false == this.values[i].drity){ 580 | 581 | var.oldValue = this.values[i]; 582 | this.values[i] = newValue; 583 | this.values[i].time = SystemTime.getSystemTime().currentTime(); 584 | var.inserted = true; 585 | 586 | this.values[i].tag = IdxBlock.VALID; 587 | }else{ 588 | var.inserted = false; 589 | } 590 | } 591 | }else if(this.numKeys != MAX_SIZE){ 592 | 593 | for(int t = this.numKeys; t > i; --t){ 594 | this.keys[t] = this.keys[t - 1]; 595 | this.values[t] = this.values[t - 1]; 596 | } 597 | 598 | if(null != transMgr && null != tid && tid.getTransID() > 0){ 599 | 600 | var.inserted = false; 601 | 602 | logMgr.logInsert(tid, key, newValue); 603 | 604 | if(transMgr.lockBlk(new BlkID(this.dbName, key), tid)){ 605 | 606 | this.keys[i] = key; 607 | this.values[i] = newValue; 608 | 609 | // System.out.println("addValue.0 " + key); 610 | this.values[i].drity = true; 611 | this.values[i].tid = tid.getTransID(); 612 | this.values[i].old = null; 613 | this.values[i].tag = IdxBlock.INVALID; 614 | this.values[i].newTag = IdxBlock.VALID; 615 | this.values[i].time = SystemTime.getSystemTime().currentTime(); 616 | this.numKeys++; 617 | var.inserted = true; 618 | 619 | }else{ 620 | 621 | var.conflict = true; 622 | } 623 | }else{ 624 | // System.out.println("addValue.0 " + key); 625 | this.keys[i] = key; 626 | this.values[i] = newValue; 627 | this.values[i].time = SystemTime.getSystemTime().currentTime(); 628 | 629 | this.numKeys++; 630 | var.inserted = true; 631 | } 632 | }else{ 633 | var.inserted = false; 634 | } 635 | } 636 | }catch(Exception e){} 637 | finally{ 638 | this.unLockWrite(); 639 | } 640 | 641 | return var; 642 | } 643 | 644 | public BTreeNode getChild(int key){ 645 | BTreeNode child = null; 646 | 647 | try{ 648 | this.lockRead(); 649 | 650 | if(!this.isLeaf){ 651 | int i = 0; 652 | for(; i < this.numKeys; ){ 653 | if(this.keys[i] <= key) 654 | ++i; 655 | else 656 | break; 657 | } 658 | child = children[i]; 659 | } 660 | } 661 | catch(Exception e){ 662 | System.out.println(e); 663 | } 664 | finally{ 665 | this.unLockRead(); 666 | } 667 | 668 | return child; 669 | } 670 | 671 | public IdxBlock delValue(int key, TransMgr transMgr, Trans tid, CellLogMgr logMgr) throws AbortTransException{ 672 | IdxBlock oldObj = null; 673 | 674 | try{ 675 | this.lockWrite(); 676 | 677 | if(this.isLeaf){ 678 | int i = 0; 679 | for(; i < this.numKeys; ){ 680 | if(this.keys[i] < key) 681 | ++i; 682 | else 683 | break; 684 | } 685 | 686 | if(this.keys[i] == key && IdxBlock.VALID == this.values[i].tag){ 687 | 688 | if(null != transMgr && null != tid && tid.getTransID() > 0){ 689 | logMgr.logDelete(tid, key); 690 | 691 | if((false == this.values[i].drity) 692 | ||(this.values[i].drity && this.values[i].tid == tid.getTransID())){ 693 | 694 | if(transMgr.lockBlk(new BlkID(this.dbName, key), tid)){ 695 | oldObj = this.values[i]; 696 | 697 | this.values[i].drity = true; 698 | this.values[i].tid = tid.getTransID(); 699 | this.values[i].tag = IdxBlock.VALID; 700 | this.values[i].newTag = IdxBlock.INVALID; 701 | this.values[i].time = SystemTime.getSystemTime().currentTime(); 702 | this.values[i].old = oldObj; 703 | transMgr.setTransState(tid, Trans.ACTIVE); 704 | }else{ 705 | transMgr.setTransState(tid, Trans.ROLLBACK); 706 | } 707 | }else{ 708 | transMgr.setTransState(tid, Trans.ROLLBACK); 709 | tid.setState(Trans.ROLLBACK); 710 | ////////// conflict 711 | throw new AbortTransException("delValue: key = " + key); 712 | } 713 | }else{ 714 | if(false == this.values[i].drity){ 715 | this.values[i].tag = IdxBlock.INVALID; 716 | } 717 | } 718 | } 719 | } 720 | } 721 | catch(AbortTransException ate){ 722 | throw ate; 723 | } 724 | catch(Exception e){ 725 | System.out.println(e); 726 | } 727 | finally{ 728 | this.unLockWrite(); 729 | } 730 | 731 | return oldObj; 732 | } 733 | 734 | public IdxBlock setValue(int key, IdxBlock newObj, TransMgr transMgr, Trans tid, CellLogMgr logMgr) throws AbortTransException{ 735 | IdxBlock oldObj = null; 736 | 737 | try{ 738 | this.lockWrite(); 739 | 740 | if(this.isLeaf){ 741 | int i = 0; 742 | for(; i < this.numKeys; ){ 743 | if(this.keys[i] < key) 744 | ++i; 745 | else 746 | break; 747 | } 748 | 749 | if(this.keys[i] == key){ 750 | 751 | if(null != transMgr && null != tid && tid.getTransID() > 0){ 752 | 753 | logMgr.logUpdate(tid, key, newObj, this.values[i]); 754 | 755 | if((false == this.values[i].drity)|| 756 | (this.values[i].tid == tid.getTransID())){ 757 | 758 | if(transMgr.lockBlk(new BlkID(this.dbName, key), tid)){ 759 | oldObj = this.values[i]; 760 | this.values[i] = newObj; 761 | 762 | this.values[i].drity = true; 763 | this.values[i].tid = tid.getTransID(); 764 | this.values[i].tag = IdxBlock.VALID; 765 | this.values[i].newTag = IdxBlock.VALID; 766 | this.values[i].old = oldObj; 767 | this.values[i].time = SystemTime.getSystemTime().currentTime(); 768 | 769 | transMgr.setTransState(tid, Trans.ACTIVE); 770 | }else{ 771 | transMgr.setTransState(tid, Trans.ROLLBACK); 772 | } 773 | }else{ 774 | transMgr.setTransState(tid, Trans.ROLLBACK); 775 | tid.setState(Trans.ROLLBACK); 776 | ////////// conflict 777 | throw new AbortTransException("setValue: key = " + key); 778 | } 779 | }else{ 780 | if(false == this.values[i].drity){ 781 | oldObj = this.values[i]; 782 | this.values[i] = newObj; 783 | } 784 | } 785 | } 786 | } 787 | }catch(AbortTransException ate){ 788 | throw ate; 789 | }catch(Exception e){ 790 | System.out.println(e); 791 | }finally{ 792 | this.unLockWrite(); 793 | } 794 | 795 | return oldObj; 796 | } 797 | 798 | public IdxBlock rollback(int key, TransMgr transMgr, Trans tid){ 799 | IdxBlock value = null; 800 | 801 | try{ 802 | this.lockWrite(); 803 | 804 | if(this.isLeaf){ 805 | int i = 0; 806 | for(; i < this.numKeys; ){ 807 | if(this.keys[i] < key) 808 | ++i; 809 | else 810 | break; 811 | } 812 | 813 | if(this.keys[i] == key){ 814 | if(null != transMgr && null != tid && tid.getTransID() > 0){ 815 | if((true == this.values[i].drity)&& 816 | (this.values[i].tid == tid.getTransID())){ 817 | 818 | IdxBlock old = this.values[i].old; 819 | if(null != old){ 820 | this.values[i] = old; 821 | this.values[i].old = null; 822 | this.values[i].tid = 0; 823 | this.values[i].drity = false; 824 | 825 | }else{ 826 | this.values[i].tag = IdxBlock.INVALID; 827 | this.values[i].tid = 0; 828 | this.values[i].drity = false; 829 | } 830 | 831 | value = this.values[i].copyData(); 832 | value.idxOffset = i; 833 | } 834 | } 835 | } 836 | } 837 | }catch(Exception e){} 838 | finally{ 839 | this.unLockWrite(); 840 | } 841 | 842 | return value; 843 | } 844 | 845 | public IdxBlock commit(int key, TransMgr transMgr, Trans tid){ 846 | IdxBlock value = null; 847 | 848 | try{ 849 | this.lockWrite(); 850 | 851 | if(this.isLeaf){ 852 | int i = 0; 853 | for(; i < this.numKeys; ){ 854 | if(this.keys[i] < key) 855 | ++i; 856 | else 857 | break; 858 | } 859 | 860 | if(this.keys[i] == key){ 861 | if(null != transMgr && null != tid && tid.getTransID() > 0){ 862 | if((false == this.values[i].drity)|| 863 | (this.values[i].tid == tid.getTransID())){ 864 | 865 | this.values[i].old = null; 866 | this.values[i].drity = false; 867 | this.values[i].tag = this.values[i].newTag; 868 | this.values[i].tid = 0; 869 | this.values[i].time = SystemTime.getSystemTime().currentTime(); 870 | value = this.values[i].copyData(); 871 | value.idxOffset = i; 872 | } 873 | } 874 | } 875 | } 876 | }catch(Exception e){} 877 | finally{ 878 | this.unLockWrite(); 879 | } 880 | 881 | return value; 882 | } 883 | 884 | public IdxBlock getValue(int key, TransMgr transMgr, Trans tid){ 885 | IdxBlock value = null; 886 | 887 | try{ 888 | 889 | this.lockRead(); 890 | if(this.isLeaf){ 891 | int i = 0; 892 | for(; i < this.numKeys; ){ 893 | if(this.keys[i] < key) 894 | ++i; 895 | else 896 | break; 897 | } 898 | 899 | // System.out.println("getValue.1 i = " + i + ", " + this.keys[i]); 900 | if(this.keys[i] == key && IdxBlock.VALID == this.values[i].tag) 901 | { 902 | // System.out.println("getValue.2 i = " + i + ", " + this.keys[i]); 903 | if(null != transMgr && null != tid && tid.getTransID() > 0){ 904 | if((false == this.values[i].drity) 905 | ||(this.values[i].tid == tid.getTransID())){ 906 | 907 | this.values[i].tid = tid.getTransID(); 908 | value = this.values[i].copyData(); 909 | }else{ 910 | if(null != this.values[i].old){ 911 | value = this.values[i].old.copyData(); 912 | } 913 | } 914 | }else{ 915 | if(false == this.values[i].drity){ 916 | // System.out.println("getValue.3 i = " + i + ", " + this.keys[i]); 917 | value = this.values[i].copyData(); 918 | // System.out.println("getValue.4 " + value.idxPageID + ", " + value.idxOffset + ", " + value.pageID + ", " + value.offset); 919 | }else{ 920 | if(null != this.values[i].old){ 921 | value = this.values[i].old.copyData(); 922 | } 923 | } 924 | } 925 | } 926 | } 927 | }catch(Exception e){ 928 | System.out.println(e); 929 | } 930 | finally{ 931 | this.unLockRead(); 932 | } 933 | return value; 934 | } 935 | } 936 | -------------------------------------------------------------------------------- /src/tenndb/bstar/IdxBlock.java: -------------------------------------------------------------------------------- 1 | package tenndb.bstar; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | public class IdxBlock { 6 | 7 | protected int tabId; 8 | protected int idxPos; 9 | protected int idxPageID; 10 | protected int idxOffset; 11 | 12 | 13 | 14 | protected int key; 15 | 16 | protected int pageID; 17 | 18 | protected int offset; 19 | 20 | protected int time; 21 | 22 | protected byte tag; 23 | 24 | protected boolean drity; 25 | // 26 | protected byte newTag; 27 | 28 | protected int tid; 29 | 30 | protected IdxBlock old; 31 | 32 | public static final byte INVALID = (byte)0; 33 | public static final byte VALID = (byte)1; 34 | 35 | public int getTabId() { 36 | return tabId; 37 | } 38 | 39 | public void setTabId(int tabId) { 40 | this.tabId = tabId; 41 | } 42 | 43 | public int getIdxPos() { 44 | return idxPos; 45 | } 46 | 47 | public void setIdxPos(int idxPos) { 48 | this.idxPos = idxPos; 49 | } 50 | 51 | public int getIdxPageID() { 52 | return idxPageID; 53 | } 54 | 55 | public void setIdxPageID(int idxPageID) { 56 | this.idxPageID = idxPageID; 57 | } 58 | 59 | public int getIdxOffset() { 60 | return idxOffset; 61 | } 62 | 63 | public void setIdxOffset(int idxOffset) { 64 | this.idxOffset = idxOffset; 65 | } 66 | 67 | public static void toByteBuffer(IdxBlock blk, ByteBuffer buff){ 68 | if(null != blk){ 69 | 70 | buff.putInt(blk.key); 71 | buff.putInt(blk.pageID); 72 | buff.putInt(blk.offset); 73 | buff.putInt(blk.time); 74 | buff.put(blk.tag); 75 | } 76 | } 77 | 78 | public IdxBlock(int key) { 79 | super(); 80 | this.idxPos = 0; 81 | this.idxPageID = 0; 82 | this.idxOffset = 0; 83 | 84 | this.key = key; 85 | this.pageID = 0; 86 | this.offset = 0; 87 | this.time = 0; 88 | this.drity = false; 89 | this.tid = 0; 90 | this.tag = VALID; 91 | this.newTag = VALID; 92 | this.old = null; 93 | } 94 | 95 | public IdxBlock copyData(){ 96 | IdxBlock blk = new IdxBlock(this.key); 97 | blk.pageID = this.pageID; 98 | blk.offset = this.offset; 99 | blk.time = this.time; 100 | return blk; 101 | } 102 | 103 | public int getTime(){ 104 | return this.time; 105 | } 106 | 107 | public int getKey() { 108 | return key; 109 | } 110 | 111 | public void setKey(int key) { 112 | this.key = key; 113 | } 114 | 115 | public byte getTag() { 116 | return tag; 117 | } 118 | 119 | public void setTag(byte tag) { 120 | this.tag = tag; 121 | } 122 | 123 | public int getPageID() { 124 | return pageID; 125 | } 126 | 127 | public void setPageID(int pageID) { 128 | this.pageID = pageID; 129 | } 130 | 131 | public int getOffset() { 132 | return offset; 133 | } 134 | 135 | public void setOffset(int offset) { 136 | this.offset = offset; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/tenndb/bstar/IdxOld.java: -------------------------------------------------------------------------------- 1 | package tenndb.bstar; 2 | 3 | public class IdxOld{ 4 | public int pageID; 5 | public int offset; 6 | public int time; 7 | }; -------------------------------------------------------------------------------- /src/tenndb/bstar/InsertVar.java: -------------------------------------------------------------------------------- 1 | package tenndb.bstar; 2 | 3 | public class InsertVar { 4 | 5 | protected boolean inserted = true; 6 | protected boolean conflict = false; 7 | 8 | protected IdxBlock oldValue = null; 9 | } 10 | -------------------------------------------------------------------------------- /src/tenndb/bstar/RandomInsertBStarTree.java: -------------------------------------------------------------------------------- 1 | package tenndb.bstar; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.concurrent.locks.ReadWriteLock; 9 | import java.util.concurrent.locks.ReentrantReadWriteLock; 10 | 11 | import tenndb.index.IBTree; 12 | import tenndb.index.IndexMgr; 13 | import tenndb.index.IndexPage; 14 | import tenndb.log.CellLogMgr; 15 | import tenndb.tx.AbortTransException; 16 | import tenndb.tx.Trans; 17 | import tenndb.tx.TransMgr; 18 | 19 | 20 | public class RandomInsertBStarTree implements IBTree { 21 | 22 | public final static int BALANCE_SIZE = 256; 23 | 24 | protected String dbName; 25 | protected final int size; 26 | protected BTreeNode root; 27 | protected IndexMgr indexMgr; 28 | protected TransMgr transMgr; 29 | 30 | protected ReadWriteLock lock = new ReentrantReadWriteLock(false); 31 | 32 | public void lockRead() { this.lock.readLock().lock(); } 33 | 34 | public void unLockRead() { this.lock.readLock().unlock(); } 35 | 36 | public void lockWrite() { this.lock.writeLock().lock(); } 37 | 38 | public void unLockWrite() { this.lock.writeLock().unlock(); } 39 | 40 | 41 | public RandomInsertBStarTree(String dbName, IndexMgr indexMgr, TransMgr transMgr) { 42 | super(); 43 | this.dbName = dbName; 44 | this.size = BALANCE_SIZE; 45 | this.indexMgr = indexMgr; 46 | this.transMgr = transMgr; 47 | } 48 | 49 | public RandomInsertBStarTree(String dbName, IndexMgr indexMgr, TransMgr transMgr, BTreeNode root) { 50 | super(); 51 | this.dbName = dbName; 52 | this.size = BALANCE_SIZE; 53 | this.indexMgr = indexMgr; 54 | this.transMgr = transMgr; 55 | this.root = root; 56 | } 57 | 58 | public BTreeNode getRoot() { return this.root; } 59 | 60 | public static IBTree buildBTree(String dbName, IndexMgr indexMgr, TransMgr tansMgr, List buffList, List pageList){ 61 | IBTree tree = null; 62 | ////type + pageid + parentid + priorid + nextid + size + (key + offset) * BALANCE_SIZE 63 | if(null != buffList && buffList.size() > 0){ 64 | Map map = new HashMap(); 65 | List nodeList = new ArrayList(); 66 | BTreeNode rootNode = null; 67 | for(int i = 0; i < buffList.size(); ++i){ 68 | ByteBuffer buffer = buffList.get(i); 69 | // System.out.println("buildBTree.1 " + i + " " + buffer.limit()); 70 | if(buffer.limit() == IndexPage.PAGE_SIZE){ 71 | 72 | buffer.position(0); 73 | byte type = buffer.get(0); 74 | int pageID = buffer.getInt(1); 75 | int parentID = buffer.getInt(5); 76 | int priorID = buffer.getInt(9); 77 | int nextID = buffer.getInt(13); 78 | int size = buffer.getInt(17); 79 | 80 | int[] keys = new int[size]; 81 | IdxBlock[] values = new IdxBlock[size + 2]; 82 | BTreeNode[] children = null; 83 | 84 | boolean isLeaf = false; 85 | if(BTreeNode.NODE_LEAF == type || (BTreeNode.NODE_ROOT == type && 1 == buffList.size())){ 86 | values = new IdxBlock[size]; 87 | for(int t = 0; t < size; ++t){ 88 | int key = buffer.getInt(IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * t); 89 | int pid = buffer.getInt(IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * t + 4); 90 | int offset = buffer.getInt(IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * t + 8); 91 | int time = buffer.getInt(IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * t + 12); 92 | byte tag = buffer.get (IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * t + 16); 93 | 94 | keys[t] = key; 95 | values[t] = new IdxBlock(key); 96 | values[t].key = key; 97 | values[t].pageID = pid; 98 | values[t].offset = offset; 99 | values[t].time = time; 100 | values[t].tag = tag; 101 | } 102 | isLeaf = true; 103 | }else if(BTreeNode.NODE_BRANCH== type || (BTreeNode.NODE_ROOT == type && 1 < buffList.size())){ 104 | for(int t = 0; t < size + 2; ++t){ 105 | int key = buffer.getInt(IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * t); 106 | int pid = buffer.getInt(IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * t + 4); 107 | byte tag = buffer.get (IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * t + 16); 108 | 109 | if(t < size) 110 | keys[t] = key; 111 | values[t] = new IdxBlock(key); 112 | values[t].key = key; 113 | values[t].pageID = pid; 114 | values[t].offset = 0; 115 | values[t].time = 0; 116 | values[t].tag = tag; 117 | } 118 | isLeaf = false;; 119 | } 120 | 121 | //(boolean isLeaf, int num, int[] keys, Object[] values, BTreeNode[] children, BTreeNode parent, BTreeNode next, BTreeNode prior) 122 | BTreeNode node = new BTreeNode(dbName, isLeaf, size, keys, values, children, null, null, null); 123 | node.pageID = pageID; 124 | node.parentID = parentID; 125 | node.priorID = priorID; 126 | node.nextID = nextID; 127 | 128 | IndexPage page = indexMgr.addIndexPage(node, buffer); 129 | long pos = IndexPage.PAGE_SIZE * i + IndexPage.INDEX_HEAD_SIZE; 130 | page.setPos(pos); 131 | node.setRefPage(page); 132 | pageList.add(page); 133 | 134 | if(!isLeaf) 135 | node.values = values; 136 | 137 | nodeList.add(node); 138 | map.put(pageID, node); 139 | 140 | if(BTreeNode.NODE_ROOT == type){ 141 | 142 | rootNode = node; 143 | } 144 | } 145 | } 146 | 147 | for(int i = 0; i < nodeList.size(); ++i){ 148 | BTreeNode node = nodeList.get(i); 149 | 150 | node.parent = map.get(node.parentID); 151 | node.prior = map.get(node.priorID); 152 | node.next = map.get(node.nextID); 153 | 154 | if(!node.isLeaf){ 155 | 156 | for(int t = 0; t < node.numKeys + 2; ++t){ 157 | node.children[t] = map.get(node.values[t].pageID); 158 | } 159 | node.values = null; 160 | } 161 | } 162 | 163 | tree = new RandomInsertBStarTree(dbName, indexMgr, tansMgr, rootNode); 164 | } 165 | 166 | return tree; 167 | } 168 | 169 | public void print(List strList){ 170 | 171 | try{ 172 | this.lockRead(); 173 | if( root != null ){ 174 | root.toString(strList); 175 | } 176 | }catch(Exception e){} 177 | finally{ 178 | this.unLockRead(); 179 | } 180 | } 181 | 182 | public String toString(){ 183 | String str = null; 184 | 185 | try{ 186 | this.lockRead(); 187 | if( root != null ){ 188 | str = root.toString(); 189 | } 190 | 191 | }catch(Exception e){} 192 | finally{ 193 | this.unLockRead(); 194 | } 195 | 196 | return str; 197 | } 198 | 199 | @Override 200 | public void printTreePrior(){ 201 | 202 | try{ 203 | this.lockRead(); 204 | 205 | if(null != root){ 206 | BTreeNode currentNode = root; 207 | while(null != currentNode && !currentNode.isLeaf){ 208 | currentNode = currentNode.children[currentNode.numKeys]; 209 | } 210 | 211 | if(null != currentNode){ 212 | int index = 0; 213 | String str = ""; 214 | while(null != currentNode){ 215 | 216 | str = ""; 217 | index++; 218 | for(int i = currentNode.numKeys - 1; i >= 0 ; --i){ 219 | if(null != currentNode.values[i]){ 220 | str += currentNode.keys[i] + "_" + currentNode.values[i].pageID + ":" + currentNode.values[i].offset + ","; 221 | }else{ 222 | str += currentNode.keys[i] + "_null,"; 223 | } 224 | } 225 | System.out.println(index + ":" + str); 226 | 227 | currentNode = currentNode.prior; 228 | } 229 | } 230 | } 231 | }catch(Exception e){} 232 | finally{ 233 | this.unLockRead(); 234 | } 235 | } 236 | 237 | @Override 238 | public void printNext() { 239 | 240 | try{ 241 | this.lockRead(); 242 | 243 | if(null != root){ 244 | BTreeNode currentNode = root; 245 | while(null != currentNode && !currentNode.isLeaf){ 246 | currentNode = currentNode.children[0]; 247 | } 248 | 249 | if(null != currentNode){ 250 | int index = 0; 251 | String str = ""; 252 | 253 | while(null != currentNode){ 254 | str = "PageID = " + currentNode.getPageID() + ", "; 255 | index++; 256 | for(int i = 0; i < currentNode.numKeys; ++i){ 257 | if(null != currentNode.values[i]){ 258 | str += currentNode.keys[i] + "_" + currentNode.values[i].pageID + ":" + currentNode.values[i].offset + ","; 259 | }else{ 260 | str += currentNode.keys[i] + "_null,"; 261 | } 262 | } 263 | System.out.println(index + ":" + str); 264 | 265 | currentNode = currentNode.next; 266 | } 267 | } 268 | } 269 | }catch(Exception e){} 270 | finally{ 271 | this.unLockRead(); 272 | } 273 | } 274 | 275 | protected boolean addChild(BTreeNode parentNode, int key, BTreeNode newNode){ 276 | boolean b = false; 277 | 278 | b = parentNode.addChild(key, newNode); 279 | 280 | if(true == b){ 281 | this.indexMgr.appendNewIndexPage(null, parentNode); 282 | } 283 | 284 | return b; 285 | } 286 | 287 | @Override 288 | public IdxBlock insert(int key, IdxBlock value, Trans tid, CellLogMgr logMgr) throws AbortTransException { 289 | IdxBlock oldVal = null; 290 | try{ 291 | this.lockRead(); 292 | 293 | if(null!= root){ 294 | BTreeNode currentNode = root; 295 | while(null != currentNode && !currentNode.isLeaf){ 296 | currentNode = currentNode.getChild(key); 297 | } 298 | 299 | if(null != currentNode){ 300 | BTreeNode leaf = currentNode; 301 | 302 | InsertVar insert = leaf.addValue(key, value, this.transMgr, tid, logMgr); 303 | 304 | if(false == insert.conflict){ 305 | if(!insert.inserted){ 306 | 307 | this.unLockRead(); // read lock up to write lock 308 | this.lockWrite(); 309 | 310 | SplitLeafVar slVar = leaf.splitLeaf(key, value, this.transMgr, tid, logMgr); 311 | 312 | BTreeNode newRight = slVar.newRight; 313 | 314 | this.indexMgr.appendNewIndexPage(newRight, null); 315 | 316 | oldVal = slVar.oldVar.oldValue; 317 | 318 | BTreeNode parent = newRight.parent; 319 | int addToParent = newRight.lowerBound(); 320 | 321 | while(null != parent && ! this.addChild(parent,addToParent, newRight)){ 322 | 323 | BTreeNode parentRight = parent.splitBranch(addToParent, newRight); 324 | 325 | this.indexMgr.appendNewIndexPage(parentRight, parent); 326 | 327 | addToParent = parent.getMiddle(); 328 | parent = parent.parent; 329 | newRight = parentRight; 330 | } 331 | 332 | if(null == parent){ 333 | 334 | BTreeNode newRoot = new BTreeNode(this.dbName, root, newRight, addToParent); 335 | this.indexMgr.appendNewIndexPage(newRoot, root); 336 | 337 | root.parent = newRoot; 338 | newRight.parent = newRoot; 339 | root = newRoot; 340 | } 341 | 342 | this.lockRead(); // write lock down to read lock 343 | this.unLockWrite(); 344 | 345 | }else{ 346 | oldVal = insert.oldValue; 347 | this.indexMgr.appendNewIndexPage(null, leaf); 348 | } 349 | }else{ 350 | transMgr.setTransState(tid, Trans.ROLLBACK); 351 | tid.setState(Trans.ROLLBACK); 352 | throw new AbortTransException("insert: key = " + key); 353 | } 354 | } 355 | }else{ 356 | this.unLockRead(); 357 | this.lockWrite(); 358 | 359 | this.root = new BTreeNode(this.dbName, key, value, this.transMgr, tid); 360 | this.indexMgr.appendNewIndexPage(root, null); 361 | 362 | this.lockRead(); 363 | this.unLockWrite(); 364 | } 365 | 366 | }catch(AbortTransException ae){ 367 | System.out.println(ae); 368 | throw ae; 369 | } 370 | catch(Exception e){ 371 | System.out.println(e); 372 | } 373 | finally{ 374 | this.unLockRead(); 375 | } 376 | 377 | return oldVal; 378 | } 379 | 380 | @Override 381 | public IdxBlock update(int key, IdxBlock rowData, Trans tid, CellLogMgr logMgr) throws AbortTransException { 382 | IdxBlock oldObj = null; 383 | 384 | try{ 385 | this.lockRead(); 386 | 387 | BTreeNode currentNode = this.root; 388 | while(null != currentNode && !currentNode.isLeaf){ 389 | currentNode = currentNode.getChild(key); 390 | } 391 | 392 | if(null != currentNode){ 393 | oldObj = currentNode.setValue(key, rowData, this.transMgr, tid, logMgr); 394 | } 395 | 396 | // this.indexMgr.flushNewPages(); 397 | }catch(AbortTransException ae){ 398 | System.out.println(ae); 399 | throw ae; 400 | }catch(Exception e){} 401 | finally{ 402 | this.unLockRead(); 403 | } 404 | 405 | return oldObj; 406 | } 407 | 408 | @Override 409 | public IdxBlock delete(int key, Trans tid, CellLogMgr logMgr) { 410 | IdxBlock oldObj = null; 411 | 412 | try{ 413 | this.lockWrite(); 414 | 415 | BTreeNode currentNode = root; 416 | while(null != currentNode && !currentNode.isLeaf){ 417 | currentNode = currentNode.getChild(key); 418 | } 419 | 420 | if(null != currentNode){ 421 | oldObj = currentNode.delValue(key, this.transMgr, tid, logMgr); 422 | if(null != oldObj){ 423 | this.indexMgr.appendNewIndexPage(null, currentNode); 424 | } 425 | } 426 | 427 | // this.indexMgr.flushNewPages(); 428 | }catch(Exception e){} 429 | finally{ 430 | this.unLockWrite(); 431 | } 432 | 433 | return oldObj; 434 | } 435 | 436 | @Override 437 | public BTreeNode seekNode(int key) { 438 | BTreeNode currentNode = null; 439 | 440 | try{ 441 | this.lockRead(); 442 | 443 | currentNode = this.root; 444 | 445 | while(null != currentNode && !currentNode.isLeaf){ 446 | currentNode = currentNode.getChild(key); 447 | } 448 | }catch(Exception e){} 449 | finally{ 450 | this.unLockRead(); 451 | } 452 | return currentNode; 453 | } 454 | 455 | public boolean rollback(int key, Trans tid, CellLogMgr logMgr){ 456 | boolean b = false; 457 | 458 | try{ 459 | this.lockRead(); 460 | 461 | BTreeNode currentNode = this.root; 462 | while(null != currentNode && !currentNode.isLeaf){ 463 | currentNode = currentNode.getChild(key); 464 | } 465 | 466 | if(null != currentNode && currentNode.isLeaf){ 467 | IdxBlock blk = currentNode.rollback(key, this.transMgr, tid); 468 | if(null != blk){ 469 | // blk.idxPageID = currentNode.pageID; 470 | // b = this.indexMgr.flushBlock(blk); 471 | b = true; 472 | } 473 | } 474 | }catch(Exception e){} 475 | finally{ 476 | this.unLockRead(); 477 | } 478 | return b; 479 | } 480 | 481 | public boolean commit(int key, Trans tid, CellLogMgr logMgr){ 482 | boolean b = false; 483 | 484 | try{ 485 | this.lockRead(); 486 | 487 | BTreeNode currentNode = root; 488 | while(null != currentNode && !currentNode.isLeaf){ 489 | currentNode = currentNode.getChild(key); 490 | } 491 | 492 | if(null != currentNode && currentNode.isLeaf){ 493 | IdxBlock blk = currentNode.commit(key, this.transMgr, tid); 494 | if(null != blk){ 495 | blk.idxPageID = currentNode.pageID; 496 | b = this.indexMgr.flushBlock(blk); 497 | } 498 | } 499 | }catch(Exception e){} 500 | finally{ 501 | this.unLockRead(); 502 | } 503 | 504 | return b; 505 | } 506 | 507 | @Override 508 | public IdxBlock search(int key, Trans tid) { 509 | IdxBlock value = null; 510 | 511 | try{ 512 | this.lockRead(); 513 | 514 | BTreeNode currentNode = this.root; 515 | while(null != currentNode && !currentNode.isLeaf){ 516 | currentNode = currentNode.getChild(key); 517 | } 518 | 519 | if(null != currentNode && currentNode.isLeaf){ 520 | value = currentNode.getValue(key, this.transMgr, tid); 521 | } 522 | }catch(Exception e){} 523 | finally{ 524 | this.unLockRead(); 525 | } 526 | 527 | return value; 528 | } 529 | 530 | @Override 531 | public List range(int fromKey, int toKey, boolean isInc) { 532 | List list = new ArrayList(); 533 | 534 | try{ 535 | this.lockRead(); 536 | if(fromKey <= toKey){ 537 | 538 | if(isInc){ 539 | BTreeNode node = this.seekNode(fromKey); 540 | boolean next = true; 541 | while(null != node){ 542 | int i = 0; 543 | for(; i < node.numKeys; ++i){ 544 | if(node.keys[i] >= fromKey && node.keys[i] <= toKey){ 545 | if(IdxBlock.VALID == node.values[i].tag){ 546 | IdxBlock iblk = new IdxBlock(node.keys[i]); 547 | iblk.pageID = node.values[i].pageID; 548 | iblk.offset = node.values[i].offset; 549 | 550 | list.add(iblk); 551 | } 552 | }else if(node.keys[i] > toKey){ 553 | next = false; 554 | break; 555 | } 556 | } 557 | if(next) 558 | node = node.next; 559 | else 560 | node = null; 561 | } 562 | }else{ 563 | 564 | BTreeNode node = this.seekNode(toKey); 565 | boolean next = true; 566 | while(null != node){ 567 | int i = node.numKeys - 1; 568 | for(; i >= 0; --i){ 569 | if(node.keys[i] >= fromKey && node.keys[i] <= toKey){ 570 | if(IdxBlock.VALID == node.values[i].tag){ 571 | IdxBlock iblk = new IdxBlock(node.keys[i]); 572 | iblk.pageID = node.values[i].pageID; 573 | iblk.offset = node.values[i].offset; 574 | 575 | list.add(iblk); 576 | } 577 | }else if(node.keys[i] < fromKey){ 578 | next = false; 579 | break; 580 | } 581 | } 582 | if(next) 583 | node = node.prior; 584 | else 585 | node = null; 586 | } 587 | } 588 | } 589 | }catch(Exception e){} 590 | finally{ 591 | this.unLockRead(); 592 | } 593 | 594 | return list; 595 | } 596 | 597 | @Override 598 | public void toByteBuffer(List list) { 599 | 600 | if(null != this.root && null != list){ 601 | 602 | try{ 603 | this.lockRead(); 604 | this.root.toByteBuffer(list, this.root); 605 | }catch(Exception e){ 606 | System.out.println(e); 607 | } 608 | finally{ 609 | this.unLockRead();; 610 | } 611 | } 612 | } 613 | 614 | @Override 615 | public int count(int fromKey, int toKey) { 616 | int count = 0; 617 | 618 | try{ 619 | this.lockRead(); 620 | if(fromKey <= toKey){ 621 | 622 | BTreeNode node = this.seekNode(fromKey); 623 | boolean next = true; 624 | while(null != node){ 625 | int i = 0; 626 | for(; i < node.numKeys; ++i){ 627 | if(node.keys[i] >= fromKey && node.keys[i] <= toKey){ 628 | if(IdxBlock.VALID == node.values[i].tag){ 629 | ++count; 630 | } 631 | }else if(node.keys[i] > toKey){ 632 | next = false; 633 | break; 634 | } 635 | } 636 | if(next) 637 | node = node.next; 638 | else 639 | node = null; 640 | } 641 | } 642 | }catch(Exception e){} 643 | finally{ 644 | this.unLockRead(); 645 | } 646 | 647 | return count; 648 | } 649 | 650 | } 651 | -------------------------------------------------------------------------------- /src/tenndb/bstar/SplitLeafVar.java: -------------------------------------------------------------------------------- 1 | package tenndb.bstar; 2 | 3 | public class SplitLeafVar { 4 | 5 | protected BTreeNode newRight = null; 6 | 7 | protected InsertVar oldVar = null; 8 | } 9 | -------------------------------------------------------------------------------- /src/tenndb/common/ByteUtil.java: -------------------------------------------------------------------------------- 1 | package tenndb.common; 2 | 3 | public final class ByteUtil { 4 | 5 | public static final int INT_SIZE = Integer.SIZE / Byte.SIZE; 6 | public static final int SHORT_SIZE = Short.SIZE / Byte.SIZE; 7 | public static final int BYTE_SIZE = Byte.SIZE / Byte.SIZE; 8 | 9 | public final static short BYTE_MAX_VALUE = 256; 10 | public final static int SHORT_MAX_VALUE = 65535; 11 | public final static long INT_MAX_VALUE = 4294967296L; 12 | 13 | public final static int byte2ToShort_big(byte[] buf, int offset) 14 | { 15 | int n = 0; 16 | if(null != buf) 17 | { 18 | for(int i = 0 ;i < 2; i++) 19 | { 20 | n <<= 8; 21 | n |= (buf[offset + i] & 0x000000FF); 22 | } 23 | } 24 | return n; 25 | } 26 | 27 | public static byte[] shortToByte2_big(int n) 28 | { 29 | byte[] buf = new byte[2]; 30 | 31 | for(int i = 1; i >= 0; i--){ 32 | buf[i] = (byte) (n & 0xFF); 33 | n >>= 8; 34 | } 35 | 36 | return buf; 37 | } 38 | 39 | 40 | public final static int byte4ToInt_big(byte[] buf, int offset) 41 | { 42 | int n = 0; 43 | if(null != buf) 44 | { 45 | for(int i = 0 ;i < 4; i++) 46 | { 47 | n <<= 8; 48 | n |= (buf[offset + i] & 0x000000FF); 49 | } 50 | } 51 | return n; 52 | } 53 | 54 | public static byte[] intToByte4_big(int n) 55 | { 56 | byte[] buf = new byte[4]; 57 | 58 | for(int i = 3; i >= 0; i--){ 59 | buf[i] = (byte) (n & 0xFF); 60 | n >>= 8; 61 | } 62 | 63 | return buf; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/tenndb/common/DateFormatUtil.java: -------------------------------------------------------------------------------- 1 | package tenndb.common; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Locale; 5 | import java.util.TimeZone; 6 | 7 | public class DateFormatUtil { 8 | 9 | private static final String GMT_TIME_ZONE = "GMT+08:00".intern(); 10 | 11 | public static ThreadLocal threadLocalDateFormat(final String pattern) 12 | { 13 | ThreadLocal tl = new ThreadLocal() { 14 | protected SimpleDateFormat initialValue() { 15 | SimpleDateFormat df = new SimpleDateFormat(pattern, Locale.ENGLISH); 16 | df.setTimeZone(TimeZone.getTimeZone(DateFormatUtil.GMT_TIME_ZONE)); 17 | return df; 18 | } 19 | }; 20 | return tl; 21 | } 22 | 23 | public static ThreadLocal threadLocalDateFormat 24 | (final String pattern, final TimeZone time_zone) 25 | { 26 | ThreadLocal tl = new ThreadLocal() 27 | { 28 | protected SimpleDateFormat initialValue() { 29 | SimpleDateFormat df = new SimpleDateFormat(pattern, Locale.ENGLISH); 30 | df.setTimeZone(time_zone); 31 | return df; 32 | } 33 | }; 34 | return tl; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/tenndb/common/FileDeco.java: -------------------------------------------------------------------------------- 1 | package tenndb.common; 2 | 3 | 4 | import java.nio.channels.FileChannel; 5 | 6 | public class FileDeco { 7 | 8 | protected String fileName; 9 | protected int ref = 0; 10 | protected int state; 11 | protected int size; 12 | protected FileChannel fc; 13 | 14 | // protected MappedByteBuffer out; 15 | 16 | protected final Object lock = new Object(); 17 | 18 | public static final int STATE_INIT = 0; 19 | public static final int STATE_OPEN = 1; 20 | public static final int STATE_CLOSING = 2; 21 | public static final int STATE_CLOSED = 3; 22 | 23 | public FileChannel getFileChannel(){ 24 | return this.fc; 25 | } 26 | 27 | public int incRef(){ 28 | int n = -1; 29 | synchronized(lock){ 30 | ref++; 31 | n = ref; 32 | } 33 | return n; 34 | } 35 | 36 | public int decRef(){ 37 | int n = -1; 38 | synchronized(lock){ 39 | ref--; 40 | n = ref; 41 | } 42 | return n; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/tenndb/common/FileMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.common; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.RandomAccessFile; 6 | import java.nio.ByteBuffer; 7 | 8 | import java.util.concurrent.ConcurrentHashMap; 9 | import java.util.concurrent.ConcurrentMap; 10 | 11 | 12 | public class FileMgr { 13 | 14 | protected ConcurrentMap fileMap = null; 15 | 16 | protected File dir; 17 | 18 | // static int LEN = 0x800000; // 128 Mb 19 | 20 | public FileMgr(String instName){ 21 | if(null != instName && instName.length() > 0){ 22 | dir = new File(instName); 23 | }else{ 24 | String homedir = System.getProperty("user.home"); 25 | dir = new File(homedir, instName); 26 | } 27 | 28 | if(!dir.exists()){ 29 | 30 | FileUtil.mkDir(dir); 31 | 32 | if(!dir.exists()){ 33 | throw new RuntimeException("cannot create " + instName); 34 | } 35 | } 36 | 37 | this.fileMap = new ConcurrentHashMap(); 38 | } 39 | 40 | public String[] listFiles(){ 41 | return dir.list(); 42 | } 43 | 44 | public boolean delete(String fileName){ 45 | boolean b = false; 46 | this.closeFileChannel(fileName); 47 | 48 | File file = new File(this.dir, fileName); 49 | if(file.exists()){ 50 | b = file.delete(); 51 | } 52 | 53 | if(b){ 54 | System.out.println("delete.ok " + fileName); 55 | }else{ 56 | System.out.println("delete.failed " + fileName); 57 | } 58 | 59 | return b; 60 | } 61 | 62 | public boolean copy(String oldFileName, String newFileName){ 63 | boolean b = false; 64 | 65 | try { 66 | long size = this.size(oldFileName); 67 | if(size > 0){ 68 | this.delete(newFileName); 69 | FileDeco dest = pinFileChannel(newFileName); 70 | FileDeco src = pinFileChannel(oldFileName); 71 | if(null != src && null != dest){ 72 | src.fc.position(0); 73 | dest.fc.position(0); 74 | ByteBuffer buffer = ByteBuffer.allocate(1000); 75 | while(src.fc.position() < src.fc.size() && src.fc.size() > 0){ 76 | 77 | src.fc.read(buffer); 78 | buffer.flip(); 79 | while(buffer.hasRemaining()){ 80 | dest.fc.write(buffer); 81 | } 82 | // System.out.println(src.fc.position() + "," + src.fc.size() + "," + buffer.limit()); 83 | buffer.rewind(); 84 | } 85 | b = true; 86 | } 87 | } 88 | } catch (IOException e) { 89 | e.printStackTrace(); 90 | } 91 | 92 | 93 | return b; 94 | } 95 | 96 | public long append(String fileName, ByteBuffer buffer){ 97 | long pos = 0; 98 | try { 99 | FileDeco dest = pinFileChannel(fileName); 100 | if(null != dest){ 101 | pos = dest.fc.size(); 102 | dest.fc.position(dest.fc.size()); 103 | 104 | buffer.position(0); 105 | 106 | while(buffer.hasRemaining()){ 107 | dest.fc.write(buffer); 108 | } 109 | } 110 | } catch (IOException e) { 111 | e.printStackTrace(); 112 | } 113 | return pos; 114 | } 115 | 116 | public boolean rename(String oldFileName, String newFileName){ 117 | boolean b = false; 118 | this.closeFileChannel(oldFileName); 119 | this.closeFileChannel(newFileName); 120 | 121 | File srcFile = new File(this.dir, oldFileName); 122 | File destFile = new File(this.dir, newFileName); 123 | 124 | b = srcFile.renameTo(destFile); 125 | if(b){ 126 | System.out.println("rename.ok " + oldFileName + " is renamed to " + newFileName); 127 | }else{ 128 | System.out.println("rename.failed " + oldFileName + " is renamed to " + newFileName); 129 | } 130 | return b; 131 | } 132 | 133 | 134 | public void readBuffer(String fileName, byte[] buffer, long pos) throws IOException{ 135 | File file = new File(this.dir, fileName); 136 | RandomAccessFile f = new RandomAccessFile(file, "rws"); 137 | 138 | f.seek(pos); 139 | f.read(buffer); 140 | f.close(); 141 | 142 | // f.close(); 143 | /* FileDeco fd = pinFileChannel(fileName); 144 | if(null != fd){ 145 | if(pos + len <= fd.fc.size()){ 146 | fd.fc.position(pos); 147 | fd.fc.read(buffer); 148 | } 149 | } */ 150 | } 151 | 152 | public void writeBuffer(String fileName, byte[] buffer, long pos) throws IOException{ 153 | 154 | File file = new File(this.dir, fileName); 155 | RandomAccessFile f = new RandomAccessFile(file, "rws"); 156 | 157 | f.seek(pos); 158 | f.write(buffer); 159 | f.close(); 160 | 161 | /* FileDeco fd = pinFileChannel(fileName); 162 | if(null != fd){ 163 | if(pos + len <= fd.fc.size()){ 164 | fd.fc.position(pos); 165 | while(buffer.hasRemaining()){ 166 | fd.fc.write(buffer); 167 | } 168 | } 169 | }*/ 170 | } 171 | 172 | public void removeFileChannel(String fileName) throws IOException{ 173 | 174 | FileDeco fd = null; 175 | fd = this.fileMap.remove(fileName); 176 | 177 | if(null != fd){ 178 | this.closeFileChannel(fd); 179 | } 180 | } 181 | 182 | public void closeFileChannel(FileDeco fd){ 183 | if(null != fd){ 184 | if(null != fd.fc){ 185 | try { 186 | 187 | fd.fc.close(); 188 | } catch (IOException e) { 189 | e.printStackTrace(); 190 | } 191 | } 192 | 193 | try { 194 | this.removeFileChannel(fd.fileName); 195 | } catch (IOException e) { 196 | e.printStackTrace(); 197 | } 198 | } 199 | } 200 | 201 | public void closeFileChannel(String fileName){ 202 | FileDeco fd = null; 203 | 204 | fd = this.fileMap.get(fileName); 205 | 206 | if(null != fd){ 207 | if(null != fd.fc){ 208 | try { 209 | 210 | fd.fc.close(); 211 | } catch (IOException e) { 212 | e.printStackTrace(); 213 | } 214 | } 215 | 216 | try { 217 | this.removeFileChannel(fd.fileName); 218 | } catch (IOException e) { 219 | e.printStackTrace(); 220 | } 221 | } 222 | } 223 | 224 | 225 | public FileDeco pinFileChannel(String fileName) throws IOException{ 226 | FileDeco fd = null; 227 | 228 | fd = this.fileMap.get(fileName); 229 | 230 | if(null == fd){ 231 | File file = new File(this.dir, fileName); 232 | RandomAccessFile f = new RandomAccessFile(file, "rws"); 233 | fd = new FileDeco(); 234 | fd.fileName = fileName; 235 | 236 | fd.fc = f.getChannel(); 237 | 238 | // fd.out = fd.fc.map(FileChannel.MapMode.READ_WRITE, 0, LEN); 239 | 240 | this.fileMap.put(fileName, fd); 241 | } 242 | 243 | return fd; 244 | } 245 | 246 | public synchronized long size(String filename) { 247 | long size = 0; 248 | try { 249 | FileDeco fd = pinFileChannel(filename); 250 | if(null != fd){ 251 | size = fd.fc.size(); 252 | } 253 | } catch (IOException e) { 254 | throw new RuntimeException("cannot access " + filename); 255 | } 256 | return size; 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /src/tenndb/common/FileUtil.java: -------------------------------------------------------------------------------- 1 | package tenndb.common; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileWriter; 6 | import java.io.IOException; 7 | import java.util.List; 8 | 9 | public class FileUtil 10 | { 11 | public final static void mkDir(File file) 12 | { 13 | if (file.getParentFile().exists()) { 14 | file.mkdir(); 15 | } else { 16 | mkDir(file.getParentFile()); 17 | file.mkdir(); 18 | } 19 | } 20 | 21 | public final static boolean createFile(File file) 22 | { 23 | boolean isCreated = false; 24 | if (file == null) 25 | { 26 | throw new RuntimeException(" can not create null file."); 27 | } 28 | 29 | if (file.exists()) 30 | isCreated = true; 31 | else 32 | { 33 | File parentDir = file.getParentFile(); 34 | 35 | if (parentDir != null && !parentDir.exists()) 36 | { 37 | if (!parentDir.mkdirs()) 38 | { 39 | isCreated = false; 40 | } 41 | } 42 | try 43 | { 44 | isCreated = file.createNewFile(); 45 | } catch (IOException e) 46 | { 47 | throw new RuntimeException(e); 48 | } 49 | } 50 | return isCreated; 51 | } 52 | 53 | public static boolean deleteDirectory(File path) 54 | { 55 | if (path.exists()) 56 | { 57 | File[] files = path.listFiles(); 58 | for (int i = 0; i < files.length; i++) 59 | { 60 | if (files[i].isDirectory()) 61 | { 62 | deleteDirectory(files[i]); 63 | } else 64 | { 65 | files[i].delete(); 66 | } 67 | } 68 | } 69 | return (path.delete()); 70 | } 71 | 72 | public final static boolean deleteFile(String filePath) 73 | { 74 | boolean ret = false; 75 | 76 | if(null != filePath && filePath.length() > 0) 77 | { 78 | File file = new File(filePath); 79 | 80 | if(file.exists()) 81 | { 82 | ret = file.delete(); 83 | } 84 | } 85 | return ret; 86 | } 87 | 88 | public static final void writeFile(String fullFilePath, List list) 89 | { 90 | if(null != fullFilePath && fullFilePath.length() > 0 && null != list && list.size() > 0) 91 | { 92 | File file = null; 93 | FileWriter fw = null; 94 | BufferedWriter out = null; 95 | try 96 | { 97 | file = new File(fullFilePath); 98 | 99 | 100 | fw = new FileWriter(file, true); 101 | out = new BufferedWriter(fw); 102 | for (String str : list) 103 | { 104 | if(null != str && str.length() > 0) 105 | { 106 | out.append(str); 107 | out.newLine(); 108 | } 109 | } 110 | out.flush(); 111 | } 112 | catch (Exception e) 113 | { 114 | System.out.println("fullFilePath = " + fullFilePath); 115 | e.printStackTrace(); 116 | } 117 | finally 118 | { 119 | if(null != fw){ 120 | try { 121 | fw.close(); 122 | } catch (IOException e) { 123 | } 124 | } 125 | 126 | if(null != out){ 127 | try { 128 | out.close(); 129 | } catch (IOException e) { 130 | } 131 | } 132 | } 133 | } 134 | } 135 | 136 | /* public final static boolean append(String path, String content) 137 | { 138 | boolean b = false; 139 | 140 | if(null != path && path.length() > 0 141 | && null != content && content.length() > 0 ) 142 | { 143 | File file = new File(path); 144 | 145 | if(createFile(file)) 146 | { 147 | RandomAccessFile accesser = null; 148 | try 149 | { 150 | accesser = new RandomAccessFile(file, "rw"); 151 | 152 | accesser.seek(accesser.length()); 153 | 154 | accesser.writeUTF(content); 155 | b = true; 156 | } catch (Exception e) 157 | { 158 | throw new RuntimeException(e); 159 | } 160 | finally 161 | { 162 | if(null != accesser) 163 | try 164 | { 165 | accesser.close(); 166 | } catch (IOException e) 167 | { 168 | } 169 | } 170 | } 171 | } 172 | 173 | return b; 174 | } 175 | 176 | public final static boolean append(String path, byte[] buf, int offset, int len) 177 | { 178 | boolean isAppended = false; 179 | 180 | if(null != path && path.length() > 0 && null != buf && buf.length > 0 && len > 0) 181 | { 182 | File file = new File(path); 183 | 184 | // System.out.println(path); 185 | 186 | if(createFile(file)) 187 | { 188 | RandomAccessFile accesser = null; 189 | try 190 | { 191 | accesser = new RandomAccessFile(file, "rw"); 192 | accesser.seek(accesser.length()); 193 | accesser.write(buf, offset, len); 194 | isAppended = true; 195 | } catch (Exception e) 196 | { 197 | throw new RuntimeException(e); 198 | } 199 | finally 200 | { 201 | if(null != accesser) 202 | try 203 | { 204 | accesser.close(); 205 | } catch (IOException e) 206 | { 207 | } 208 | } 209 | } 210 | } 211 | return isAppended; 212 | }*/ 213 | } 214 | -------------------------------------------------------------------------------- /src/tenndb/common/GraphFindCycle.java: -------------------------------------------------------------------------------- 1 | package tenndb.common; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | 7 | 8 | public class GraphFindCycle { 9 | public List servList; 10 | 11 | public void setServList(List servList){ 12 | this.servList = servList; 13 | } 14 | 15 | class ServRel{ 16 | public String useServId; 17 | public String providerServId; 18 | public double amount; 19 | } 20 | 21 | class Serv{ 22 | public String servId; 23 | public List refServ = new ArrayList(); 24 | } 25 | 26 | public List findRefServ(String servId,List servRelList){ 27 | List refServList = new ArrayList(); 28 | for(int i = 0; i < servRelList.size(); i++){ 29 | ServRel rel = (ServRel)servRelList.get(i); 30 | if(servId.equals(rel.useServId)){ 31 | refServList.add(rel.providerServId); 32 | } 33 | } 34 | return refServList; 35 | } 36 | 37 | class CycleServ{ 38 | public List cycleServList; 39 | } 40 | 41 | public void findCycleServ(String servId,String cyclePath, List servRelList){ 42 | String id = servId; 43 | List refServList = findRefServ(servId, servRelList); 44 | if(!(refServList.size()>0)){ 45 | return; 46 | } 47 | else if(cyclePath.indexOf(servId)>0){ 48 | System.out.println(cyclePath + "," + id); 49 | return; 50 | } 51 | else{ 52 | cyclePath = cyclePath+","+id; 53 | for(int j = 0; j < refServList.size(); j++){ 54 | String childServId = (String)refServList.get(j); 55 | findCycleServ(childServId,cyclePath,servRelList); 56 | } 57 | } 58 | } 59 | 60 | 61 | public static void main(String[] args) { 62 | GraphFindCycle gfc = new GraphFindCycle(); 63 | List servList = new ArrayList(); 64 | servList.add("A"); 65 | servList.add("B"); 66 | servList.add("C"); 67 | servList.add("D"); 68 | servList.add("E"); 69 | servList.add("F"); 70 | 71 | List servRelList = new ArrayList(); 72 | ServRel sr = gfc.new ServRel(); 73 | sr.useServId = "A"; 74 | sr.providerServId = "B"; 75 | servRelList.add(sr); 76 | ServRel sr1 = gfc.new ServRel(); 77 | sr1.useServId = "B"; 78 | sr1.providerServId = "A"; 79 | servRelList.add(sr1); 80 | ServRel sr2 = gfc.new ServRel(); 81 | sr2.useServId = "A"; 82 | sr2.providerServId = "C"; 83 | servRelList.add(sr2); 84 | ServRel sr3 = gfc.new ServRel(); 85 | sr3.useServId = "B"; 86 | sr3.providerServId = "D"; 87 | servRelList.add(sr3); 88 | ServRel sr4 = gfc.new ServRel(); 89 | sr4.useServId = "E"; 90 | sr4.providerServId = "A"; 91 | servRelList.add(sr4); 92 | ServRel sr5 = gfc.new ServRel(); 93 | sr5.useServId = "F"; 94 | sr5.providerServId = "B"; 95 | servRelList.add(sr5); 96 | 97 | //System.out.println(servRelList.size()); 98 | for(int i=0;i 10*1000L){ 43 | synchronized(_lock){ 44 | if((lastTick - this.baseTick) > 10*1000L){ 45 | // System.out.println("+++++++++++++++++++++++++++++++++++++++getCurrentTime"); 46 | this.baseTime = new Date().getTime(); 47 | this.baseTick = System.currentTimeMillis(); 48 | lastTick = this.baseTick; 49 | } 50 | } 51 | } 52 | 53 | currentTime = this.baseTime + (lastTick - this.baseTick); 54 | 55 | return currentTime; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/tenndb/common/test/TestSystemTime.java: -------------------------------------------------------------------------------- 1 | package tenndb.common.test; 2 | 3 | import java.util.Date; 4 | 5 | import tenndb.common.SystemTime; 6 | 7 | public class TestSystemTime { 8 | 9 | /** 10 | * @param args 11 | */ 12 | public static void main(String[] args) { 13 | 14 | for(int i = 0; i < 100; ++i){ 15 | SystemTime sys = SystemTime.getSystemTime(); 16 | System.out.println(new Date().toString() + " " + sys.currentTimeMillis()); 17 | try { 18 | Thread.sleep(1000); 19 | } catch (InterruptedException e) { 20 | // TODO Auto-generated catch block 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/tenndb/data/ByteBufferMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | import java.util.concurrent.LinkedBlockingQueue; 8 | 9 | public class ByteBufferMgr { 10 | 11 | protected List list = null; 12 | 13 | protected Queue queue = null; 14 | 15 | protected int size; 16 | 17 | protected final Object lock = new Object(); 18 | 19 | public ByteBufferMgr(int size) { 20 | super(); 21 | this.size = size; 22 | this.queue = new LinkedBlockingQueue(); 23 | this.list = new ArrayList(); 24 | } 25 | 26 | public ByteBuffer pinBuffer(){ 27 | ByteBuffer buffer = null; 28 | 29 | buffer = this.queue.poll(); 30 | 31 | if(null == buffer){ 32 | buffer = ByteBuffer.allocate(this.size); 33 | this.list.add(buffer); 34 | } 35 | 36 | return buffer; 37 | } 38 | 39 | public void unpinBuffer(ByteBuffer buffer){ 40 | 41 | if(null != buffer){ 42 | this.queue.add(buffer); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/tenndb/data/Colunm.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import tenndb.common.ByteUtil; 7 | 8 | public class Colunm { 9 | 10 | protected String key; 11 | 12 | protected int hashCode; 13 | protected int len; 14 | protected int version; 15 | protected List fileds; 16 | 17 | protected int time; 18 | 19 | public Colunm(String key, int version) { 20 | super(); 21 | this.key = key; 22 | this.hashCode = hashCode(key); 23 | this.version = version; 24 | this.fileds = new ArrayList(); 25 | this.len = 0; 26 | 27 | this.addFiled(new Filed("key", key)); 28 | } 29 | 30 | public static final int hashCode(String value){ 31 | int hashCode = 0; 32 | if(null != value && value.length() > 0){ 33 | hashCode = value.hashCode(); 34 | } 35 | return hashCode; 36 | } 37 | 38 | public int getTime() { 39 | return time; 40 | } 41 | 42 | public void setTime(int time) { 43 | this.time = time; 44 | } 45 | 46 | public int getLen(){ 47 | return len; 48 | } 49 | 50 | public int getVersion() { 51 | return version; 52 | } 53 | 54 | public int getHashCode(){ 55 | return this.hashCode; 56 | } 57 | 58 | public String getKey() { 59 | if(null == this.key && this.fileds.size() > 0){ 60 | this.key = this.fileds.get(0).getValue(); 61 | } 62 | return key; 63 | } 64 | 65 | public void addFiled(Filed filed){ 66 | if(null != filed){ 67 | this.len += ByteUtil.SHORT_SIZE; 68 | String value = filed.getValue(); 69 | if(null != value && value.length() > 0){ 70 | this.len += value.length(); 71 | } 72 | fileds.add(filed); 73 | } 74 | } 75 | 76 | public final List getFileds() { 77 | return fileds; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/tenndb/data/DBBlock.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | import java.util.List; 4 | 5 | import tenndb.common.ByteUtil; 6 | 7 | 8 | public class DBBlock { 9 | 10 | //head 11 | protected int pageID; 12 | 13 | protected int offset; 14 | 15 | //body 16 | protected PageBuffer page = null; 17 | 18 | public static final int HEAD_SIZE = ByteUtil.INT_SIZE + ByteUtil.SHORT_SIZE + ByteUtil.SHORT_SIZE; 19 | 20 | public DBBlock(PageBuffer page){ 21 | this.page = page; 22 | } 23 | 24 | public int getTableID(){ 25 | int tableID = 0; 26 | if(null != this.page){ 27 | tableID = this.page.getTableID(); 28 | } 29 | return tableID; 30 | } 31 | 32 | public String getTableName(){ 33 | String tableName = null; 34 | 35 | if(null != this.page){ 36 | tableName = this.page.getTableName(); 37 | } 38 | 39 | return tableName; 40 | } 41 | 42 | public Colunm getColunm(){ 43 | Colunm colunm = null; 44 | int version = 0; 45 | int length = 0; 46 | int key = 0; 47 | 48 | synchronized(this.page){ 49 | // this.page.buffer.rewind(); 50 | this.page.buffer.position(DBPage.HEAD_SIZE + this.offset); 51 | 52 | key = this.page.buffer.getInt(); 53 | 54 | version = this.page.buffer.getShort(); 55 | if(version < 0){ 56 | version += ByteUtil.SHORT_MAX_VALUE; 57 | } 58 | 59 | length = this.page.buffer.getShort(); 60 | if(length < 0){ 61 | length += ByteUtil.SHORT_MAX_VALUE; 62 | } 63 | 64 | int total = length; 65 | int index = 0; 66 | 67 | 68 | while(total > 0){ 69 | int len = this.page.buffer.getShort(); 70 | if(len < 0){ 71 | len += ByteUtil.SHORT_MAX_VALUE; 72 | } 73 | 74 | if(len > 0){ 75 | byte[] buff = new byte[len]; 76 | this.page.buffer.get(buff); 77 | String value = new String(buff); 78 | 79 | if(0 == index){ 80 | colunm = new Colunm(value, version); 81 | }else{ 82 | Filed filed = new Filed("filed_" + index, value); 83 | colunm.fileds.add(filed); 84 | } 85 | } 86 | 87 | total -= (ByteUtil.SHORT_SIZE + len); 88 | index++; 89 | } 90 | } 91 | 92 | colunm.len = length; 93 | return colunm; 94 | } 95 | 96 | public void setColunm(Colunm colunm){ 97 | if(null != colunm ){ 98 | this.setVar(colunm.hashCode, colunm.version, colunm.len, colunm.fileds); 99 | } 100 | } 101 | 102 | public void setVar(int hashCode, int version, byte[] buff, int offset, int len){ 103 | 104 | if(null != buff && buff.length > 0 && len > 0 && offset >= 0 && (offset + len) <= buff.length){ 105 | 106 | synchronized(this.page){ 107 | // this.page.buffer.rewind(); 108 | this.page.buffer.limit(DBPage.HEAD_SIZE + this.offset + DBBlock.HEAD_SIZE + len); 109 | this.page.buffer.position(DBPage.HEAD_SIZE + this.offset); 110 | //dword key 111 | //word version 112 | //word len 113 | //byte[] buff 114 | this.page.buffer.putInt(hashCode); 115 | byte[] vers = ByteUtil.shortToByte2_big(version); 116 | this.page.buffer.put(vers); 117 | 118 | byte[] lens = ByteUtil.shortToByte2_big(len); 119 | this.page.buffer.put(lens); 120 | 121 | this.page.buffer.put(buff, offset, len); 122 | } 123 | } 124 | } 125 | 126 | public void setVar(int hashCode, int version, int len, List fileds){ 127 | 128 | if(null != fileds && version >= 0){ 129 | 130 | synchronized(this.page){ 131 | // this.page.buffer.rewind(); 132 | this.page.buffer.limit(DBPage.HEAD_SIZE + this.offset + DBBlock.HEAD_SIZE + len); 133 | this.page.buffer.position(DBPage.HEAD_SIZE + this.offset); 134 | //dword key 135 | //word version 136 | //word len 137 | //word filed1_len 138 | //word filed1_buff 139 | //word filed2_len 140 | //word filed2_buff 141 | this.page.buffer.putInt(hashCode); 142 | 143 | byte[] vers = ByteUtil.shortToByte2_big(version); 144 | this.page.buffer.put(vers); 145 | 146 | byte[] lens = ByteUtil.shortToByte2_big(len); 147 | this.page.buffer.put(lens); 148 | 149 | int total = 0; 150 | for(int i = 0; i < fileds.size(); ++i){ 151 | Filed filed = fileds.get(i); 152 | if(null != filed.value){ 153 | byte[] buff = filed.value.getBytes(); 154 | if(null != buff && buff.length > 0){ 155 | total += (ByteUtil.SHORT_SIZE + buff.length); 156 | if(total <= ByteUtil.SHORT_MAX_VALUE){ 157 | 158 | byte[] itemsize = ByteUtil.shortToByte2_big(buff.length); 159 | 160 | this.page.buffer.put(itemsize, 0, itemsize.length); 161 | this.page.buffer.put(buff, 0, buff.length); 162 | }else{ 163 | total -= (ByteUtil.SHORT_SIZE + buff.length); 164 | break; 165 | } 166 | } 167 | } 168 | } 169 | } 170 | } 171 | } 172 | 173 | public PageBuffer getPage() { 174 | return page; 175 | } 176 | 177 | public int getPageID() { 178 | return pageID; 179 | } 180 | 181 | public void setPageID(int pageID) { 182 | this.pageID = pageID; 183 | } 184 | 185 | public int getOffset() { 186 | return offset; 187 | } 188 | 189 | public void setOffset(int offset) { 190 | this.offset = offset; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/tenndb/data/DBPage.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | import tenndb.common.ByteUtil; 4 | 5 | 6 | public class DBPage { 7 | 8 | // public static final int MAX_BLOCK_SIZE = 10; 9 | 10 | 11 | 12 | //len 13 | // public static final int BLOCK_HEAD_SIZE = INT_SIZE; 14 | //data 15 | // public static final int BLOCK_BODY_SIZE = INT_SIZE * 24; 16 | 17 | // public static final int BLOCK_SIZE = BLOCK_HEAD_SIZE + BLOCK_BODY_SIZE; 18 | 19 | //(num,key,data) x86: (1 + 4 + 40)*20=900 20 | 21 | //pageid + size 22 | public static final int HEAD_SIZE = 0;//INT_SIZE + INT_SIZE ; 23 | // public static final int BLOCK_SIZE = ByteUtil.INT_SIZE; 24 | 25 | public static final int PAGE_SIZE = 1024 * 40; 26 | //HEAD_SIZE + 27 | //(key + offset)*BALANCE_SIZE 48 28 | // BLOCK_SIZE * MAX_BLOCK_SIZE; 29 | 30 | 31 | public static final int MAX_BLOCK_SIZE = ByteUtil.SHORT_MAX_VALUE; 32 | 33 | protected static final int NEW_PAGES_SIZE = 10; 34 | 35 | protected static final int PAGE_INDEX_SIZE = ByteUtil.INT_SIZE + ByteUtil.INT_SIZE; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/tenndb/data/DBPageMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | import tenndb.common.FileMgr; 4 | 5 | public class DBPageMgr { 6 | 7 | protected PageBufferMgr pageMgr = null; 8 | 9 | protected String dbName; 10 | 11 | protected FileMgr fileMgr = null; 12 | 13 | protected final Object lock = new Object(); 14 | 15 | public DBPageMgr(String dbName, FileMgr fileMgr){ 16 | this.dbName = dbName; 17 | this.fileMgr = fileMgr; 18 | 19 | this.pageMgr = new PageBufferMgr(this.dbName, fileMgr); 20 | } 21 | 22 | public void load(){ 23 | this.pageMgr.load(); 24 | } 25 | 26 | public void flush(){ 27 | this.pageMgr.flushPage(); 28 | this.pageMgr.flushData(); 29 | } 30 | 31 | public PageBuffer getPageBuffer(int pageID){ 32 | PageBuffer buffer = null; 33 | 34 | buffer = this.pageMgr.getPageBuffer(pageID); 35 | 36 | return buffer; 37 | } 38 | 39 | public synchronized DBBlock getDBBlock(int pageID, int offset){ 40 | DBBlock blk = null; 41 | // System.out.println("getDBBlock.1"); 42 | PageBuffer buffer = this.getPageBuffer(pageID); 43 | if(null != buffer){ 44 | // System.out.println("getDBBlock.2"); 45 | blk = buffer.getBlock(offset); 46 | }else{ 47 | // System.out.println("getDBBlock.3"); 48 | } 49 | 50 | return blk; 51 | } 52 | 53 | public DBBlock nextDBBlock(int hashCode, int version, byte[] buff, int offset, int len){ 54 | DBBlock blk = null; 55 | 56 | if(null != buff && buff.length > 0 && offset >= 0 && len > 0 && (offset + len) <= buff.length){ 57 | blk = this.pageMgr.nextBlock(hashCode, version, buff, offset, len); 58 | } 59 | 60 | return blk; 61 | } 62 | 63 | public DBBlock nextDBBlock(Colunm colunm){ 64 | 65 | return this.pageMgr.nextBlock(colunm); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/tenndb/data/Filed.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | public class Filed { 4 | 5 | public static final byte BYTE = 1; 6 | public static final byte WORD = 2; 7 | public static final byte DWORD = 4; 8 | public static final byte LWORD = 8; 9 | 10 | protected byte type; 11 | protected String name; 12 | protected String value; 13 | 14 | public Filed(String name, String value) { 15 | super(); 16 | this.name = name; 17 | this.value = value; 18 | } 19 | public String getName() { 20 | return name; 21 | } 22 | public String getValue() { 23 | return value; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/tenndb/data/PageBuffer.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import tenndb.common.SystemTime; 6 | 7 | 8 | public class PageBuffer { 9 | 10 | protected int pageID; 11 | 12 | protected int offset; 13 | 14 | protected int size; 15 | 16 | protected ByteBuffer buffer = null; 17 | 18 | protected int tableID; 19 | 20 | protected String tableName; 21 | 22 | protected int tick; 23 | 24 | public PageBuffer(String tableName){ 25 | this.pageID = 0; 26 | this.offset = 0; 27 | this.tableName = tableName; 28 | this.size = DBPage.PAGE_SIZE; 29 | this.tableID = 0; 30 | this.tick = SystemTime.getSystemTime().currentTime(); 31 | } 32 | 33 | public String getTableName(){ 34 | return this.tableName; 35 | } 36 | 37 | public int getTableID(){ 38 | return this.tableID; 39 | } 40 | 41 | public int getPageID() { 42 | return this.pageID; 43 | } 44 | 45 | public void setPageID(int pageID) { 46 | this.pageID = pageID; 47 | } 48 | 49 | public int getOffset() { 50 | return this.offset; 51 | } 52 | 53 | public int getSize() { 54 | return size; 55 | } 56 | 57 | public boolean isfull(int len){ 58 | return (this.offset + DBBlock.HEAD_SIZE + len) > this.size; 59 | } 60 | 61 | public DBBlock nextBlock(int hashCode, int version, byte[] buff, int offset, int len){ 62 | DBBlock blk = null; 63 | if(null != buff && buff.length > 0 && (this.offset + DBBlock.HEAD_SIZE + len) <= this.size){ 64 | synchronized(this){ 65 | try{ 66 | blk = this.getBlock(this.offset); 67 | blk.setVar(hashCode, version, buff, offset, len); 68 | this.offset += (DBBlock.HEAD_SIZE + len); 69 | }catch(Exception e){ 70 | System.out.println("nextBlock.1 " + e + " " + this.buffer.capacity() + " " + this.buffer.limit() + " " + this.buffer.position() + " " + this.size + ", " + this.offset + ", " + len); 71 | } 72 | } 73 | } 74 | 75 | return blk; 76 | } 77 | 78 | public DBBlock nextBlock(Colunm colunm){ 79 | DBBlock blk = null; 80 | if((this.offset + DBBlock.HEAD_SIZE + colunm.len) <= this.size){ 81 | try{ 82 | blk = this.getBlock(this.offset); 83 | blk.setColunm(colunm); 84 | this.offset += (DBBlock.HEAD_SIZE + colunm.len); 85 | }catch(Exception e){ 86 | System.out.println("nextBlock.2 " + e + " " + this.buffer.capacity() + " " + this.buffer.limit() + " " + this.buffer.position() + " " + this.size + ", " + this.offset + ", " + colunm.len); 87 | } 88 | } 89 | return blk; 90 | } 91 | 92 | public void setBlock(Colunm colunm, int offset){ 93 | DBBlock block = this.getBlock(offset); 94 | 95 | if(null != block){ 96 | block.setColunm(colunm); 97 | } 98 | } 99 | 100 | public Colunm getColunm(int offset){ 101 | Colunm colunm = null;; 102 | DBBlock blk = this.getBlock(offset); 103 | if(null != blk){ 104 | colunm = blk.getColunm(); 105 | } 106 | return colunm; 107 | } 108 | 109 | public DBBlock getBlock(int offset){ 110 | DBBlock blk = null; 111 | // System.out.println("getBlock " + offset + ", " + this.size + ", " + this.pageID); 112 | if(offset < this.size){ 113 | blk = new DBBlock(this); 114 | blk.setOffset(offset); 115 | blk.setPageID(this.pageID); 116 | this.tick = SystemTime.getSystemTime().currentTime(); 117 | } 118 | 119 | return blk; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/tenndb/data/PageBufferMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | 4 | import java.io.IOException; 5 | import java.nio.ByteBuffer; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.Queue; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | import java.util.concurrent.ConcurrentMap; 13 | import java.util.concurrent.LinkedBlockingDeque; 14 | import java.util.concurrent.locks.ReadWriteLock; 15 | import java.util.concurrent.locks.ReentrantReadWriteLock; 16 | 17 | import tenndb.common.FileDeco; 18 | import tenndb.common.FileMgr; 19 | 20 | public class PageBufferMgr { 21 | 22 | protected String dbName = null; 23 | 24 | protected Map unusedMap = null; 25 | 26 | protected Queue unusedQueue = null; 27 | 28 | protected List usedList = null; 29 | 30 | protected ConcurrentMap pageMap = null; 31 | 32 | protected FileMgr fileMgr = null; 33 | 34 | protected ByteBufferMgr bufMgr = null; 35 | 36 | // protected final Object lock = new Object(); 37 | 38 | protected static final String PREFIX_UNUSED_PAGE = "unused_page_"; 39 | 40 | protected static final String PREFIX_DATA = "data_"; 41 | 42 | 43 | protected ReadWriteLock lock = new ReentrantReadWriteLock(false); 44 | 45 | public void RLock() { this.lock.readLock().lock(); } 46 | 47 | public void URLock() { this.lock.readLock().unlock(); } 48 | 49 | public void WLock() { this.lock.writeLock().lock(); } 50 | 51 | public void UWLock() { this.lock.writeLock().unlock(); } 52 | 53 | 54 | public PageBufferMgr(String dbName, FileMgr fileMgr){ 55 | this.dbName = dbName; 56 | this.fileMgr = fileMgr; 57 | 58 | this.unusedQueue = new LinkedBlockingDeque(); 59 | this.usedList = new ArrayList(); 60 | this.pageMap = new ConcurrentHashMap(); 61 | this.unusedMap = new HashMap(); 62 | this.bufMgr = new ByteBufferMgr(DBPage.PAGE_SIZE); 63 | } 64 | 65 | protected DBBlock getBlock(int hashCode, int version, byte[] buff, int offset, int len){ 66 | DBBlock blk = null; 67 | 68 | this.RLock(); 69 | 70 | PageBuffer page = this.unusedQueue.peek(); 71 | 72 | if(null != page){ 73 | 74 | if(page.isfull(len)){ 75 | 76 | this.URLock(); 77 | this.WLock(); 78 | 79 | PageBuffer full = this.unusedQueue.poll(); 80 | this.usedList.add(full); 81 | this.unusedMap.remove(page.pageID); 82 | page = this.unusedQueue.peek(); 83 | 84 | this.UWLock(); 85 | this.RLock(); 86 | } 87 | 88 | if(null != page){ 89 | blk = page.nextBlock(hashCode, version, buff, offset, len); 90 | } 91 | } 92 | 93 | this.URLock(); 94 | return blk; 95 | } 96 | 97 | protected DBBlock getBlock(Colunm colunm){ 98 | DBBlock blk = null; 99 | 100 | this.RLock(); 101 | 102 | PageBuffer page = this.unusedQueue.peek(); 103 | 104 | if(null != page){ 105 | 106 | if(page.isfull(colunm.len)){ 107 | 108 | this.URLock(); 109 | this.WLock(); 110 | 111 | PageBuffer full = this.unusedQueue.poll(); 112 | this.usedList.add(full); 113 | this.unusedMap.remove(page.pageID); 114 | page = this.unusedQueue.peek(); 115 | 116 | this.UWLock(); 117 | this.RLock(); 118 | } 119 | 120 | if(null != page){ 121 | blk = page.nextBlock(colunm); 122 | } 123 | } 124 | 125 | this.URLock(); 126 | return blk; 127 | } 128 | 129 | public DBBlock nextBlock(int hashCode, int version, byte[] buff, int offset, int len){ 130 | DBBlock blk = null; 131 | if(null != buff && buff.length > 0 && (len + DBBlock.HEAD_SIZE) <= DBPage.MAX_BLOCK_SIZE){ 132 | blk = this.getBlock(hashCode, version, buff, offset, len); 133 | 134 | if(null == blk){ 135 | this.apppend(); 136 | blk = this.getBlock(hashCode, version, buff, offset, len); 137 | } 138 | } 139 | 140 | return blk; 141 | } 142 | 143 | public DBBlock nextBlock(Colunm colunm){ 144 | DBBlock blk = null; 145 | if(colunm.len > 0 && (colunm.len + DBBlock.HEAD_SIZE) <= DBPage.MAX_BLOCK_SIZE){ 146 | blk = this.getBlock(colunm); 147 | 148 | if(null == blk){ 149 | this.apppend(); 150 | blk = this.getBlock(colunm); 151 | } 152 | } 153 | 154 | return blk; 155 | } 156 | 157 | public void flushData(){ 158 | this.RLock(); 159 | 160 | PageBuffer page = this.unusedQueue.peek(); 161 | if(null != page){ 162 | this.setPageBuffer(page); 163 | } 164 | 165 | if(usedList.size() > 0){ 166 | for(int i = 0; i < usedList.size(); ++i){ 167 | PageBuffer buffer = usedList.get(i); 168 | this.setPageBuffer(buffer); 169 | 170 | this.pageMap.remove(buffer.pageID); 171 | } 172 | 173 | usedList.clear(); 174 | } 175 | 176 | this.URLock(); 177 | } 178 | 179 | public void flushPage(){ 180 | this.RLock(); 181 | 182 | List unusedList = new ArrayList(); 183 | if(this.unusedMap.size() > 0){ 184 | 185 | for(Integer pageID : this.unusedMap.keySet()){ 186 | 187 | PageBuffer buffer = this.unusedMap.get(pageID); 188 | 189 | PageUnusedIndex index = new PageUnusedIndex(); 190 | index.pageID = buffer.pageID; 191 | index.offset = buffer.offset; 192 | unusedList.add(index); 193 | } 194 | } 195 | 196 | if(null != unusedList && unusedList.size() > 0){ 197 | FileDeco fd = null; 198 | try { 199 | fd = this.fileMgr.pinFileChannel(PREFIX_UNUSED_PAGE + this.dbName); 200 | if(null != fd){ 201 | fd.getFileChannel().position(0); 202 | 203 | ByteBuffer buffer = ByteBuffer.allocate(DBPage.PAGE_INDEX_SIZE * unusedList.size()); 204 | buffer.rewind(); 205 | for(int i = 0; i < unusedList.size(); ++i){ 206 | PageUnusedIndex index = unusedList.get(i); 207 | buffer.putInt(index.pageID); 208 | buffer.putInt(index.offset); 209 | } 210 | 211 | buffer.flip(); 212 | fd.getFileChannel().position(0); 213 | 214 | while(buffer.hasRemaining()) { 215 | fd.getFileChannel().write(buffer); 216 | } 217 | } 218 | } catch (IOException e) { 219 | e.printStackTrace(); 220 | } finally{ 221 | if(null != fd){ 222 | this.fileMgr.closeFileChannel(fd); 223 | } 224 | } 225 | } 226 | 227 | this.URLock(); 228 | } 229 | 230 | public void load(){ 231 | 232 | List unusedList = new ArrayList(); 233 | 234 | FileDeco fd = null; 235 | try { 236 | fd = this.fileMgr.pinFileChannel(PREFIX_UNUSED_PAGE + this.dbName); 237 | if(null != fd){ 238 | int len = (int) fd.getFileChannel().size(); 239 | ByteBuffer buffer = ByteBuffer.allocate(len); 240 | int size = fd.getFileChannel().read(buffer); 241 | int limit = size / DBPage.PAGE_INDEX_SIZE; 242 | for(int i = 0; i < limit; ++i){ 243 | int pageID = buffer.getInt(i * DBPage.PAGE_INDEX_SIZE); 244 | int offset = buffer.getInt(i * DBPage.PAGE_INDEX_SIZE + 4); 245 | 246 | PageUnusedIndex blk = new PageUnusedIndex(); 247 | blk.pageID = pageID; 248 | blk.offset = offset; 249 | 250 | if(!this.unusedMap.containsKey(blk.pageID)){ 251 | unusedList.add(blk); 252 | } 253 | } 254 | } 255 | } catch (IOException e) { 256 | e.printStackTrace(); 257 | } finally{ 258 | if(null != fd){ 259 | this.fileMgr.closeFileChannel(fd); 260 | } 261 | } 262 | 263 | if(null != unusedList && unusedList.size() > 0){ 264 | for(int i = 0; i < unusedList.size(); ++i){ 265 | PageUnusedIndex index = unusedList.get(i); 266 | PageBuffer buff = this.getPageBuffer(index.pageID); 267 | if(null != buff){ 268 | buff.offset = index.offset; 269 | this.unusedQueue.add(buff); 270 | this.unusedMap.put(buff.pageID, buff); 271 | } 272 | } 273 | } 274 | } 275 | 276 | public void setPageBuffer(PageBuffer buffer){ 277 | if(null != buffer){ 278 | FileDeco fd = null; 279 | try { 280 | fd = this.fileMgr.pinFileChannel(PREFIX_DATA + this.dbName); 281 | 282 | if (null != fd && null != fd.getFileChannel() && fd.getFileChannel().isOpen()) { 283 | int limit = (int) (fd.getFileChannel().size()/DBPage.PAGE_SIZE); 284 | 285 | if (buffer.pageID < limit) { 286 | buffer.buffer.flip(); 287 | int read = fd.getFileChannel().write(buffer.buffer, buffer.pageID * DBPage.PAGE_SIZE); 288 | if (DBPage.PAGE_SIZE == read) { 289 | 290 | } 291 | } 292 | } 293 | } catch (IOException e) { 294 | System.out.println(e); 295 | if (null != fd) { 296 | this.fileMgr.closeFileChannel(fd); 297 | } 298 | } 299 | } 300 | } 301 | 302 | public PageBuffer getPageBuffer(int pageID) { 303 | PageBuffer buffer = null; 304 | 305 | buffer = this.pin(pageID); 306 | 307 | if (null == buffer) { 308 | 309 | FileDeco fd = null; 310 | try { 311 | fd = this.fileMgr.pinFileChannel(PREFIX_DATA + this.dbName); 312 | 313 | if (null != fd && null != fd.getFileChannel() && fd.getFileChannel().isOpen()) { 314 | int limit = (int) (fd.getFileChannel().size()/DBPage.PAGE_SIZE); 315 | 316 | if (pageID <= limit) { 317 | PageBuffer pageBuffer = new PageBuffer(this.dbName); 318 | pageBuffer.pageID = pageID; 319 | pageBuffer.buffer = this.bufMgr.pinBuffer(); 320 | 321 | int read = fd.getFileChannel().read(pageBuffer.buffer, pageID * DBPage.PAGE_SIZE); 322 | if (DBPage.PAGE_SIZE == read) { 323 | this.put(pageBuffer); 324 | buffer = pageBuffer; 325 | } 326 | } 327 | } 328 | } catch (IOException e) { 329 | System.out.println(e); 330 | if (null != fd) { 331 | this.fileMgr.closeFileChannel(fd); 332 | } 333 | } 334 | } 335 | 336 | return buffer; 337 | } 338 | 339 | public void apppend(){ 340 | 341 | FileDeco fd = null; 342 | try { 343 | fd = this.fileMgr.pinFileChannel(PREFIX_DATA + this.dbName); 344 | 345 | if(null != fd){ 346 | // long size0 = fd.getFileChannel().size(); 347 | int pos = (int)(fd.getFileChannel().size()/DBPage.PAGE_SIZE) ; 348 | 349 | // System.out.println(size0 + ", " + size0/DBPage.PAGE_SIZE + ", " + size0 % DBPage.PAGE_SIZE ); 350 | 351 | // System.out.println(key + ", append.1, size = " + fd.getFileChannel().size() + ", pos = " + pos); 352 | ByteBuffer[] array = new ByteBuffer[DBPage.NEW_PAGES_SIZE]; 353 | List newBuffList = new ArrayList(); 354 | for(int i = 0; i < DBPage.NEW_PAGES_SIZE; ++i){ 355 | PageBuffer pageBuffer = new PageBuffer(this.dbName); 356 | pageBuffer.pageID = pos + i; 357 | pageBuffer.buffer = this.bufMgr.pinBuffer(); 358 | 359 | pageBuffer.buffer.rewind(); 360 | // pageBuffer.buffer.putInt(0, pageBuffer.pageID); 361 | // pageBuffer.buffer.putInt(4, 0); 362 | 363 | array[i] = pageBuffer.buffer; 364 | newBuffList.add(pageBuffer); 365 | } 366 | 367 | fd.getFileChannel().position(fd.getFileChannel().size()); 368 | 369 | long size = fd.getFileChannel().write(array, 0, DBPage.NEW_PAGES_SIZE); 370 | // System.out.println(key + ", append.2, size = " + size); 371 | if(size == DBPage.NEW_PAGES_SIZE * DBPage.PAGE_SIZE){ 372 | 373 | // System.out.println(key + ", append.3, size = " + this.unusedQueue.size()); 374 | 375 | for(int i = 0; i < newBuffList.size(); ++i){ 376 | PageBuffer page = newBuffList.get(i); 377 | this.put(page); 378 | this.unusedMap.put(page.pageID, page); 379 | this.unusedQueue.add(page); 380 | } 381 | } 382 | } 383 | } catch (IOException e) { 384 | System.out.println(e); 385 | if(null != fd){ 386 | this.fileMgr.closeFileChannel(fd); 387 | } 388 | } 389 | } 390 | 391 | public void put(PageBuffer buffer){ 392 | this.pageMap.put(buffer.pageID, buffer); 393 | } 394 | 395 | public PageBuffer pin(int pageID){ 396 | return this.pageMap.get(pageID); 397 | } 398 | 399 | public PageBuffer unpin(int pageID){ 400 | return this.pageMap.remove(pageID); 401 | } 402 | } 403 | -------------------------------------------------------------------------------- /src/tenndb/data/PageUnusedIndex.java: -------------------------------------------------------------------------------- 1 | package tenndb.data; 2 | 3 | public class PageUnusedIndex { 4 | 5 | protected int pageID; 6 | protected int offset; 7 | 8 | public PageUnusedIndex(){ 9 | this.pageID = 0; 10 | this.offset = 0; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tenndb/dist/DistMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.dist; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Queue; 6 | import java.util.concurrent.LinkedBlockingDeque; 7 | import java.util.concurrent.atomic.AtomicInteger; 8 | import java.util.concurrent.locks.ReadWriteLock; 9 | import java.util.concurrent.locks.ReentrantReadWriteLock; 10 | import java.nio.ByteBuffer; 11 | 12 | import tenndb.common.ByteUtil; 13 | import tenndb.common.FileMgr; 14 | import tenndb.thread.DistThread; 15 | 16 | public class DistMgr { 17 | 18 | protected FileMgr fileMgr = null; 19 | 20 | protected Queue unusedQueue = null; 21 | 22 | protected List usedList = null; 23 | 24 | protected AtomicInteger counter = null; 25 | 26 | protected static final int MAX_PAGE_NUM = 3; 27 | 28 | protected static final int MAX_QUEUE_SIZE = ByteUtil.SHORT_MAX_VALUE - ByteUtil.BYTE_MAX_VALUE; 29 | 30 | public static final String DIST_PATH = System.getProperty("file.separator") + "dist_data"; 31 | 32 | public static final String PREFIX_TEMP = "temp_"; 33 | 34 | public static final String PREFIX_DELETE = "delete_"; 35 | 36 | public static final String PREFIX_QUEUE = "queue_"; 37 | 38 | public static final byte TAG_DATA = 1; 39 | public static final byte TAG_NULL = 0; 40 | 41 | protected DistThread distThread = null; 42 | 43 | protected final ReadWriteLock lock = new ReentrantReadWriteLock(false); 44 | 45 | protected volatile boolean initialized = false; 46 | 47 | 48 | public DistMgr(String root){ 49 | 50 | this.fileMgr = new FileMgr(root + DIST_PATH); 51 | this.unusedQueue = new LinkedBlockingDeque(); 52 | this.usedList = new ArrayList(); 53 | 54 | this.counter = new AtomicInteger(1); 55 | } 56 | 57 | public void init(){ 58 | if(false == this.initialized){ 59 | try{ 60 | this.lockWrite(); 61 | if(false == this.initialized){ 62 | this.distThread = new DistThread(this); 63 | this.distThread.start(); 64 | this.initialized = true; 65 | } 66 | }catch(Exception e){ 67 | System.out.println(e); 68 | }finally{ 69 | this.unLockWrite(); 70 | } 71 | } 72 | } 73 | 74 | public void flush(DistPage page, String fileName){ 75 | if(null != page && null != page.buffer && page.buffer.limit() > 0){ 76 | page.buffer.rewind(); 77 | String tempFileName = PREFIX_TEMP + PREFIX_QUEUE + fileName; 78 | String newfileName = PREFIX_QUEUE + fileName; 79 | 80 | this.fileMgr.append(tempFileName, page.buffer); 81 | this.fileMgr.rename(tempFileName, newfileName); 82 | this.fileMgr.closeFileChannel(newfileName); 83 | page.clear(); 84 | 85 | synchronized(this.lock){ 86 | if(this.unusedQueue.size() < MAX_PAGE_NUM){ 87 | this.unusedQueue.add(page); 88 | } 89 | } 90 | } 91 | } 92 | 93 | public String newFileName(){ 94 | String fileName = null; 95 | int index = this.counter.getAndIncrement(); 96 | if(index > MAX_QUEUE_SIZE){ 97 | index = this.counter.getAndSet(1); 98 | } 99 | fileName = String.format("%04X", index); 100 | return fileName; 101 | } 102 | 103 | 104 | public List getAndClearUsedList(){ 105 | List list = null; 106 | synchronized(this.lock){ 107 | if(this.usedList.size() > 0){ 108 | list = this.usedList; 109 | this.usedList = new ArrayList(); 110 | } 111 | } 112 | return list; 113 | } 114 | 115 | protected DistPage pinDistPage(){ 116 | DistPage page = this.unusedQueue.peek(); 117 | 118 | if(null == page){ 119 | ByteBuffer buff = ByteBuffer.allocate(DistPage.PAGE_SIZE); 120 | page = new DistPage(buff); 121 | this.unusedQueue.add(page); 122 | } 123 | 124 | return page; 125 | } 126 | 127 | public void write(List list){ 128 | if(null != list && list.size() > 0){ 129 | synchronized(this.lock){ 130 | for(byte[] array : list){ 131 | 132 | DistPage page = this.pinDistPage(); 133 | boolean b = page.write(array); 134 | if(false == b){ 135 | this.usedList.add(page); 136 | this.unusedQueue.poll(); 137 | page = this.pinDistPage(); 138 | b = page.write(array); 139 | } 140 | } 141 | } 142 | } 143 | } 144 | 145 | protected void lockRead() { this.lock.readLock().lock(); } 146 | 147 | protected void unLockRead() { this.lock.readLock().unlock(); } 148 | 149 | protected void lockWrite() { this.lock.writeLock().lock(); } 150 | 151 | protected void unLockWrite() { this.lock.writeLock().unlock(); } 152 | } 153 | -------------------------------------------------------------------------------- /src/tenndb/dist/DistPage.java: -------------------------------------------------------------------------------- 1 | package tenndb.dist; 2 | 3 | 4 | import java.nio.ByteBuffer; 5 | 6 | 7 | public class DistPage { 8 | // 9 | // public static final int PAGE_SIZE = 1024 * 1000 * 10; 10 | 11 | public static final int PAGE_SIZE = 1024 * 400; 12 | 13 | protected ByteBuffer buffer; 14 | 15 | protected int limit; 16 | 17 | protected int offset; 18 | 19 | protected final Object lock = new Object(); 20 | 21 | public DistPage(ByteBuffer buffer) { 22 | super(); 23 | this.buffer = buffer; 24 | this.limit = PAGE_SIZE; 25 | this.offset = 0; 26 | } 27 | 28 | public ByteBuffer getBuffer() { 29 | return buffer; 30 | } 31 | 32 | public void clear(){ 33 | this.offset = 0; 34 | this.buffer.clear(); 35 | } 36 | 37 | public boolean write(byte[] buff){ 38 | boolean b = false; 39 | 40 | if(null != buff && buff.length > 0){ 41 | synchronized(this.lock){ 42 | if(this.offset + buff.length < this.limit){ 43 | this.buffer.position(this.offset); 44 | this.buffer.put(buff); 45 | this.offset += buff.length; 46 | b = true; 47 | } 48 | } 49 | } 50 | 51 | return b; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/tenndb/disttest/DemoThread.java: -------------------------------------------------------------------------------- 1 | package tenndb.disttest; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import tenndb.common.SystemTime; 8 | import tenndb.dist.DistMgr; 9 | 10 | public class DemoThread extends Thread { 11 | 12 | protected int devID; 13 | protected DistMgr distMgr; 14 | 15 | public DemoThread(int devID, DistMgr distMgr) { 16 | super(); 17 | this.devID = devID; 18 | this.distMgr = distMgr; 19 | } 20 | protected static int SIZE = 100; 21 | 22 | public void run(){ 23 | int time = SystemTime.getSystemTime().currentTime(); 24 | List list = new ArrayList(); 25 | ByteBuffer buffer = ByteBuffer.allocate(25); 26 | 27 | for(int i = 0; i < SIZE; ++i){ 28 | byte[] array = new byte[25]; 29 | list.add(array); 30 | } 31 | 32 | while(true){ 33 | try{ 34 | int lng = 1200000000; 35 | int lat = 300000000; 36 | 37 | for(int i = 0; i < SIZE; ++i){ 38 | time++; 39 | String strDevID = String.valueOf(this.devID); 40 | byte[] devIDArray = new byte[10]; 41 | byte[] temp = strDevID.getBytes(); 42 | System.arraycopy(temp, 0, devIDArray, 0, 10); 43 | 44 | buffer.clear(); 45 | buffer.rewind(); 46 | buffer.put(DistMgr.TAG_DATA); 47 | buffer.put(devIDArray); //10 48 | buffer.putInt(time); //4 49 | buffer.putShort((short) 8); //2 50 | buffer.putInt(lng + i); //4 51 | buffer.putInt(lat + i); //4 52 | 53 | byte[] array = list.get(i); 54 | System.arraycopy(buffer.array(), 0, array, 0, array.length); 55 | } 56 | 57 | this.distMgr.write(list); 58 | 59 | }catch(Exception e){ 60 | System.out.println(e); 61 | }finally{ 62 | try { 63 | Thread.sleep(100); 64 | } catch (InterruptedException e) { 65 | e.printStackTrace(); 66 | } 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/tenndb/disttest/Test.java: -------------------------------------------------------------------------------- 1 | package tenndb.disttest; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import tenndb.dist.DistMgr; 7 | import tenndb.route.RouteMgr; 8 | 9 | public class Test { 10 | 11 | /** 12 | * @param args 13 | */ 14 | public static void main(String[] args) { 15 | 16 | DistMgr distMgr = new DistMgr("J:\\tennbase"); 17 | distMgr.init(); 18 | 19 | RouteMgr routeMgr = new RouteMgr("J:\\tennbase"); 20 | routeMgr.init(); 21 | 22 | int devID = 1607140000; 23 | List list = new ArrayList(); 24 | 25 | for(int i = 0; i < 20; ++i){ 26 | DemoThread thread = new DemoThread(devID + i, distMgr); 27 | list.add(thread); 28 | } 29 | 30 | for(DemoThread thread : list){ 31 | thread.start(); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/tenndb/disttest/TestDist.java: -------------------------------------------------------------------------------- 1 | package tenndb.disttest; 2 | 3 | import tenndb.dist.DistMgr; 4 | 5 | public class TestDist { 6 | 7 | /** 8 | * @param args 9 | */ 10 | public static void main(String[] args) { 11 | 12 | DistMgr distMgr = new DistMgr("J:\\tennbase"); 13 | distMgr.init(); 14 | 15 | 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/tenndb/disttest/TestFileName.java: -------------------------------------------------------------------------------- 1 | package tenndb.disttest; 2 | 3 | import java.io.File; 4 | import java.util.Date; 5 | 6 | public class TestFileName { 7 | 8 | /** 9 | * @param args 10 | */ 11 | public static void main(String[] args) { 12 | 13 | String str = "1607140000"; 14 | System.out.println(str.getBytes().length); 15 | 16 | /* for(int i = 0; i < 100; ++i){ 17 | long time = new Date().getTime(); 18 | time %= 1000; 19 | System.out.println(time + "," + String.format("%04X", time)); 20 | 21 | }*/ 22 | 23 | File dir = new File("J:\\tennbase\\dist_data"); 24 | 25 | String[] files = dir.list(); 26 | 27 | if(null != files){ 28 | for(String file : files){ 29 | System.out.println(file); 30 | } 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/tenndb/disttest/TestRoute.java: -------------------------------------------------------------------------------- 1 | package tenndb.disttest; 2 | 3 | import tenndb.dist.DistMgr; 4 | import tenndb.route.RouteMgr; 5 | 6 | public class TestRoute { 7 | 8 | /** 9 | * @param args 10 | */ 11 | public static void main(String[] args) { 12 | 13 | RouteMgr routeMgr = new RouteMgr("J:\\tennbase"); 14 | routeMgr.init(); 15 | 16 | // DistMgr distMgr = new DistMgr("J:\\tennbase"); 17 | // distMgr.init(); 18 | 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/tenndb/index/IBTree.java: -------------------------------------------------------------------------------- 1 | package tenndb.index; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.List; 5 | 6 | import tenndb.bstar.BTreeNode; 7 | import tenndb.bstar.IdxBlock; 8 | import tenndb.log.CellLogMgr; 9 | import tenndb.tx.AbortTransException; 10 | import tenndb.tx.Trans; 11 | 12 | 13 | public interface IBTree { 14 | 15 | public BTreeNode getRoot(); 16 | 17 | public void print(List strList); 18 | 19 | public String toString(); 20 | 21 | public void printNext(); 22 | 23 | public void printTreePrior(); 24 | 25 | public IdxBlock insert(int key, IdxBlock var, Trans tid, CellLogMgr logMgr) throws AbortTransException ; 26 | 27 | public IdxBlock update(int key, IdxBlock var, Trans tid, CellLogMgr logMgr) throws AbortTransException ; 28 | 29 | public IdxBlock delete(int key, Trans tid, CellLogMgr logMgr) throws AbortTransException ; 30 | 31 | public IdxBlock search(int key, Trans tid); 32 | 33 | public boolean rollback(int key, Trans tid, CellLogMgr logMgr); 34 | 35 | public boolean commit(int key, Trans tid, CellLogMgr logMgr); 36 | 37 | public BTreeNode seekNode(int key); 38 | 39 | public int count(int fromKey, int toKey); 40 | 41 | public List range(int fromKey, int toKey, boolean isInc); 42 | 43 | public void toByteBuffer(List list); 44 | 45 | } -------------------------------------------------------------------------------- /src/tenndb/index/IndexMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.index; 2 | 3 | import java.io.IOException; 4 | import java.nio.ByteBuffer; 5 | import java.util.ArrayList; 6 | import java.util.HashSet; 7 | import java.util.Hashtable; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.Set; 11 | import java.util.concurrent.atomic.AtomicInteger; 12 | 13 | import tenndb.bstar.RandomInsertBStarTree; 14 | import tenndb.bstar.BTreeNode; 15 | import tenndb.bstar.IdxBlock; 16 | import tenndb.common.ByteUtil; 17 | import tenndb.common.FileDeco; 18 | import tenndb.common.FileMgr; 19 | import tenndb.data.ByteBufferMgr; 20 | import tenndb.tx.TransMgr; 21 | 22 | public class IndexMgr { 23 | 24 | protected IBTree tree = null; 25 | 26 | protected String dbName = null; 27 | 28 | protected FileMgr fileMgr = null; 29 | 30 | protected ByteBufferMgr bufferMgr = null; 31 | 32 | protected static final String PREFIX_TEMP_INDEX = "temp_index_"; 33 | 34 | protected static final String PREFIX_SNAPSHOT_INDEX = "snapshot_index_"; 35 | 36 | protected static final String PREFIX_INDEX = "index_"; 37 | 38 | protected static final String PREFIX_BAK_INDEX = "bak_index_"; 39 | 40 | protected int lastNodeID = -1; 41 | 42 | protected AtomicInteger counter = new AtomicInteger(1); 43 | 44 | protected Map pageMap = null; 45 | 46 | protected List blockList = null; 47 | 48 | protected Set newPageList = null; 49 | 50 | protected Set dirtyPageList = null; 51 | 52 | protected TransMgr transMgr = null; 53 | 54 | 55 | 56 | 57 | public IndexMgr(String dbName, FileMgr fileMgr, TransMgr transMgr) { 58 | super(); 59 | this.dbName = dbName; 60 | this.tree = null; 61 | this.fileMgr = fileMgr; 62 | this.transMgr = transMgr; 63 | this.bufferMgr = new ByteBufferMgr(IndexPage.PAGE_SIZE); 64 | this.pageMap = new Hashtable(); 65 | this.newPageList = new HashSet(); 66 | this.dirtyPageList = new HashSet(); 67 | this.blockList = new ArrayList(); 68 | } 69 | 70 | public boolean flushBlock(IdxBlock blk){ 71 | boolean b = false; 72 | 73 | if(null != blk){ 74 | IndexPage page = this.pageMap.get(blk.getIdxPageID()); 75 | if(null != page){ 76 | long pos = page.pos + IndexPage.PAGE_HEAD_SIZE + IndexPage.PAGE_BLOCK_SIZE * blk.getIdxOffset(); 77 | ByteBuffer buff = ByteBuffer.allocate(IndexPage.PAGE_BLOCK_SIZE); 78 | byte[] array = buff.array(); 79 | // System.out.println("flushBlock " + pos); 80 | try { 81 | this.fileMgr.writeBuffer(PREFIX_SNAPSHOT_INDEX + this.dbName, array, pos); 82 | b = true; 83 | } catch (IOException e) { 84 | e.printStackTrace(); 85 | } 86 | } 87 | } 88 | return b; 89 | } 90 | 91 | public IndexPage addIndexPage(BTreeNode node, ByteBuffer buffer){ 92 | IndexPage page = null; 93 | if(null != node && null != buffer){ 94 | page = new IndexPage(node, buffer); 95 | // System.out.println("pinIndexPage " + page.pageID()); 96 | this.pageMap.put(page.pageID(), page); 97 | } 98 | return page; 99 | } 100 | 101 | public IndexPage appendNewIndexPage(BTreeNode newNode, BTreeNode oldNode){ 102 | IndexPage newPage = null; 103 | if(null != newNode){ 104 | int nodeID = this.nextNodeID(); 105 | // System.out.println("appendNewIndexPage " + nodeID); 106 | newNode.setPageID(nodeID); 107 | ByteBuffer buffer = this.bufferMgr.pinBuffer(); 108 | newPage = new IndexPage(newNode, buffer); 109 | newNode.setRefPage(newPage); 110 | this.pageMap.put(newPage.pageID(), newPage); 111 | this.newPageList.add(newPage.pageID()); 112 | } 113 | 114 | if(null != oldNode){ 115 | IndexPage oldPage = oldNode.getRefPage(); 116 | // System.out.println("dirtyPageList.1 " + oldNode.getPageID()); 117 | if(null != oldPage){ 118 | // System.out.println("dirtyPageList.2 " + oldPage.pos + ", " + oldPage.pageID()); 119 | 120 | this.dirtyPageList.add(oldPage.pageID()); 121 | } 122 | } 123 | return newPage; 124 | } 125 | 126 | public boolean flushNewPages(){ 127 | boolean b = false; 128 | if(this.newPageList.size() > 0){ 129 | byte[] array = ByteUtil.intToByte4_big(this.counter.get()); 130 | try { 131 | this.fileMgr.writeBuffer(PREFIX_SNAPSHOT_INDEX + this.dbName, array, 0); 132 | } catch (IOException e) { 133 | e.printStackTrace(); 134 | } 135 | 136 | for(Integer pid : this.newPageList){ 137 | IndexPage page = this.pageMap.get(pid); 138 | if(null != page){ 139 | page.flush(this.tree.getRoot()); 140 | long pos = this.fileMgr.append(PREFIX_SNAPSHOT_INDEX + this.dbName, page.buffer); 141 | page.setPos(pos); 142 | } 143 | 144 | // System.out.println("new " + page.pageID() + ", " + page.pos + ", " + page.node.isLeaf()); 145 | } 146 | 147 | // this.tree.printTreeNext(); 148 | // System.out.println("+++++++++++++++++++++++++++++++++++++++++++"); 149 | this.newPageList.clear(); 150 | b = true; 151 | } 152 | 153 | if(this.dirtyPageList.size() > 0){ 154 | for(Integer pid : this.dirtyPageList){ 155 | 156 | IndexPage page = this.pageMap.get(pid); 157 | if(null != page){ 158 | page.flush(this.tree.getRoot()); 159 | byte[] array = page.buffer.array(); 160 | try { 161 | this.fileMgr.writeBuffer(PREFIX_SNAPSHOT_INDEX + this.dbName, array, page.pos); 162 | // System.out.println("old " + page.pageID() + ", " + page.pos + ", " + page.node.isLeaf()); 163 | } catch (IOException e) { 164 | e.printStackTrace(); 165 | } 166 | } 167 | } 168 | 169 | this.dirtyPageList.clear(); 170 | 171 | b = true; 172 | } 173 | 174 | return b; 175 | } 176 | 177 | public IndexPage getPage(int pageID){ 178 | return this.pageMap.get(pageID); 179 | } 180 | 181 | public int nextNodeID(){ 182 | return this.counter.getAndIncrement(); 183 | } 184 | 185 | public IBTree getBTree(){ 186 | return this.tree; 187 | } 188 | 189 | public void load(){ 190 | 191 | try { 192 | List bufferList = new ArrayList(); 193 | 194 | FileDeco fd = this.fileMgr.pinFileChannel(PREFIX_INDEX + this.dbName); 195 | long len = fd.getFileChannel().size(); 196 | // System.out.println(PREFIX_INDEX + this.dbName + " len = " + len); 197 | if(len >= ByteUtil.INT_SIZE){ 198 | fd.getFileChannel().position(0); 199 | ByteBuffer buff = ByteBuffer.allocate(ByteUtil.INT_SIZE); 200 | fd.getFileChannel().read(buff); 201 | buff.rewind(); 202 | this.counter.set(buff.getInt()); 203 | 204 | // System.out.println("load counter = " + this.counter.get()); 205 | } 206 | if(len >= IndexPage.PAGE_SIZE + ByteUtil.INT_SIZE){ 207 | int size = (int) ((len - ByteUtil.INT_SIZE) / IndexPage.PAGE_SIZE); 208 | 209 | // System.out.println("load size = " + size + ", len = " + len); 210 | 211 | if(size * IndexPage.PAGE_SIZE < len){ 212 | ByteBuffer[] array = new ByteBuffer[size]; 213 | for(int i = 0; i < size; ++i){ 214 | ByteBuffer buffer = this.bufferMgr.pinBuffer(); 215 | array[i] = buffer; 216 | array[i].position(0); 217 | bufferList.add(buffer); 218 | } 219 | 220 | fd.getFileChannel().position(ByteUtil.INT_SIZE); 221 | fd.getFileChannel().read(array); 222 | } 223 | } 224 | 225 | List pageList = new ArrayList(); 226 | if(null != bufferList && bufferList.size() > 0){ 227 | 228 | this.tree = RandomInsertBStarTree.buildBTree(this.dbName, this, this.transMgr, bufferList, pageList); 229 | 230 | }else{ 231 | 232 | this.tree = new RandomInsertBStarTree(this.dbName, this, this.transMgr); 233 | /* IndexPage page = this.appendNewIndexPage(this.tree.getRoot()); 234 | pageList.add(page);*/ 235 | } 236 | 237 | if(pageList.size() > 0){ 238 | for(IndexPage page : pageList){ 239 | // System.out.println("load " + page.pageID() + ", " + page.pos); 240 | this.pageMap.put(page.pageID(), page); 241 | } 242 | } 243 | 244 | this.fileMgr.copy(PREFIX_INDEX + this.dbName, PREFIX_SNAPSHOT_INDEX + this.dbName); 245 | } catch (Exception e) { 246 | System.out.println(e); 247 | e.printStackTrace(); 248 | } 249 | 250 | 251 | } 252 | 253 | public void flush(){ 254 | 255 | if(null != this.tree){ 256 | try { 257 | List bufferList = new ArrayList(); 258 | 259 | this.tree.toByteBuffer(bufferList); 260 | 261 | if(null != bufferList && bufferList.size() > 0){ 262 | 263 | FileDeco fd = this.fileMgr.pinFileChannel(PREFIX_TEMP_INDEX + this.dbName); 264 | // ByteBuffer[] array = new ByteBuffer[bufferList.size()]; 265 | fd.getFileChannel().truncate(0); 266 | fd.getFileChannel().position(0); 267 | 268 | ByteBuffer buff = ByteBuffer.allocate(ByteUtil.INT_SIZE); 269 | buff.putInt(this.counter.get()); 270 | buff.position(0); 271 | // System.out.println("flush counter = " + this.counter.get()); 272 | fd.getFileChannel().write(buff); 273 | 274 | for(int i = 0; i < bufferList.size(); ++i){ 275 | ByteBuffer array = bufferList.get(i); 276 | // System.out.println(i + " limit = " + array[i].limit() + ", size = " + array[i].getInt(17)); 277 | array.position(0); 278 | 279 | while(array.hasRemaining()) { 280 | fd.getFileChannel().write(array); 281 | } 282 | 283 | 284 | BTreeNode.buffMgr.unpinBuffer(array); 285 | } 286 | 287 | this.fileMgr.closeFileChannel(fd); 288 | this.fileMgr.delete(PREFIX_BAK_INDEX + this.dbName); 289 | 290 | this.fileMgr.rename(PREFIX_INDEX + this.dbName, PREFIX_BAK_INDEX + this.dbName); 291 | this.fileMgr.rename(PREFIX_TEMP_INDEX + this.dbName, PREFIX_INDEX + this.dbName); 292 | } 293 | } catch (IOException e) { 294 | System.out.println(e); 295 | e.printStackTrace(); 296 | } 297 | } 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /src/tenndb/index/IndexPage.java: -------------------------------------------------------------------------------- 1 | package tenndb.index; 2 | 3 | 4 | import java.nio.ByteBuffer; 5 | 6 | import tenndb.bstar.RandomInsertBStarTree; 7 | import tenndb.bstar.BTreeNode; 8 | import tenndb.bstar.IdxBlock; 9 | import tenndb.common.ByteUtil; 10 | 11 | 12 | public class IndexPage { 13 | 14 | 15 | public static final int INDEX_HEAD_SIZE = ByteUtil.INT_SIZE; 16 | 17 | public static final int PAGE_HEAD_SIZE = ByteUtil.BYTE_SIZE + ByteUtil.INT_SIZE + ByteUtil.INT_SIZE + ByteUtil.INT_SIZE + ByteUtil.INT_SIZE + ByteUtil.INT_SIZE ; 18 | public static final int PAGE_BLOCK_SIZE = ByteUtil.INT_SIZE + ByteUtil.INT_SIZE + ByteUtil.INT_SIZE + ByteUtil.INT_SIZE + ByteUtil.BYTE_SIZE ; 19 | public static final int PAGE_BODY_SIZE = PAGE_BLOCK_SIZE * (RandomInsertBStarTree.BALANCE_SIZE + 2); 20 | //(num,key,data) x86: (1 + 4 + 40)*20=900 21 | //type + pageid + parentid + priorid + nextid + size 22 | public static final int PAGE_SIZE = PAGE_HEAD_SIZE + PAGE_BODY_SIZE; 23 | //(key + pageid + blockid + tag)*BALANCE_SIZE 48 24 | 25 | 26 | protected long pos = 0; 27 | protected BTreeNode node = null; 28 | protected ByteBuffer buffer = null; 29 | 30 | public IndexPage(BTreeNode node, ByteBuffer buffer) { 31 | super(); 32 | this.node = node; 33 | this.buffer = buffer; 34 | } 35 | 36 | public ByteBuffer getBuffer() { 37 | return buffer; 38 | } 39 | 40 | public IdxBlock getBlock(int index){ 41 | return this.node.getBlock(index); 42 | } 43 | 44 | public int size(){ 45 | return this.node.size(); 46 | } 47 | 48 | public long getPos() { 49 | return pos; 50 | } 51 | 52 | public void setPos(long pos) { 53 | this.pos = pos; 54 | } 55 | 56 | public void flush(BTreeNode rootNode){ 57 | this.node.toByteBuffer(this.buffer, rootNode); 58 | } 59 | 60 | public int pageID(){ 61 | return this.node.getPageID(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/tenndb/log/CellLogMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.log; 2 | 3 | import tenndb.bstar.IdxBlock; 4 | import tenndb.tx.Trans; 5 | 6 | public class CellLogMgr { 7 | 8 | protected final int tabID; 9 | 10 | protected final LogMgr logMgr; 11 | 12 | public CellLogMgr(int tabID, LogMgr logMgr) { 13 | super(); 14 | this.tabID = tabID; 15 | this.logMgr = logMgr; 16 | } 17 | 18 | public boolean logBegin(Trans tid){ 19 | return this.logMgr.logBegin(tid); 20 | } 21 | 22 | public boolean logRollback(Trans tid){ 23 | return this.logMgr.logRollback(tid); 24 | } 25 | 26 | public boolean logCommit(Trans tid){ 27 | return this.logMgr.logCommit(tid); 28 | } 29 | 30 | public boolean logTerminated(Trans tid){ 31 | return this.logMgr.logTerminated(tid); 32 | } 33 | 34 | public boolean logInsert(Trans tid, int key, IdxBlock newblk){ 35 | return this.logMgr.logInsert(tid, key, this.tabID, newblk); 36 | } 37 | 38 | public boolean logDelete(Trans tid, int key){ 39 | return this.logMgr.logDelete(tid, key, this.tabID); 40 | } 41 | 42 | public boolean logUpdate(Trans tid, int key, IdxBlock newblk, IdxBlock oldblk){ 43 | return this.logMgr.logUpdate(tid, key, this.tabID, newblk, oldblk); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/tenndb/log/LogMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.log; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.io.RandomAccessFile; 7 | import java.nio.ByteBuffer; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | import java.util.Hashtable; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.Set; 15 | import java.util.concurrent.locks.ReadWriteLock; 16 | import java.util.concurrent.locks.ReentrantReadWriteLock; 17 | 18 | import tenndb.base.Catalog; 19 | import tenndb.base.Cell; 20 | import tenndb.bstar.IdxBlock; 21 | import tenndb.common.FileUtil; 22 | import tenndb.tx.Trans; 23 | 24 | public class LogMgr { 25 | 26 | static final byte START_RECORD = 1; 27 | 28 | static final byte INSERT_RECORD = 2; 29 | static final byte UPDATE_RECORD = 3; 30 | static final byte DELETE_RECORD = 4; 31 | 32 | static final byte ROLLBACK_RECORD = 5; 33 | static final byte COMMIT_RECORD = 6; 34 | static final byte TERMINATED_RECORD = 7; 35 | 36 | static final byte CHECKPOINT_RECORD = 8; 37 | static final byte NO_CHECKPOINT_ID = 0; 38 | 39 | 40 | public static final int INT_SIZE = Integer.SIZE / Byte.SIZE; 41 | public static final int SHORT_SIZE = Short.SIZE / Byte.SIZE; 42 | public static final int BYTE_SIZE = Byte.SIZE / Byte.SIZE; 43 | 44 | //tid 4 45 | //type 1 46 | //state 1 47 | //new.key 4 48 | //tabId 4 49 | //new.pageid 4 50 | //new.offset 2 51 | //new.tag 1 52 | //old.pageid 4 53 | //old.offset 2 54 | //old.tag 1 55 | //prelog.pos 4 56 | 57 | public static final int LOG_BLOCK_SIZE = INT_SIZE + BYTE_SIZE + BYTE_SIZE + INT_SIZE + INT_SIZE 58 | + INT_SIZE + SHORT_SIZE + BYTE_SIZE 59 | + INT_SIZE + SHORT_SIZE + BYTE_SIZE 60 | + INT_SIZE; 61 | 62 | protected boolean logging = true; 63 | protected final File logFile; 64 | protected RandomAccessFile raf = null; 65 | private Map tidToTailLogRecord = null; 66 | 67 | protected final ReadWriteLock lock = new ReentrantReadWriteLock(false); 68 | 69 | protected static final String PREFIX_LOG = "log_"; 70 | 71 | 72 | public void recover(Catalog catalog){ 73 | List logRecordList = this.loadLogRecord(); 74 | if(null != logRecordList){ 75 | Map> undoSetMap = new HashMap>(); 76 | Map> redoSetMap = new HashMap>(); 77 | 78 | this.recoverLogRecord(logRecordList, undoSetMap, redoSetMap); 79 | 80 | System.out.println("undo.size = " + undoSetMap.size()); 81 | System.out.println("redo.size = " + redoSetMap.size()); 82 | 83 | this.redo(catalog, redoSetMap); 84 | this.undo(catalog, undoSetMap); 85 | } 86 | 87 | this.truncate(); 88 | } 89 | 90 | public void undo(Catalog catalog, Map> undoSetMap){ 91 | 92 | } 93 | 94 | public void redo(Catalog catalog, Map> redoSetMap){ 95 | Set tidSet = redoSetMap.keySet(); 96 | for(Integer tid : tidSet){ 97 | List list = redoSetMap.get(tid); 98 | if(null != list && list.size() > 0){ 99 | for(int i = list.size() - 1; i >= 0; --i){ 100 | LogRecord record = list.get(i); 101 | 102 | int tabID = record.tabId; 103 | Cell cell = catalog.getCell(tabID); 104 | if(null != cell){ 105 | if(INSERT_RECORD == record.type){ 106 | cell.recoverInsert(record.key, record.getNewPid(), record.getNewOffset()); 107 | }else if(UPDATE_RECORD == record.type){ 108 | cell.recoverUpdate(record.key, record.getNewPid(), record.getNewOffset()); 109 | }else if(DELETE_RECORD == record.type){ 110 | cell.recoverDelete(record.key); 111 | } 112 | } 113 | } 114 | } 115 | } 116 | } 117 | 118 | public void truncate(){ 119 | System.out.println("truncate.1"); 120 | if(this.logFile.exists()){ 121 | try { 122 | this.raf.close(); 123 | System.out.println("truncate.2"); 124 | this.logFile.delete(); 125 | this.raf = new RandomAccessFile(this.logFile, "rw"); 126 | } catch (IOException e) { 127 | // TODO Auto-generated catch block 128 | e.printStackTrace(); 129 | } 130 | } 131 | System.out.println("truncate.3"); 132 | } 133 | 134 | public void recoverLogRecord(List logRecordList, Map> undoSetMap, Map> redoSetMap){ 135 | 136 | Map recordMap = new HashMap(); 137 | Set undoSet = new HashSet(); 138 | Set redoSet = new HashSet(); 139 | 140 | for(int i = logRecordList.size() - 1; i >= 0 ; --i){ 141 | LogRecord record = logRecordList.get(i); 142 | if(!recordMap.containsKey(record.tid)){ 143 | if(Trans.COMMIT == record.type){ 144 | redoSet.add(record.tid); 145 | }else if(Trans.ROLLBACK == record.type){ 146 | undoSet.add(record.tid); 147 | }else if(Trans.ACTIVE == record.type){ 148 | undoSet.add(record.tid); 149 | } 150 | 151 | recordMap.put(record.tid, record.type); 152 | }else{ 153 | if(Trans.START == record.type){ 154 | undoSet.remove(record.tid); 155 | redoSet.remove(record.tid); 156 | } 157 | } 158 | 159 | if(redoSet.contains(record.tid)){ 160 | List list = redoSetMap.get(record.tid); 161 | if(null == list){ 162 | list = new ArrayList(); 163 | redoSetMap.put(record.tid, list); 164 | } 165 | list.add(record); 166 | } 167 | 168 | if(undoSet.contains(record.tid)){ 169 | List list = undoSetMap.get(record.tid); 170 | if(null == list){ 171 | list = new ArrayList(); 172 | undoSetMap.put(record.tid, list); 173 | } 174 | list.add(record); 175 | } 176 | } 177 | } 178 | 179 | public LogMgr(String cataName, String root){ 180 | File dir = new File(root); 181 | 182 | if(!dir.exists()){ 183 | FileUtil.mkDir(dir); 184 | } 185 | 186 | File file = new File(root, PREFIX_LOG + cataName); 187 | this.logFile = file; 188 | this.logging = true; 189 | this.tidToTailLogRecord = new Hashtable(); 190 | try { 191 | this.raf = new RandomAccessFile(this.logFile, "rw"); 192 | } catch (FileNotFoundException e) { 193 | e.printStackTrace(); 194 | } 195 | } 196 | 197 | public List loadLogRecord(){ 198 | List list = new ArrayList(); 199 | 200 | try{ 201 | byte[] array = new byte[LOG_BLOCK_SIZE]; 202 | ByteBuffer buff = ByteBuffer.allocate(LOG_BLOCK_SIZE); 203 | this.lockWrite(); 204 | 205 | this.raf.seek(0); 206 | 207 | while(this.raf.getFilePointer() < this.raf.length()){ 208 | this.raf.read(array); 209 | buff.flip(); 210 | buff.clear(); 211 | buff.put(array); 212 | //tid 4 213 | //type 1 214 | //state 1 215 | //new.key 4 216 | //tabId 4 217 | //new.pageid 4 218 | //new.offset 2 219 | //new.tag 1 220 | //old.pageid 4 221 | //old.offset 2 222 | //old.tag 1 223 | //prelog.pos 4 224 | buff.flip(); 225 | 226 | int tid = buff.getInt(); 227 | byte type = buff.get(); 228 | byte state = buff.get(); 229 | int key = buff.getInt(); 230 | int tabId = buff.getInt(); 231 | int newPid = buff.getInt(); 232 | short newOffset = buff.getShort(); 233 | byte newTag = buff.get(); 234 | int oldPid = buff.getInt(); 235 | short oldOffset = buff.getShort(); 236 | byte oldTag = buff.get(); 237 | int pos = buff.getInt(); 238 | 239 | LogRecord record = new LogRecord(tid, state, type, key, tabId, 240 | newPid, newOffset, newTag, 241 | oldPid, oldOffset, oldTag); 242 | record.prePos = pos; 243 | record.state = state; 244 | list.add(record); 245 | } 246 | }catch(Exception e){} 247 | finally{ 248 | this.unLockWrite(); 249 | } 250 | 251 | return list; 252 | } 253 | 254 | public boolean writeLog(LogRecord record){ 255 | boolean b = false; 256 | 257 | // this.logCache.push(record); 258 | 259 | if(null != record && record.tid > 0 && true == this.logging){ 260 | try{ 261 | this.lockWrite(); 262 | int start = (int) this.raf.length(); 263 | 264 | this.raf.seek(start); 265 | this.raf.writeInt (record.tid); 266 | this.raf.writeByte (record.type); 267 | this.raf.writeByte (record.state); 268 | this.raf.writeInt (record.key); 269 | this.raf.writeInt (record.tabId); 270 | 271 | this.raf.writeInt (record.newPid); 272 | this.raf.writeShort(record.newOffset); 273 | this.raf.writeByte (record.newTag); 274 | 275 | this.raf.writeInt (record.oldPid); 276 | this.raf.writeShort(record.oldOffset); 277 | this.raf.writeByte (record.oldTag); 278 | 279 | if(START_RECORD != record.type){ 280 | Integer pos = this.tidToTailLogRecord.get(record.tid); 281 | 282 | this.raf.writeInt(pos); 283 | 284 | }else{ 285 | this.raf.writeInt(0); 286 | } 287 | 288 | this.tidToTailLogRecord.put(record.tid, start); 289 | 290 | b = true; 291 | }catch(Exception e){} 292 | finally{ 293 | this.unLockWrite(); 294 | } 295 | } 296 | 297 | return b; 298 | } 299 | 300 | public boolean logBegin(Trans tid){ 301 | boolean b = false; 302 | 303 | if(null != tid && tid.getTransID() > 0){ 304 | LogRecord record = new LogRecord(tid.getTransID(), Trans.START, START_RECORD, 0, 0, 305 | 0, (short)0, (byte)0, 0, (short)0, (byte)0); 306 | b = this.writeLog(record); 307 | } 308 | return b; 309 | } 310 | 311 | public boolean logTerminated(Trans tid){ 312 | boolean b = false; 313 | 314 | if(null != tid && tid.getTransID() > 0){ 315 | LogRecord record = new LogRecord(tid.getTransID(), Trans.TERMINATED, TERMINATED_RECORD, 0, 0, 316 | 0, (short)0, (byte)0, 0, (short)0, (byte)0); 317 | b = this.writeLog(record); 318 | } 319 | return b; 320 | } 321 | 322 | public boolean logRollback(Trans tid){ 323 | boolean b = false; 324 | 325 | if(null != tid && tid.getTransID() > 0){ 326 | LogRecord record = new LogRecord(tid.getTransID(), Trans.ROLLBACK, ROLLBACK_RECORD, 0, 0, 327 | 0, (short)0, (byte)0, 0, (short)0, (byte)0); 328 | b = this.writeLog(record); 329 | } 330 | return b; 331 | } 332 | 333 | public boolean logCommit(Trans tid){ 334 | boolean b = false; 335 | 336 | if(null != tid && tid.getTransID() > 0){ 337 | LogRecord record = new LogRecord(tid.getTransID(), Trans.COMMIT, COMMIT_RECORD, 0, 0, 338 | 0, (short)0, (byte)0, 0, (short)0, (byte)0); 339 | b = this.writeLog(record); 340 | } 341 | return b; 342 | } 343 | 344 | public boolean logInsert(Trans tid, int key, int tabId, IdxBlock newblk){ 345 | boolean b = false; 346 | 347 | if(null != tid && tid.getTransID() > 0 && null != newblk){ 348 | LogRecord record = new LogRecord(tid.getTransID(), Trans.ACTIVE, INSERT_RECORD, key, tabId, 349 | newblk.getPageID(), (short)newblk.getOffset(), (byte)newblk.getTag(), 350 | (int)0, (short)0, (byte)0); 351 | b = this.writeLog(record); 352 | } 353 | return b; 354 | } 355 | 356 | public boolean logDelete(Trans tid, int key, int tabId){ 357 | boolean b = false; 358 | 359 | if(null != tid && tid.getTransID() > 0){ 360 | LogRecord record = new LogRecord(tid.getTransID(), Trans.ACTIVE, DELETE_RECORD, key, tabId, 361 | 0, (short)0, (byte)IdxBlock.INVALID, 362 | 0, (short)0, (byte)IdxBlock.VALID); 363 | b = this.writeLog(record); 364 | } 365 | 366 | return b; 367 | } 368 | 369 | public boolean logUpdate(Trans tid, int key, int tabId, IdxBlock newblk, IdxBlock oldblk){ 370 | boolean b = false; 371 | 372 | if(null != tid && tid.getTransID() > 0 && null != newblk && null != oldblk){ 373 | LogRecord record = new LogRecord(tid.getTransID(), Trans.ACTIVE, UPDATE_RECORD, key, tabId, 374 | newblk.getPageID(), (short)newblk.getOffset(), (byte)newblk.getTag(), 375 | oldblk.getPageID(), (short)oldblk.getOffset(), (byte)oldblk.getTag()); 376 | b = this.writeLog(record); 377 | } 378 | 379 | return b; 380 | } 381 | 382 | 383 | protected void lockRead() { this.lock.readLock().lock(); } 384 | 385 | protected void unLockRead() { this.lock.readLock().unlock(); } 386 | 387 | protected void lockWrite() { this.lock.writeLock().lock(); } 388 | 389 | protected void unLockWrite() { this.lock.writeLock().unlock(); } 390 | } 391 | -------------------------------------------------------------------------------- /src/tenndb/log/LogRecord.java: -------------------------------------------------------------------------------- 1 | package tenndb.log; 2 | 3 | public class LogRecord { 4 | 5 | //tid 4 6 | //type 1 7 | //state 1 8 | //new.key 4 9 | //tabId 4 10 | //new.pageid 4 11 | //new.offset 2 12 | //new.tag 1 13 | //old.pageid 4 14 | //old.offset 2 15 | //old.tag 1 16 | //prelog.pos 4 17 | 18 | protected int tid; 19 | protected byte type; 20 | protected byte state; 21 | protected int key; 22 | protected int tabId; 23 | protected int newPid; 24 | protected short newOffset; 25 | protected byte newTag; 26 | protected int oldPid; 27 | protected short oldOffset; 28 | protected byte oldTag; 29 | protected int prePos; 30 | 31 | public LogRecord(int tid, byte state, byte type, int key, int tabId, 32 | int newPid, short newOffset, byte newTag, 33 | int oldPid, short oldOffset, byte oldTag) { 34 | super(); 35 | this.tid = tid; 36 | this.type = type; 37 | this.state = state; 38 | this.key = key; 39 | this.tabId = tabId; 40 | this.newPid = newPid; 41 | this.newOffset = newOffset; 42 | this.newTag = newTag; 43 | this.oldPid = oldPid; 44 | this.oldOffset = oldOffset; 45 | this.oldTag = oldTag; 46 | } 47 | 48 | public int getTid() { 49 | return tid; 50 | } 51 | 52 | public byte getType() { 53 | return type; 54 | } 55 | 56 | public byte getState() { 57 | return state; 58 | } 59 | 60 | public int getKey() { 61 | return key; 62 | } 63 | 64 | public int getTabId() { 65 | return tabId; 66 | } 67 | 68 | public int getNewPid() { 69 | return newPid; 70 | } 71 | 72 | public short getNewOffset() { 73 | return newOffset; 74 | } 75 | 76 | public byte getNewTag() { 77 | return newTag; 78 | } 79 | 80 | public int getOldPid() { 81 | return oldPid; 82 | } 83 | 84 | public short getOldOffset() { 85 | return oldOffset; 86 | } 87 | 88 | public byte getOldTag() { 89 | return oldTag; 90 | } 91 | 92 | public int getPrePos() { 93 | return prePos; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/tenndb/route/RouteMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.route; 2 | 3 | import java.util.Hashtable; 4 | import java.util.Map; 5 | import java.util.concurrent.locks.ReadWriteLock; 6 | import java.util.concurrent.locks.ReentrantReadWriteLock; 7 | 8 | import tenndb.base.Cell; 9 | import tenndb.common.FileMgr; 10 | import tenndb.data.ByteBufferMgr; 11 | import tenndb.data.Colunm; 12 | import tenndb.data.DBPage; 13 | import tenndb.dist.DistMgr; 14 | import tenndb.log.LogMgr; 15 | import tenndb.thread.ImportThread; 16 | import tenndb.tx.TransMgr; 17 | 18 | 19 | public class RouteMgr { 20 | 21 | protected Cell level0 = null; 22 | 23 | protected Map level1 = null; 24 | protected Map level2 = null; 25 | 26 | protected final String root; 27 | protected final String cataName; 28 | protected final FileMgr rootMgr; 29 | protected final LogMgr logMgr; 30 | protected final TransMgr transMgr; 31 | protected final ByteBufferMgr bufMgr; 32 | 33 | protected ImportThread importThread = null; 34 | 35 | protected final ReadWriteLock lock = new ReentrantReadWriteLock(false); 36 | 37 | protected volatile boolean initialized = false; 38 | 39 | public static final String LOGS_PATH = System.getProperty("file.separator") + "logs_data"; 40 | 41 | public static final String ROUTE_PATH = System.getProperty("file.separator") + "route_data"; 42 | 43 | public static final String DATA_PATH = System.getProperty("file.separator") + "raw_data"; 44 | 45 | 46 | public RouteMgr(String root){ 47 | this.cataName = "date_route"; 48 | this.root = root; 49 | this.rootMgr = new FileMgr(this.root); 50 | 51 | this.logMgr = new LogMgr(this.cataName, this.root + LOGS_PATH); 52 | this.bufMgr = new ByteBufferMgr(DBPage.PAGE_SIZE); 53 | this.transMgr = new TransMgr(); 54 | 55 | this.level0 = new Cell(this.cataName, 0, new FileMgr(this.root + ROUTE_PATH), this.transMgr, this.logMgr); 56 | this.level1 = new Hashtable(); 57 | this.level2 = new Hashtable(); 58 | } 59 | 60 | public void init(){ 61 | if(false == this.initialized){ 62 | try{ 63 | this.lockWrite(); 64 | if(false == this.initialized){ 65 | this.level0.init(); 66 | this.importThread = new ImportThread(new FileMgr(this.root + DistMgr.DIST_PATH), this); 67 | this.importThread.start(); 68 | this.initialized = true; 69 | } 70 | }catch(Exception e){ 71 | System.out.println(e); 72 | }finally{ 73 | this.unLockWrite(); 74 | } 75 | } 76 | } 77 | 78 | public final Cell getLevel0(){ 79 | return this.level0; 80 | } 81 | 82 | public static final String data2path(String date){ 83 | String path = null; 84 | //20160701 85 | if(null != date && date.length() == 8){ 86 | path = System.getProperty("file.separator") + date.substring(0, 4) 87 | + System.getProperty("file.separator") + date.substring(4, 6) 88 | + System.getProperty("file.separator") + date.substring(6, 8) ; 89 | } 90 | 91 | return path; 92 | } 93 | 94 | public static final String dev2path(String dev){ 95 | String path = null; 96 | 97 | if(null != dev && dev.length() == 10){ 98 | path = System.getProperty("file.separator") + dev.substring(8, 10) 99 | + System.getProperty("file.separator") + dev.substring(0, 8); 100 | } 101 | 102 | return path; 103 | } 104 | 105 | public final Cell pinLevel2(String level1, String level2){ 106 | Cell cell2 = null; 107 | 108 | try{ 109 | if(null != level1 && level1.length() > 0 && null != level2 && level2.length() > 0){ 110 | String key = level1 + "_" + level2; 111 | 112 | // this.lockRead(); 113 | cell2 = this.level2.get(key); 114 | // this.unLockRead(); 115 | 116 | if(null == cell2){ 117 | Cell cell1 = this.pinLevel1(level1); 118 | if(null != cell1){ 119 | 120 | Colunm colunm = cell1.search(Colunm.hashCode(level2)); 121 | if(null == colunm){ 122 | colunm = new Colunm(level2, 1); 123 | cell1.insert(colunm.getHashCode(), colunm); 124 | } 125 | 126 | if(null != colunm){ 127 | 128 | String key2 = colunm.getKey(); 129 | if(null != key2){ 130 | String datepath = data2path(level1); 131 | String devpath = dev2path (level2); 132 | //dev2path 133 | cell2 = new Cell(key2, 0, new FileMgr(this.root + DATA_PATH + datepath + devpath), this.transMgr, this.logMgr); 134 | cell2.init(); 135 | 136 | try{ 137 | // this.unLockRead(); 138 | this.lockWrite(); 139 | this.level2.put(key, cell2); 140 | }catch(Exception e){ 141 | System.out.println(e); 142 | } 143 | finally{ 144 | this.unLockWrite(); 145 | // this.lockRead(); 146 | } 147 | } 148 | } 149 | } 150 | } 151 | } 152 | }catch(Exception e){ 153 | System.out.println(e); 154 | }finally{ 155 | // this.unLockRead(); 156 | } 157 | 158 | return cell2; 159 | } 160 | 161 | //160101 162 | public final Cell pinLevel1(String level1){ 163 | 164 | Cell cell = null; 165 | 166 | try{ 167 | if(null != level1 && level1.length() > 0){ 168 | // this.lockRead(); 169 | 170 | cell = this.level1.get(level1); 171 | if(null == cell){ 172 | Colunm colunm = this.level0.search(Colunm.hashCode(level1)); 173 | if(null == colunm){ 174 | colunm = new Colunm(level1, 1); 175 | this.level0.insert(colunm.getHashCode(), colunm); 176 | } 177 | 178 | if(null != colunm){ 179 | String key = colunm.getKey(); 180 | if(null != key){ 181 | String path = data2path(key); 182 | cell = new Cell(key, 0, new FileMgr(this.root + DATA_PATH + path), this.transMgr, this.logMgr); 183 | cell.init(); 184 | try{ 185 | // this.unLockRead(); 186 | this.lockWrite(); 187 | this.level1.put(key, cell); 188 | }catch(Exception e){ 189 | System.out.println(e); 190 | } 191 | finally{ 192 | this.unLockWrite(); 193 | // this.lockRead(); 194 | } 195 | } 196 | } 197 | } 198 | } 199 | }catch(Exception e){ 200 | System.out.println(e); 201 | }finally{ 202 | // this.unLockRead(); 203 | } 204 | return cell; 205 | } 206 | 207 | protected void lockRead() { this.lock.readLock().lock(); } 208 | 209 | protected void unLockRead() { this.lock.readLock().unlock(); } 210 | 211 | protected void lockWrite() { this.lock.writeLock().lock(); } 212 | 213 | protected void unLockWrite() { this.lock.writeLock().unlock(); } 214 | 215 | } 216 | -------------------------------------------------------------------------------- /src/tenndb/routetest/TestRoute.java: -------------------------------------------------------------------------------- 1 | package tenndb.routetest; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Hashtable; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import tenndb.base.Cell; 9 | import tenndb.common.SystemTime; 10 | import tenndb.data.Colunm; 11 | import tenndb.data.Filed; 12 | import tenndb.route.RouteMgr; 13 | 14 | public class TestRoute { 15 | 16 | /** 17 | * @param args 18 | */ 19 | public static void main(String[] args) { 20 | 21 | RouteMgr mgr = new RouteMgr("J:\\tennbase"); 22 | mgr.init(); 23 | 24 | String date = "160713"; 25 | Map map = new Hashtable(); 26 | List list = new ArrayList(); 27 | 28 | for(int i = 0; i < 3; ++i) 29 | { 30 | long dev = 1607130000 + i; 31 | String level2 = String.valueOf(dev); 32 | Cell cell2 = mgr.pinLevel2(date, level2); 33 | if(null != cell2){ 34 | map.put(cell2.getDbName(), cell2); 35 | list.add(cell2); 36 | } 37 | } 38 | 39 | int when = SystemTime.getSystemTime().currentTime(); 40 | for(int i = 1; i < 100000; ++i){ 41 | String key = String.valueOf(when + i); 42 | Colunm colunm = new Colunm(key, 1); 43 | colunm.addFiled(new Filed("var1", key + 1)); 44 | 45 | for(int t = 0; t < list.size(); ++t){ 46 | Cell cell = list.get(t); 47 | cell.insert(colunm.getHashCode(), colunm); 48 | } 49 | } 50 | 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/tenndb/test/TestAbortTransException.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | import tenndb.tx.AbortTransException; 4 | 5 | public class TestAbortTransException { 6 | 7 | public static void test() throws AbortTransException{ 8 | try{ 9 | System.out.println("test.1"); 10 | throw new AbortTransException("abort "); 11 | 12 | }catch(AbortTransException ae){ 13 | System.out.println(ae); 14 | System.out.println("test.2"); 15 | throw ae; 16 | } 17 | catch(Exception e){ 18 | System.out.println(e); 19 | System.out.println("test.3"); 20 | } 21 | finally{ 22 | System.out.println("test.4"); 23 | } 24 | } 25 | 26 | 27 | public static void main(String[] args) { 28 | 29 | try { 30 | test(); 31 | } catch (AbortTransException e) { 32 | // TODO Auto-generated catch block 33 | e.printStackTrace(); 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/tenndb/test/TestByte.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | import tenndb.common.ByteUtil; 4 | 5 | public class TestByte { 6 | 7 | /** 8 | * @param args 9 | */ 10 | public static void main(String[] args) { 11 | byte[] array = ByteUtil.intToByte4_big(123456); 12 | 13 | int n = ByteUtil.byte4ToInt_big(array, 0); 14 | System.out.println("n = " + n); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/tenndb/test/TestCell.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | import java.util.List; 4 | 5 | import tenndb.base.Cell; 6 | import tenndb.common.FileMgr; 7 | import tenndb.data.Colunm; 8 | import tenndb.tx.Trans; 9 | import tenndb.tx.TransMgr; 10 | 11 | public class TestCell { 12 | 13 | /** 14 | * @param args 15 | */ 16 | public static void main(String[] args) { 17 | 18 | TransMgr trasMgr = new TransMgr(); 19 | 20 | FileMgr fileMgr = new FileMgr("J:\\tennbase\\"); 21 | String dbName = "stu"; 22 | int dbID = 123; 23 | Cell cell = new Cell(dbName, dbID, fileMgr, trasMgr, null); 24 | 25 | cell.init(); 26 | /* 27 | for(int i = 1000; i < 2000; ++i){ 28 | int key = i; 29 | String var = i + "_hellowrold"; 30 | cell.insert(key, var); 31 | } 32 | 33 | for(int i = 2000; i < 3000; ++i){ 34 | int key = i; 35 | String var = i + "_hellowrold"; 36 | cell.insert(key, var); 37 | } 38 | 39 | for(int i = 3000; i < 4000; ++i){ 40 | int key = i; 41 | String var = i + "_hellowrold"; 42 | cell.insert(key, var); 43 | } 44 | */ 45 | Trans tid = new Trans(); 46 | /* for(int i = 0; i < 100; ++i){ 47 | int key = i; 48 | String var = i + "_hellowrold"; 49 | cell.insert(key, var, tid); 50 | cell.commit(key, tid); 51 | } 52 | */ 53 | 54 | // cell.delete(51); 55 | // TransID tid = new TransID(); 56 | 57 | for(int i = 1; i <= 100; i+=10){ 58 | Colunm var = cell.search(i, tid); 59 | System.out.println("key = " + i + ", var = " + var.getKey()); 60 | } 61 | 62 | 63 | int n1 = cell.count(33, 88); 64 | System.out.println("count = " + n1); 65 | 66 | 67 | 68 | System.out.println("++++++++++++++++++++++++++++"); 69 | 70 | List list2 = cell.range(8888, 8988, false); 71 | 72 | for(int i = 0; i < list2.size(); ++i){ 73 | System.out.println("range2 " + list2.get(i).getKey()); 74 | } 75 | 76 | cell.printTreeNext(); 77 | 78 | // reactor.print(); 79 | /* try { 80 | Thread.sleep(1000*1000); 81 | } catch (InterruptedException e) { 82 | // TODO Auto-generated catch block 83 | e.printStackTrace(); 84 | }*/ 85 | cell.flush(); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/tenndb/test/TestDBPageMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | import tenndb.bstar.IdxBlock; 4 | import tenndb.common.FileMgr; 5 | import tenndb.data.DBBlock; 6 | import tenndb.data.DBPageMgr; 7 | import tenndb.index.IBTree; 8 | import tenndb.index.IndexMgr; 9 | import tenndb.tx.AbortTransException; 10 | import tenndb.tx.Trans; 11 | import tenndb.tx.TransMgr; 12 | 13 | 14 | public class TestDBPageMgr { 15 | 16 | /** 17 | * @param args 18 | */ 19 | public static void main(String[] args) { 20 | 21 | FileMgr fileMgr = new FileMgr("J:\\tennbase\\"); 22 | 23 | String dbName = "stu"; 24 | 25 | TransMgr trasMgr = new TransMgr(); 26 | IndexMgr indexMgr = new IndexMgr(dbName, fileMgr, trasMgr); 27 | DBPageMgr dbPageMgr = new DBPageMgr(dbName, fileMgr); 28 | dbPageMgr.load(); 29 | indexMgr.load(); 30 | 31 | IBTree tree = indexMgr.getBTree(); 32 | System.out.println(tree.toString()); 33 | tree.printNext(); 34 | // Trans tid = new Trans(); 35 | for(int i = 0; i < 100; ++i){ 36 | int key = i; 37 | String str = i + "_hellowrold"; 38 | byte[] var = str.getBytes(); 39 | 40 | /* DBBlock dbblk = dbPageMgr.nextDBBlock(var); 41 | if(null != dbblk){ 42 | 43 | 44 | 45 | dbblk.setVar(var); 46 | System.out.println("pageID = " + dbblk.getPageID() + ", offset = " + dbblk.getOffset()); 47 | IdxBlock idxblk = new IdxBlock(key); 48 | idxblk.setPageID(dbblk.getPageID()); 49 | idxblk.setOffset(dbblk.getOffset()); 50 | try { 51 | tree.insert(key, idxblk, null, null); 52 | } catch (AbortTransException e) { 53 | // TODO Auto-generated catch block 54 | e.printStackTrace(); 55 | } 56 | }*/ 57 | } 58 | 59 | for(int i = 1; i < 100; i*=10){ 60 | int key = i; 61 | IdxBlock idxblk = tree.search(key, null); 62 | System.out.println(idxblk.getPageID() + ", " + idxblk.getOffset()); 63 | DBBlock dbblk = dbPageMgr.getDBBlock(idxblk.getPageID(), idxblk.getOffset()); 64 | System.out.println(key + ", " + dbblk.getColunm().getKey()); 65 | } 66 | 67 | indexMgr.flush(); 68 | dbPageMgr.flush(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/tenndb/test/TestFileMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | 4 | import java.io.IOException; 5 | 6 | import tenndb.common.FileMgr; 7 | 8 | public class TestFileMgr { 9 | 10 | /** 11 | * @param args 12 | */ 13 | public static void main(String[] args) { 14 | // TODO Auto-generated method stub 15 | //snapshot_index_stu 16 | FileMgr mgr = new FileMgr("J:\\tennbase"); 17 | byte[] buffer = new byte[4]; 18 | for(int i = 0 ; i < 4; ++i) 19 | buffer[i] = (byte) i; 20 | try{ 21 | mgr.writeBuffer("snapshot_index_stu", buffer, 0); 22 | } catch (IOException e) { 23 | e.printStackTrace(); 24 | } 25 | 26 | try { 27 | for(int i = 0 ; i < 4; ++i) 28 | buffer[i] = (byte) 0; 29 | mgr.readBuffer("snapshot_index_stu", buffer, 0); 30 | 31 | for(int i = 0 ; i < 4; ++i) 32 | System.out.println("readBuffer " + i + ", " + buffer[i]); 33 | 34 | 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/tenndb/test/TestIndexMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import tenndb.bstar.IdxBlock; 8 | import tenndb.common.FileMgr; 9 | import tenndb.index.IBTree; 10 | import tenndb.index.IndexMgr; 11 | import tenndb.tx.AbortTransException; 12 | import tenndb.tx.Trans; 13 | import tenndb.tx.TransMgr; 14 | 15 | public class TestIndexMgr { 16 | 17 | /** 18 | * @param args 19 | */ 20 | public static void main(String[] args) { 21 | 22 | TransMgr trasMgr = new TransMgr(); 23 | FileMgr fileMgr = new FileMgr("J:\\tennbase\\"); 24 | IndexMgr indexMgr = new IndexMgr("stu", fileMgr, trasMgr); 25 | indexMgr.load(); 26 | IBTree tree = indexMgr.getBTree(); 27 | // Trans tid = new Trans(); 28 | for(int i = 0; i < 100; ++i){ 29 | int key = i; 30 | IdxBlock blk = new IdxBlock(key); 31 | blk.setPageID(i); 32 | blk.setOffset(1); 33 | /* try { 34 | tree.insert(key, blk, null, null); 35 | } catch (AbortTransException e) { 36 | // TODO Auto-generated catch block 37 | e.printStackTrace(); 38 | }*/ 39 | } 40 | 41 | List bufferList = new ArrayList(); 42 | /* 43 | try{ 44 | tree.toByteBuffer(bufferList); 45 | }catch(Exception e) 46 | { 47 | System.out.println(e); 48 | }*/ 49 | 50 | System.out.println("toByteBuffer, bufferList.len = " + bufferList.size()); 51 | 52 | tree.printNext(); 53 | 54 | // indexMgr.flush(); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/tenndb/test/TestLogMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | import java.util.List; 4 | 5 | import tenndb.bstar.IdxBlock; 6 | import tenndb.log.LogMgr; 7 | import tenndb.log.LogRecord; 8 | import tenndb.tx.Trans; 9 | 10 | public class TestLogMgr { 11 | 12 | /** 13 | * @param args 14 | */ 15 | public static void main(String[] args) { 16 | 17 | LogMgr logMgr = new LogMgr("tenn", "J:\\tennbase"); 18 | 19 | Trans tid = new Trans(); 20 | 21 | logMgr.logBegin(tid); 22 | 23 | for(int i = 1; i <= 10; ++i){ 24 | IdxBlock newblk = new IdxBlock(i); 25 | newblk.setPageID(3); 26 | newblk.setOffset(i); 27 | newblk.setTag(IdxBlock.VALID); 28 | logMgr.logInsert(tid, i, 1, newblk); 29 | } 30 | 31 | for(int i = 1; i <= 10; ++i){ 32 | IdxBlock newblk = new IdxBlock(i); 33 | newblk.setPageID(3); 34 | newblk.setOffset(i); 35 | newblk.setTag(IdxBlock.VALID); 36 | 37 | IdxBlock oldblk = new IdxBlock(i); 38 | oldblk.setPageID(4); 39 | oldblk.setOffset(i); 40 | oldblk.setTag(IdxBlock.VALID); 41 | 42 | logMgr.logUpdate(tid, i, 1, newblk, oldblk); 43 | } 44 | 45 | logMgr.logCommit(tid); 46 | 47 | List list = logMgr.loadLogRecord(); 48 | 49 | if(null != list){ 50 | for(int i = 0; i < list.size(); ++i){ 51 | LogRecord record = list.get(i); 52 | 53 | System.out.println("tid = " + record.getTid() + ", type = " + record.getType() + ", key = " + record.getKey() 54 | + ", state = " + record.getState() + ", pos = " + record.getPrePos() 55 | + ", nPid = " + record.getNewPid() + ", nOffSet = " + record.getNewOffset() + ", nTag = " + record.getNewTag() 56 | + ", oPid = " + record.getOldPid() + ", oOffSet = " + record.getOldOffset() + ", oTag = " + record.getOldTag()); 57 | } 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/tenndb/test/TestRun.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | public class TestRun { 4 | 5 | /** 6 | * @param args 7 | */ 8 | public static void main(String[] args) { 9 | 10 | Runtime.getRuntime().addShutdownHook(new Thread() { 11 | public void run() { System.out.println("wwwwww"); } 12 | }); 13 | 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/tenndb/test/TestTennBase.java: -------------------------------------------------------------------------------- 1 | package tenndb.test; 2 | 3 | 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.Random; 7 | 8 | import tenndb.base.Catalog; 9 | import tenndb.base.Cell; 10 | import tenndb.base.TennBase; 11 | import tenndb.common.DateFormatUtil; 12 | import tenndb.data.Colunm; 13 | import tenndb.data.Filed; 14 | import tenndb.tx.AbortTransException; 15 | import tenndb.tx.Trans; 16 | 17 | public class TestTennBase { 18 | 19 | 20 | private static final ThreadLocal LOG_DATE_FORMAT = 21 | DateFormatUtil.threadLocalDateFormat("yyyy-MM-dd HH:mm:ss"); 22 | 23 | /** 24 | * @param args 25 | */ 26 | public static void main(String[] args) { 27 | Catalog catalog = TennBase.getCatalog(); 28 | 29 | SimpleDateFormat df = LOG_DATE_FORMAT.get(); 30 | 31 | String dbStudent = "student"; 32 | String dbDepartment = "department"; 33 | int dbStudentID = 1; 34 | int dbDepartmentID = 2; 35 | if(null != catalog){ 36 | 37 | // tid = null; 38 | 39 | catalog.addCell(dbStudent, dbStudentID); 40 | // catalog.addCell(dbDepartment); 41 | Cell cellStu = catalog.getCell(dbStudent); 42 | 43 | long t1 = System.currentTimeMillis(); 44 | 45 | // cellStu.print(); 46 | for(int i = 1; i <= 200000; ++i){ 47 | // for(int i = 100000; i >= 1; --i){ 48 | Random r = new Random(); 49 | 50 | int p = r.nextInt(10000000); 51 | // String key = "helloworld_" + p; 52 | String key = "hello_" + i; 53 | Colunm colunm = new Colunm(key, 1); 54 | colunm.addFiled(new Filed("var1", key + 1)); 55 | colunm.addFiled(new Filed("var2", key + 2)); 56 | colunm.addFiled(new Filed("var3", key + 3)); 57 | colunm.addFiled(new Filed("var4", key + 4)); 58 | colunm.addFiled(new Filed("var5", key + 5)); 59 | colunm.addFiled(new Filed("var6", key + 6)); 60 | 61 | cellStu.insert(colunm.getHashCode(), colunm); 62 | } 63 | 64 | // cellStu.print(); 65 | 66 | { 67 | int num = 0; 68 | //for(int i = 1; i <= 100000; i*=10){ 69 | for(int i = 1; i <= 200000; ++i){ 70 | String key = "hello_" + i; 71 | 72 | Colunm colunm = cellStu.search(key.hashCode()); 73 | if(null != colunm) 74 | { 75 | /* System.out.println("search" + i + " : " + colunm.getKey() + ", " + df.format(new Date(colunm.getTime()*1000L)) + ", " + colunm.getVersion() + ", " + colunm.getLen()); 76 | for(int t = 0; t < colunm.getFileds().size(); ++t){ 77 | Filed filed = colunm.getFileds().get(t); 78 | System.out.println(" " + filed.getName() + ", " + filed.getValue()); 79 | }*/ 80 | } 81 | else{ 82 | ++num; 83 | System.out.println("+++++++++++++++++++++++++++++++++ miss " + i); 84 | } 85 | } 86 | System.out.println(" miss " + num); 87 | } 88 | 89 | { 90 | Colunm str = cellStu.search(99477, null); 91 | System.out.println("search " + str); 92 | } 93 | 94 | /* Trans trans = catalog.beginTrans(); 95 | for(int i = 1; i <= 10000; ++i){ 96 | 97 | String str = i + "_helloworld"; 98 | try { 99 | cellStu.insert(i, str, trans); 100 | } catch (AbortTransException e) { 101 | System.out.println(e); 102 | } 103 | 104 | }*/ 105 | long t2 = System.currentTimeMillis(); 106 | 107 | // catalog.commit(trans); 108 | 109 | int count = 0; 110 | /* for(int i = 100001; i <= 200000; ++i){ 111 | String str = cellStu.search(i); 112 | if(null == str || str.length() == 0){ 113 | count++; 114 | } 115 | }*/ 116 | 117 | long t3 = System.currentTimeMillis(); 118 | 119 | // Cell cellDep = catalog.getCell(dbDepartment); 120 | 121 | //0123456789 122 | //abcdefghij 123 | //kmnpqrstuv 124 | //wsyz_ 125 | //35 126 | 127 | // cellStu.print(); 128 | 129 | /* { 130 | TransID tid = catalog.getTransID(); 131 | System.out.println("transID = " + tid.getTransID()); 132 | // tid = null; 133 | for(int i = 1; i <= 100; ++i){ 134 | boolean b = cellStu.insert(i, i +"_student_3", tid); 135 | System.out.println("insert.x " + b); 136 | TransID tid2 = catalog.getTransID(); 137 | boolean b2 = cellStu.insert(i, i +"_student_4", tid2); 138 | System.out.println("insert.y " + b2); 139 | catalog.commit(tid2); 140 | 141 | } 142 | 143 | catalog.commit(tid); 144 | }*/ 145 | 146 | /* for(int t = 0; t < 100; ++t) 147 | { 148 | TransID tid = catalog.beginTrans(); 149 | System.out.println("transID = " + tid.getTransID()); 150 | // tid = null; 151 | for(int i = 1; i <= 1000; ++i){ 152 | boolean b = cellStu.insert(t*100 + i, (t*100 + i) +"_student_" + (t*100 + i), tid); 153 | } 154 | 155 | catalog.commit(tid); 156 | }*/ 157 | 158 | /* { 159 | TransID tid = catalog.getTransID(); 160 | System.out.println("transID = " + tid.getTransID()); 161 | // tid = null; 162 | for(int i = 1; i <= 10; ++i){ 163 | TransID tid2 = catalog.getTransID(); 164 | cellStu.update(i, i +"_student_2", tid); 165 | cellStu.delete(i, tid2); 166 | catalog.commit(tid2); 167 | } 168 | 169 | catalog.commit(tid); 170 | }*/ 171 | 172 | /* System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); 173 | 174 | { 175 | Trans tid = catalog.beginTrans(); 176 | System.out.println("transID = " + tid.getTransID()); 177 | for(int i = 1; i <= 10; ++i){ 178 | String str = cellStu.search(i, tid); 179 | System.out.println("search" + i + " : " + str); 180 | } 181 | catalog.commit(tid); 182 | } 183 | 184 | System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");*/ 185 | /* 186 | 187 | 188 | { 189 | TransID tid = catalog.getTransID(); 190 | System.out.println("transID = " + tid.getTransID()); 191 | // tid = null; 192 | for(int i = 1; i <= 10; ++i){ 193 | cellStu.insert(i, i +"_student_2", tid); 194 | } 195 | 196 | catalog.commit(tid); 197 | } 198 | 199 | 200 | { 201 | TransID tid = catalog.getTransID(); 202 | System.out.println("transID = " + tid.getTransID()); 203 | for(int i = 1; i <= 10; ++i){ 204 | String str = cellStu.search(i, tid); 205 | System.out.println("search" + i + " : " + str); 206 | } 207 | catalog.commit(tid); 208 | } 209 | */ 210 | // catalog.flush(); 211 | 212 | // cellStu.print(); 213 | 214 | // cellDep.print(); 215 | } 216 | 217 | } 218 | 219 | } 220 | -------------------------------------------------------------------------------- /src/tenndb/thread/DistThread.java: -------------------------------------------------------------------------------- 1 | package tenndb.thread; 2 | 3 | import java.util.List; 4 | 5 | import tenndb.dist.DistPage; 6 | import tenndb.dist.DistMgr; 7 | 8 | public class DistThread extends Thread { 9 | 10 | protected DistMgr pageMgr = null; 11 | 12 | public DistThread(DistMgr pageMgr) { 13 | super(); 14 | this.pageMgr = pageMgr; 15 | } 16 | 17 | public void run(){ 18 | 19 | while(true){ 20 | try{ 21 | if(null != this.pageMgr){ 22 | List list = this.pageMgr.getAndClearUsedList(); 23 | if(null != list && list.size() > 0){ 24 | System.out.println(list.size()); 25 | for(DistPage page : list){ 26 | String fileName = this.pageMgr.newFileName(); 27 | System.out.println("fileName = " + fileName) ; 28 | this.pageMgr.flush(page, fileName); 29 | } 30 | } 31 | } 32 | }catch(Exception e){} 33 | finally{ 34 | try { 35 | Thread.sleep(3000); 36 | } catch (InterruptedException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/tenndb/thread/FlushHook.java: -------------------------------------------------------------------------------- 1 | package tenndb.thread; 2 | 3 | import java.util.Date; 4 | 5 | import tenndb.base.Cell; 6 | import tenndb.bstar.RandomInsertBStarTree; 7 | import tenndb.common.SystemTime; 8 | 9 | public class FlushHook extends Thread { 10 | 11 | protected Cell cell = null; 12 | protected int lastTime = 0; 13 | public FlushHook(Cell cell) { 14 | super(); 15 | this.cell = cell; 16 | this.lastTime = SystemTime.getSystemTime().currentTime(); 17 | } 18 | 19 | public void run(){ 20 | while(true){ 21 | try{ 22 | if(null != this.cell){ 23 | RandomInsertBStarTree tree = (RandomInsertBStarTree) this.cell.getIndex(); 24 | boolean next = false; 25 | tree.lockWrite(); 26 | next = this.cell.flushNewPages(); 27 | 28 | int current = SystemTime.getSystemTime().currentTime(); 29 | 30 | if(next || (current > (this.lastTime + 60))){ 31 | long t1 = System.currentTimeMillis(); 32 | this.cell.flush(); 33 | long t2 = System.currentTimeMillis(); 34 | System.out.println("flush, cost = " + (t2 - t1) + ", " + new Date()); 35 | this.lastTime = current; 36 | } 37 | 38 | tree.unLockWrite(); 39 | } 40 | }catch(Exception e){ 41 | System.out.println(e); 42 | } 43 | finally{ 44 | try { 45 | Thread.sleep(3000); 46 | } catch (InterruptedException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/tenndb/thread/ImportThread.java: -------------------------------------------------------------------------------- 1 | package tenndb.thread; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | 7 | import tenndb.base.Cell; 8 | import tenndb.common.ByteUtil; 9 | import tenndb.common.DateFormatUtil; 10 | import tenndb.common.FileMgr; 11 | import tenndb.dist.DistPage; 12 | import tenndb.dist.DistMgr; 13 | import tenndb.route.RouteMgr; 14 | 15 | public class ImportThread extends Thread { 16 | 17 | protected FileMgr fileMgr; 18 | protected RouteMgr routeMgr; 19 | 20 | protected final ByteBuffer buffer; 21 | protected final byte[] buff; 22 | 23 | private static final ThreadLocal LOG_DATE_FORMAT = 24 | DateFormatUtil.threadLocalDateFormat("yyyyMMdd"); 25 | 26 | public ImportThread(FileMgr fileMgr, RouteMgr routeMgr) { 27 | super(); 28 | this.fileMgr = fileMgr; 29 | this.routeMgr = routeMgr; 30 | this.buffer = ByteBuffer.allocate(DistPage.PAGE_SIZE); 31 | this.buff = new byte[DistPage.PAGE_SIZE]; 32 | } 33 | 34 | public void run(){ 35 | this.reflush(DistMgr.PREFIX_TEMP + DistMgr.PREFIX_QUEUE); 36 | 37 | while(true) 38 | { 39 | try{ 40 | this.reflush(DistMgr.PREFIX_QUEUE); 41 | }catch(Exception e){ 42 | System.out.println(e); 43 | }finally{ 44 | try { 45 | Thread.sleep(3000); 46 | } catch (InterruptedException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | } 51 | } 52 | 53 | public void reflush(String prefix){ 54 | if(null != prefix && prefix.length() > 0){ 55 | String[] files = this.fileMgr.listFiles(); 56 | if(null != files && files.length > 0){ 57 | 58 | SimpleDateFormat df = LOG_DATE_FORMAT.get(); 59 | 60 | for(String fileName : files){ 61 | 62 | if(fileName.startsWith(prefix)){ 63 | // System.out.println("fileName = " + fileName); 64 | try { 65 | this.buffer.clear(); 66 | this.fileMgr.readBuffer(fileName, this.buffer.array(), 0); 67 | 68 | /* 69 | buffer.put(devIDArray); //10 70 | buffer.putInt(time); //4 71 | buffer.putShort((short) 8);//2 72 | buffer.putInt(lng + i); //4 73 | buffer.putInt(lat + i); //4 74 | */ 75 | this.buffer.rewind(); 76 | while(buffer.remaining() > 0){ 77 | byte tag = this.buffer.get(); 78 | 79 | if(DistMgr.TAG_NULL == tag){ 80 | break; 81 | } 82 | 83 | byte[] devArray = new byte[10]; 84 | 85 | this.buffer.get(devArray); 86 | 87 | String strDevID = new String(devArray); 88 | 89 | int time = this.buffer.getInt(); 90 | int len = this.buffer.getShort(); 91 | // System.out.println("len = " + len); 92 | 93 | if(len < 0){ 94 | len += ByteUtil.SHORT_MAX_VALUE; 95 | } 96 | if(len > 0){ 97 | this.buffer.get(buff, 0, len); 98 | } 99 | 100 | String strDate = df.format(new Date(time * 1000L)); 101 | // System.out.println("pinLevel2: strDate = " + strDate + ", strDevID = " + strDevID); 102 | 103 | Cell cell = this.routeMgr.pinLevel2(strDate, strDevID); 104 | if(null != cell){ 105 | // System.out.println("insert: time = " + time + ", len = " + len); 106 | cell.insert(time, this.buff, 0, len); 107 | } 108 | } 109 | 110 | } catch (Exception e) { 111 | System.out.println(e); 112 | } 113 | 114 | // String newFileName = DistMgr.PREFIX_DELETE + fileName; 115 | 116 | this.fileMgr.delete(fileName); 117 | 118 | // break; 119 | } 120 | 121 | try { 122 | Thread.sleep(10); 123 | } catch (InterruptedException e) { 124 | e.printStackTrace(); 125 | } 126 | 127 | } 128 | } 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/tenndb/thread/ShutdownHook.java: -------------------------------------------------------------------------------- 1 | package tenndb.thread; 2 | 3 | import tenndb.base.Catalog; 4 | 5 | public class ShutdownHook extends Thread { 6 | 7 | protected Catalog catalog = null; 8 | 9 | public ShutdownHook(Catalog catalog) { 10 | super(); 11 | this.catalog = catalog; 12 | } 13 | 14 | public void run(){ 15 | System.out.println("+ShutdownHook"); 16 | this.catalog.flush(); 17 | System.out.println("-ShutdownHook"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/tenndb/threadtest/InsertThread.java: -------------------------------------------------------------------------------- 1 | package tenndb.threadtest; 2 | 3 | import tenndb.base.Cell; 4 | import tenndb.data.Colunm; 5 | import tenndb.data.Filed; 6 | 7 | public class InsertThread extends Thread { 8 | 9 | protected Cell cell; 10 | 11 | public InsertThread(Cell cell) { 12 | super(); 13 | this.cell = cell; 14 | } 15 | 16 | public void run(){ 17 | 18 | 19 | // while(true) 20 | { 21 | for(int i = 1; i <= 1000; ++i){ 22 | 23 | String key = i + "_helloworld_"; 24 | 25 | Colunm colunm = new Colunm(key, 1); 26 | colunm.addFiled(new Filed("var1", key + 1)); 27 | /* colunm.addFiled(new Filed("var2", key + 2)); 28 | colunm.addFiled(new Filed("var3", key + 3)); 29 | colunm.addFiled(new Filed("var4", key + 4)); 30 | colunm.addFiled(new Filed("var5", key + 5)); 31 | colunm.addFiled(new Filed("var6", key + 6));*/ 32 | this.cell.insert(i, colunm); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/tenndb/threadtest/TestTennBase.java: -------------------------------------------------------------------------------- 1 | package tenndb.threadtest; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import tenndb.base.Catalog; 7 | import tenndb.base.Cell; 8 | import tenndb.base.TennBase; 9 | 10 | public class TestTennBase { 11 | 12 | /** 13 | * @param args 14 | */ 15 | public static void main(String[] args) { 16 | 17 | Catalog catalog = TennBase.getCatalog(); 18 | String dbStudent = "student"; 19 | int dbStudentID = 1; 20 | catalog.addCell(dbStudent, dbStudentID); 21 | Cell cellStu = catalog.getCell(dbStudent); 22 | 23 | List list = new ArrayList(); 24 | 25 | for(int i = 0; i < 10; ++i){ 26 | InsertThread thread = new InsertThread(cellStu); 27 | list.add(thread); 28 | } 29 | 30 | for(InsertThread thread : list){ 31 | thread.start(); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/tenndb/tx/AbortTransException.java: -------------------------------------------------------------------------------- 1 | package tenndb.tx; 2 | 3 | public class AbortTransException extends Exception { 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = 4369948384114813894L; 9 | 10 | public AbortTransException(String message) { 11 | super(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/tenndb/tx/BlkID.java: -------------------------------------------------------------------------------- 1 | package tenndb.tx; 2 | 3 | import java.io.Serializable; 4 | 5 | import tenndb.index.IndexPage; 6 | 7 | public class BlkID implements Serializable { 8 | 9 | private static final long serialVersionUID = -2731980102685155241L; 10 | 11 | protected String dbName; 12 | protected int key; 13 | 14 | protected IndexPage page; 15 | protected Trans transactionID; 16 | 17 | public BlkID(String dbName, int key) { 18 | super(); 19 | this.dbName = dbName; 20 | this.key = key; 21 | } 22 | 23 | public String getDbName() { 24 | return dbName; 25 | } 26 | 27 | public void setDbName(String dbName) { 28 | this.dbName = dbName; 29 | } 30 | 31 | public void setKey(int key) { 32 | this.key = key; 33 | } 34 | 35 | public IndexPage getPage() { 36 | return page; 37 | } 38 | 39 | public void setPage(IndexPage page) { 40 | this.page = page; 41 | } 42 | 43 | public Trans getTransactionID() { 44 | return transactionID; 45 | } 46 | 47 | public void setTransactionID(Trans transactionID) { 48 | this.transactionID = transactionID; 49 | } 50 | 51 | public int getKey(){ 52 | return this.key; 53 | } 54 | 55 | public String getSeq(){ 56 | return this.dbName + "_" + this.key; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/tenndb/tx/Trans.java: -------------------------------------------------------------------------------- 1 | package tenndb.tx; 2 | 3 | import java.io.Serializable; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | public class Trans implements Serializable { 7 | 8 | private static final long serialVersionUID = -3717435910507148488L; 9 | 10 | protected static AtomicInteger _counter = new AtomicInteger(1); 11 | 12 | protected int transID = 0; 13 | 14 | protected byte state; 15 | 16 | public static final byte INVALID = 0; 17 | public static final byte START = 1; 18 | public static final byte ACTIVE = 2; 19 | public static final byte TERMINATED = 3; 20 | 21 | public static final byte COMMIT = 4; 22 | public static final byte ROLLBACK = 5; 23 | 24 | public static final byte REDO = 6; 25 | public static final byte UNDO = 7; 26 | 27 | //normal 28 | // COMMITED 29 | // START -> ACTIVE -> -> TERMINATED 30 | // ROLLBACK 31 | // 32 | 33 | //crashdown 34 | //COMMITED -> REDO 35 | //ROLLBACK -> UNDO 36 | 37 | public Trans(){ 38 | this.transID = _counter.getAndIncrement(); 39 | this.state = ACTIVE; 40 | } 41 | 42 | public int getState() { 43 | return state; 44 | } 45 | 46 | public void setState(byte state) { 47 | this.state = state; 48 | } 49 | 50 | public int getTransID(){ 51 | return this.transID; 52 | } 53 | 54 | public int hashCode(){ 55 | return this.transID; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/tenndb/tx/TransMgr.java: -------------------------------------------------------------------------------- 1 | package tenndb.tx; 2 | 3 | import java.util.ArrayList; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | import java.util.concurrent.locks.ReadWriteLock; 6 | import java.util.concurrent.locks.ReentrantReadWriteLock; 7 | 8 | 9 | public class TransMgr { 10 | 11 | protected ConcurrentHashMap blkTrans; 12 | 13 | protected ConcurrentHashMap> transBlks; 14 | 15 | protected ConcurrentHashMap transState; 16 | 17 | public TransMgr(){ 18 | 19 | this.blkTrans = new ConcurrentHashMap(); 20 | this.transBlks = new ConcurrentHashMap>(); 21 | this.transState = new ConcurrentHashMap(); 22 | } 23 | 24 | protected ReadWriteLock lock = new ReentrantReadWriteLock(false); 25 | 26 | protected void lockRead() { this.lock.readLock().lock(); } 27 | 28 | protected void unLockRead() { this.lock.readLock().unlock(); } 29 | 30 | protected void lockWrite() { this.lock.writeLock().lock(); } 31 | 32 | protected void unLockWrite() { this.lock.writeLock().unlock(); } 33 | 34 | 35 | public synchronized void delTransBlks(Trans tid){ 36 | if(null != tid){ 37 | ArrayList blkList = this.transBlks.get(tid); 38 | 39 | if(null != blkList){ 40 | for(BlkID blk : blkList){ 41 | this.blkTrans.remove(blk.getSeq()); 42 | } 43 | } 44 | 45 | this.transBlks.remove(tid); 46 | this.transState.remove(tid); 47 | } 48 | } 49 | 50 | public synchronized void setTransState(Trans tid, byte state){ 51 | if(null != tid){ 52 | this.transState.put(tid, state); 53 | } 54 | } 55 | 56 | public synchronized byte getTransState(Trans tid){ 57 | byte state = Trans.INVALID; 58 | 59 | if(null != tid){ 60 | Byte var = this.transState.get(tid); 61 | if(null != var){ 62 | state = var.byteValue(); 63 | } 64 | } 65 | return state; 66 | } 67 | 68 | public synchronized ArrayList getTransBlks(Trans tid){ 69 | ArrayList blkList = null; 70 | 71 | if(null != tid){ 72 | blkList = this.transBlks.get(tid); 73 | } 74 | return blkList; 75 | } 76 | 77 | public synchronized boolean unlockBlk(Trans tid){ 78 | boolean b = false; 79 | 80 | if(null != tid){ 81 | this.transBlks.remove(tid); 82 | ArrayList blkList = this.transBlks.get(tid); 83 | if(null != blkList && blkList.size() > 0){ 84 | for(BlkID blk : blkList){ 85 | this.blkTrans.remove(blk.getSeq()); 86 | } 87 | } 88 | b = true; 89 | } 90 | 91 | return b; 92 | } 93 | 94 | /* public synchronized boolean lockBlk(BlkID bid, Trans tid){ 95 | boolean b = false; 96 | 97 | if(null != bid && null != tid){ 98 | Trans trans = this.blkTrans.get(bid.getSeq()); 99 | if(null == trans || trans.equals(tid)){ 100 | 101 | if(null == trans){ 102 | this.blkTrans.put(bid.getSeq(), tid); 103 | } 104 | 105 | ArrayList blkList = this.transBlks.get(tid); 106 | 107 | if(null == blkList){ 108 | blkList = new ArrayList(); 109 | this.transBlks.put(tid, blkList); 110 | } 111 | boolean had = false; 112 | for(BlkID tmp : blkList){ 113 | if(tmp.getSeq().equals(bid.getSeq())){ 114 | had = true; 115 | break; 116 | } 117 | } 118 | 119 | if(false == had){ 120 | // System.out.println("lockBlk " + bid.getSeq()); 121 | blkList.add(bid); 122 | } 123 | 124 | b = true; 125 | } 126 | } 127 | 128 | return b; 129 | }*/ 130 | 131 | public synchronized boolean lockBlk(BlkID bid, Trans tid){ 132 | boolean b = false; 133 | 134 | if(null != bid && null != tid){ 135 | Trans trans = this.blkTrans.get(bid.getSeq()); 136 | if(null == trans || trans.equals(tid)){ 137 | 138 | if(null == trans){ 139 | this.blkTrans.put(bid.getSeq(), tid); 140 | } 141 | 142 | ArrayList blkList = this.transBlks.get(tid); 143 | 144 | if(null == blkList){ 145 | blkList = new ArrayList(); 146 | this.transBlks.put(tid, blkList); 147 | } 148 | blkList.add(bid); 149 | 150 | b = true; 151 | } 152 | } 153 | 154 | return b; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/tenndb/txtest/TestInsertTx.java: -------------------------------------------------------------------------------- 1 | package tenndb.txtest; 2 | 3 | import tenndb.base.Catalog; 4 | import tenndb.base.Cell; 5 | import tenndb.base.TennBase; 6 | import tenndb.data.Colunm; 7 | import tenndb.data.Filed; 8 | import tenndb.tx.AbortTransException; 9 | import tenndb.tx.Trans; 10 | 11 | public class TestInsertTx { 12 | 13 | /** 14 | * @param args 15 | */ 16 | public static void main(String[] args) { 17 | 18 | Catalog catalog = TennBase.getCatalog(); 19 | String dbStudent = "student"; 20 | int dbStudentID = 1; 21 | catalog.addCell(dbStudent, dbStudentID); 22 | Cell cellStu = catalog.getCell(dbStudent); 23 | 24 | Trans trans1 = catalog.beginTrans(); 25 | Trans trans2 = catalog.beginTrans(); 26 | /* 27 | for(int i = 1; i < 100; i+=2){ 28 | String str1 = i + "_helloworld1_"; 29 | String str2 = i+1 + "_helloworld2_"; 30 | try { 31 | cellStu.insert(i, str1, trans1); 32 | } catch (AbortTransException e) { 33 | System.out.println(e); 34 | e.printStackTrace(); 35 | } 36 | 37 | try { 38 | cellStu.insert(i+1, str2, trans2); 39 | } catch (AbortTransException e) { 40 | System.out.println(e); 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | { 46 | String str = 99 + "_helloworld2_"; 47 | try { 48 | cellStu.insert(99, str, trans2); 49 | } catch (AbortTransException e) { 50 | // TODO Auto-generated catch block 51 | e.printStackTrace(); 52 | } 53 | } 54 | 55 | { 56 | String str = 98 + "_helloworld2_"; 57 | try { 58 | cellStu.insert(98, str, trans1); 59 | } catch (AbortTransException e) { 60 | // TODO Auto-generated catch block 61 | e.printStackTrace(); 62 | } 63 | }*/ 64 | 65 | 66 | 67 | { 68 | int key = 1; 69 | String str = key + "_helloworld_1"; 70 | try { 71 | Colunm colunm = new Colunm(str, 1); 72 | colunm.addFiled(new Filed("var1", str + 1)); 73 | 74 | cellStu.insert(key, colunm, trans1); 75 | } catch (AbortTransException e) { 76 | // TODO Auto-generated catch block 77 | e.printStackTrace(); 78 | catalog.rollback(trans1); 79 | } 80 | } 81 | 82 | 83 | { 84 | int key = 2; 85 | String str = key + "_helloworld_2"; 86 | try { 87 | Colunm colunm = new Colunm(str, 1); 88 | colunm.addFiled(new Filed("var1", str + 1)); 89 | 90 | cellStu.insert(key, colunm, trans2); 91 | } catch (AbortTransException e) { 92 | // TODO Auto-generated catch block 93 | e.printStackTrace(); 94 | catalog.rollback(trans2); 95 | } 96 | } 97 | 98 | 99 | { 100 | int key = 1; 101 | String str = key + "_helloworld_2"; 102 | try { 103 | Colunm colunm = new Colunm(str, 1); 104 | colunm.addFiled(new Filed("var1", str + 1)); 105 | 106 | cellStu.insert(key, colunm, trans2); 107 | } catch (AbortTransException e) { 108 | // TODO Auto-generated catch block 109 | e.printStackTrace(); 110 | catalog.rollback(trans2); 111 | } 112 | } 113 | 114 | 115 | { 116 | int key = 2; 117 | String str = key + "_helloworld_1"; 118 | try { 119 | Colunm colunm = new Colunm(str, 1); 120 | colunm.addFiled(new Filed("var1", str + 1)); 121 | 122 | cellStu.insert(key, colunm, trans1); 123 | } catch (AbortTransException e) { 124 | // TODO Auto-generated catch block 125 | e.printStackTrace(); 126 | catalog.rollback(trans1); 127 | } 128 | } 129 | 130 | 131 | 132 | 133 | // catalog.rollback(trans); 134 | // catalog.commit(trans1); 135 | // catalog.commit(trans2); 136 | 137 | for(int i = 1; i <= 100000; ++i){ 138 | Colunm colunm = cellStu.search(i, null); 139 | if(null != colunm){ 140 | System.out.println("search" + i + " : " + colunm.getKey()); 141 | } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /简易数据库存储系统的JAVA实现.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tenn-cn/TennBase/bd67a825100b565d58f0153cbfc2f848cb298367/简易数据库存储系统的JAVA实现.ppt --------------------------------------------------------------------------------