📄 paged.java
字号:
public synchronized void write(RandomAccessFile raf) throws IOException { raf.writeShort(headerSize); raf.writeInt(pageSize); raf.writeLong(pageCount); raf.writeLong(totalCount); raf.writeLong(firstFreePage); raf.writeLong(lastFreePage); raf.writeByte(pageHeaderSize); raf.writeShort(maxKeySize); raf.writeLong(recordCount); } public synchronized final void setDirty() { dirty = true; } public synchronized final boolean isDirty() { return dirty; } /** * The size of the FileHeader. Usually 1 OS Page. * This method should be called only while initializing Paged, not during normal processing. */ public synchronized final void setHeaderSize(short headerSize) { this.headerSize = headerSize; dirty = true; } /** The size of the FileHeader. Usually 1 OS Page */ public synchronized final short getHeaderSize() { return headerSize; } /** * The size of a page. Usually a multiple of a FS block. * This method should be called only while initializing Paged, not during normal processing. */ public synchronized final void setPageSize(int pageSize) { this.pageSize = pageSize; calculateWorkSize(); dirty = true; } /** The size of a page. Usually a multiple of a FS block */ public synchronized final int getPageSize() { return pageSize; } /** * The number of pages in primary storage. * This method should be called only while initializing Paged, not during normal processing. */ public synchronized final void setPageCount(long pageCount) { this.pageCount = pageCount; dirty = true; } /** The number of pages in primary storage */ public synchronized final long getPageCount() { return pageCount; } /** * The number of total pages in the file. * This method should be called only while initializing Paged, not during normal processing. */ public synchronized final void setTotalCount(long totalCount) { this.totalCount = totalCount; dirty = true; } public synchronized final long incTotalCount() { dirty = true; return this.totalCount++; } /** The number of total pages in the file */ public synchronized final long getTotalCount() { return totalCount; } /** The first free page in unused secondary space */ public synchronized final void setFirstFreePage(long firstFreePage) { this.firstFreePage = firstFreePage; dirty = true; } /** The first free page in unused secondary space */ public synchronized final long getFirstFreePage() { return firstFreePage; } /** The last free page in unused secondary space */ public synchronized final void setLastFreePage(long lastFreePage) { this.lastFreePage = lastFreePage; dirty = true; } /** The last free page in unused secondary space */ public synchronized final long getLastFreePage() { return lastFreePage; } /** * Set the size of a page header. * * Normally, 64 is sufficient. */ public synchronized final void setPageHeaderSize(byte pageHeaderSize) { this.pageHeaderSize = pageHeaderSize; calculateWorkSize(); dirty = true; } /** * Get the size of a page header. * * Normally, 64 is sufficient */ public synchronized final byte getPageHeaderSize() { return pageHeaderSize; } /** * Set the maximum number of bytes a key can be. * * Normally, 256 is good */ public synchronized final void setMaxKeySize(short maxKeySize) { this.maxKeySize = maxKeySize; dirty = true; } /** * Get the maximum number of bytes. * * Normally, 256 is good. */ public synchronized final short getMaxKeySize() { return maxKeySize; } /** 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) */ 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...) */ public synchronized final void setStatus(byte status) { this.status = status; dirty = true; } /** The status of this page (UNUSED, RECORD, DELETED, etc...) */ 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 */ public synchronized final void setKeyLen(int keyLen) { this.keyLen = keyLen; dirty = true; } /** The length of the Key */ public synchronized final int getKeyLen() { return keyLen; } /** The hashed value of the Key for quick comparisons */ public synchronized final void setKeyHash(int keyHash) { this.keyHash = keyHash; dirty = true; } /** The hashed value of the Key for quick comparisons */ public synchronized final int getKeyHash() { return keyHash; } /** The length of the Data */ public synchronized final void setDataLen(int dataLen) { this.dataLen = dataLen; dirty = true; } /** The length of the Data */ public synchronized final int getDataLen() { return dataLen; } /** The length of the Record's value */ public synchronized void setRecordLen(int recordLen) { this.recordLen = recordLen; dirty = true; } /** The length of the Record's value */ public synchronized final int getRecordLen() { return recordLen; } /** The next page for this Record (if overflowed) */ public synchronized final void setNextPage(long nextPage) { this.nextPage = nextPage; dirty = true; } /** The next page for this Record (if overflowed) */ public synchronized final long getNextPage() { return nextPage; } } /** * Paged file's page */ public final class Page implements Comparable { /** * 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.longValue() * fileHeader.pageSize); } /** * Reads a page into the memory, once. Subsequent calls are ignored. */ 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. */ 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 */ 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(Object o) { return (int) (this.pageNum.longValue() - ((Page) o).pageNum.longValue()); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -