📄 paged.java
字号:
/** * Increment the number of records being managed by the file */ public synchronized final void incRecordCount() { recordCount++; dirty = true; } /** * Decrement the number of records being managed by the file */ public synchronized final void decRecordCount() { recordCount--; dirty = true; } /** * The number of records being managed by the file (not pages) * @return the record count */ public synchronized final long getRecordCount() { return recordCount; } private synchronized void calculateWorkSize() { workSize = pageSize - pageHeaderSize; } public synchronized final int getWorkSize() { return workSize; } } /** * PageHeader */ public abstract class PageHeader implements Streamable { private boolean dirty = false; private byte status = UNUSED; private int keyLen = 0; private int keyHash = 0; private int dataLen = 0; private int recordLen = 0; private long nextPage = -1; public PageHeader() {} public PageHeader(DataInputStream dis) throws IOException { read(dis); } public synchronized void read(DataInputStream dis) throws IOException { status = dis.readByte(); dirty = false; if (status == UNUSED) { return; } keyLen = dis.readInt(); if (keyLen < 0) { // hack for win98/ME - see issue 564 keyLen = 0; } keyHash = dis.readInt(); dataLen = dis.readInt(); recordLen = dis.readInt(); nextPage = dis.readLong(); } public synchronized void write(DataOutputStream dos) throws IOException { dirty = false; dos.writeByte(status); dos.writeInt(keyLen); dos.writeInt(keyHash); dos.writeInt(dataLen); dos.writeInt(recordLen); dos.writeLong(nextPage); } public synchronized final boolean isDirty() { return dirty; } public synchronized final void setDirty() { dirty = true; } /** * The status of this page (UNUSED, RECORD, DELETED, etc...) * @param status the new status */ public synchronized final void setStatus(byte status) { this.status = status; dirty = true; } /** * The status of this page (UNUSED, RECORD, DELETED, etc...) * @return the status */ public synchronized final byte getStatus() { return status; } public synchronized final void setKey(Key key) { // setKey WIPES OUT the Page data setRecordLen(0); dataLen = 0; keyHash = key.getHash(); keyLen = key.getLength(); dirty = true; } /** * The length of the Key * @param keyLen the new key length */ public synchronized final void setKeyLen(int keyLen) { this.keyLen = keyLen; dirty = true; } /** * The length of the Key * @return the key length */ public synchronized final int getKeyLen() { return keyLen; } /** * The hashed value of the Key for quick comparisons * @param keyHash sets the key hash */ public synchronized final void setKeyHash(int keyHash) { this.keyHash = keyHash; dirty = true; } /** * The hashed value of the Key for quick comparisons * @return the key hash */ public synchronized final int getKeyHash() { return keyHash; } /** * The length of the Data * @param dataLen sets the data length */ public synchronized final void setDataLen(int dataLen) { this.dataLen = dataLen; dirty = true; } /** * The length of the Data * @return the data length */ public synchronized final int getDataLen() { return dataLen; } /** * The length of the Record's value * @param recordLen sets the record length */ public synchronized void setRecordLen(int recordLen) { this.recordLen = recordLen; dirty = true; } /** * The length of the Record's value * @return record length */ public synchronized final int getRecordLen() { return recordLen; } /** * The next page for this Record (if overflowed) * @param nextPage next page */ public synchronized final void setNextPage(long nextPage) { this.nextPage = nextPage; dirty = true; } /** * The next page for this Record (if overflowed) * @return next page */ public synchronized final long getNextPage() { return nextPage; } } /** * Paged file's page */ public final class Page implements Comparable<Page> { /** * This page number */ private final Long pageNum; /** * The Header for this Page */ private final PageHeader header; /** * The offset into the file that this page starts */ private final long offset; /** * The data for this page. Null if page is not loaded. */ private byte[] data; /** * The position (relative) of the Key in the data array */ private int keyPos; /** * The position (relative) of the Data in the data array */ private int dataPos; public Page(Long pageNum) { this.header = createPageHeader(); this.pageNum = pageNum; this.offset = fileHeader.headerSize + (pageNum * fileHeader.pageSize); } /** * Reads a page into the memory, once. Subsequent calls are ignored. * @throws java.io.IOException if an io error occurs */ public synchronized void read() throws IOException { if (data == null) { RandomAccessFile raf = null; try { byte[] data = new byte[fileHeader.pageSize]; raf = getDescriptor(); raf.seek(this.offset); raf.read(data); // Read in the header ByteArrayInputStream bis = new ByteArrayInputStream(data); this.header.read(new DataInputStream(bis)); this.keyPos = fileHeader.pageHeaderSize; this.dataPos = this.keyPos + this.header.keyLen; // Successfully read all the data this.data = data; } finally { putDescriptor(raf); } } } /** * Writes out the header into the this.data, and adds a page to the set of * dirty pages. * @throws java.io.IOException if an io error occurs */ public void write() throws IOException { // Write out the header into the this.data synchronized (this) { ByteArrayOutputStream bos = new ByteArrayOutputStream(fileHeader.getPageHeaderSize()); header.write(new DataOutputStream(bos)); byte[] b = bos.toByteArray(); System.arraycopy(b, 0, data, 0, b.length); } // Add to the list of dirty pages Paged.this.addDirty(this); } /** * Flushes content of the dirty page into the file * @throws java.io.IOException if an io error occurs */ public synchronized void flush() throws IOException { RandomAccessFile raf = null; try { raf = getDescriptor(); if (this.offset >= raf.length()) { // Grow the file long o = (fileHeader.headerSize + ((fileHeader.totalCount * 3) / 2) * fileHeader.pageSize) + (fileHeader.pageSize - 1); raf.seek(o); raf.writeByte(0); } raf.seek(this.offset); raf.write(this.data); if (sync) { raf.getFD().sync(); } } finally { putDescriptor(raf); } } // No synchronization - pageNum is final public Long getPageNum() { return this.pageNum; } // No synchronization - header is final public PageHeader getPageHeader() { return this.header; } public synchronized void setKey(Key key) { header.setKey(key); // Insert the key into the data array. key.copyTo(this.data, this.keyPos); // Set the start of data to skip over the key. this.dataPos = this.keyPos + header.keyLen; } public synchronized Key getKey() { if (header.keyLen > 0) { return new Key(this.data, this.keyPos, header.keyLen); } else { return null; } } public synchronized void streamTo(OutputStream os) throws IOException { if (header.dataLen > 0) { os.write(this.data, this.dataPos, header.dataLen); } } public synchronized void streamFrom(InputStream is) throws IOException { int avail = is.available(); header.dataLen = fileHeader.workSize - header.keyLen; if (avail < header.dataLen) { header.dataLen = avail; } if (header.dataLen > 0) { is.read(this.data, this.keyPos + header.keyLen, header.dataLen); } } // No synchronization: pageNum is final. public int compareTo(Page o) { return (int) (this.pageNum - o.pageNum); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -