public String getLine(int lineNo) throws Exception { if (lineNo <= 0 || lineNo > mNumLines) { return null; } String line = null; Jedis jedis = pool_.getResource(); try { String lineNoStr = Integer.toString(lineNo); line = jedis.hget(lineNoStr, LINE_KEY); if (line == null) { RecordId lineId = getRecordId(lineNo); byte[] buffer = new byte[BLOCK_SIZE]; synchronized (mDataFile) { mDataFile.seek(lineId.pageNo() * BLOCK_SIZE); mDataFile.read(buffer); } ByteBuffer bb = ByteBuffer.wrap(buffer); int numRecords = bb.getInt(BLOCK_SIZE - INT_SIZE); int indexPos = BLOCK_SIZE - 3 * INT_SIZE; int curLineNo = lineNo - lineId.slotNo() + 1; String[] recordKeys = {PAGE_NO_KEY, SLOT_NO_KEY}; for (int i = 1; i < numRecords; i++, curLineNo++) { int offset = bb.getInt(indexPos); int len = bb.getInt(indexPos + INT_SIZE); ByteBuffer linebb = ByteBuffer.wrap(buffer, offset, len); byte[] lineBuf = new byte[linebb.remaining()]; linebb.get(lineBuf); String lineStr = new String(lineBuf); if (i == lineId.slotNo()) { line = lineStr; } // Store in cache lineNoStr = Integer.toString(curLineNo); jedis.hdel(lineNoStr, recordKeys); jedis.hset(lineNoStr, LINE_KEY, lineStr); indexPos -= 2 * INT_SIZE; } } if (line == null) { throw new Exception("LineServer: Could not find line on page"); } } catch (IOException ioe) { System.err.println("LineServer: IOException on line retrieval"); throw ioe; } finally { pool_.returnResource(jedis); } return line; }
private RecordId getRecordId(int lineNo) throws IOException { RecordId id = null; Jedis jedis = pool_.getResource(); try { int pageNo, slotNo; String lineNoStr = Integer.toString(lineNo); String pageNoStr = jedis.hget(lineNoStr, PAGE_NO_KEY); String slotNoStr = jedis.hget(lineNoStr, SLOT_NO_KEY); if (pageNoStr != null && slotNoStr != null) { id = new RecordId(Integer.parseInt(pageNoStr), Integer.parseInt(slotNoStr)); } else { // Was not cached // Read directory page containing line in question byte[] buffer = new byte[BLOCK_SIZE]; int absIndex = (lineNo - 1) * 2 * INT_SIZE; int relativeIndex = absIndex % BLOCK_SIZE; int bytesRead = 0; synchronized (mDirectoryFile) { mDirectoryFile.seek(absIndex - relativeIndex); bytesRead = mDirectoryFile.read(buffer); } ByteBuffer bb = ByteBuffer.wrap(buffer); // Cache all entries in the page int curLineNo = lineNo - relativeIndex / (2 * INT_SIZE); for (int i = 0; i < bytesRead / (2 * INT_SIZE); i++, curLineNo++) { pageNo = bb.getInt(); slotNo = bb.getInt(); if (curLineNo == lineNo) { id = new RecordId(pageNo, slotNo); } lineNoStr = Integer.toString(curLineNo); jedis.hset(lineNoStr, PAGE_NO_KEY, Integer.toString(pageNo)); jedis.hset(lineNoStr, SLOT_NO_KEY, Integer.toString(slotNo)); } } if (id == null) { throw new IOException("LineServer: Could not find record id in directory"); } } finally { pool_.returnResource(jedis); } return id; }