public Entry<InternalKey, Slice> next(int bucket, long minSeq) { if (hasNext()) { // parse the key in the block Entry<InternalKey, Slice> entry = iterator.next(); InternalKey internalKey = entry.getKey(); Preconditions.checkState( internalKey != null, "Corrupt key for %s", internalKey.getUserKey().toString(UTF_8)); if (internalKey.bucket() == bucket && internalKey.getSequenceNumber() > minSeq) { return entry; } } return null; }
private void readSst( String standby, int bucket, Position pos, int batchSize, Version v, FileQueue queue, Entrys entrys, boolean availableRollback, int deep) { // 防止调用超时,和栈溢出异常 if (deep > 50) { return; } FileMetaData file = null; if (pos.fileNumber() < 0) { file = queue.poll(); } else { file = queue.poll(pos.fileNumber()); } // 当file为null时,意味着当前的version所有sst文件已经迁移完成, // 如果存在新的version,就切换到新的version,否则切换到log模式,开始去拉去log文件的数据 if (file == null) { v.release(); pos.switchToNew(); Version snapshot = versions.getCurrent(); if (v != snapshot) { v = snapshot; v.retain(); pos.version(v.hashCode()); pos.fileNumber(-1); readSst( standby, bucket, pos, batchSize, v, new FileQueue(bucket, v, pos.maxFileNumber()), entrys, availableRollback, ++deep); } else { // 日志模式不锁定version,只锁定log文件 // log文件的锁定逻辑见DBImpl的logQ属性 pos.fileNumber(log.getFileNumber()); pos.pointer(0); pos.fileType(LOG); } return; } else { pos.fileNumber(file.getNumber()); } // 读取大于maxSeq的记录 String key = generateKey(standby, bucket); SlaveIterator si = v.iterators.get(key); if (si == null) { si = new SlaveIterator(file); } else { if (si.getFileNumber() != file.getNumber()) { si = new SlaveIterator(file); } } v.iterators.put(key, si); if (availableRollback) { if (pos.pointer() > 0) { logger.warn("{}-bucket sst happen rollback, position={}.", bucket, pos); si.seekToFirst(); } else { pos.pointer(file.getNumber()); } } long maxSeq = pos.maxSeq(); while (si.hasNext()) { Entry<InternalKey, Slice> e = si.next(bucket, maxSeq); if (e != null) { InternalKey ikey = e.getKey(); pos.curMaxSeq(ikey.getSequenceNumber()); entrys.add( new BlockEntry( ikey.getUserKey(), ValueType.VALUE.equals(ikey.getValueType()) ? e.getValue() : Slices.EMPTY_SLICE)); } if (entrys.size() > batchSize) { break; } } // 判断文件是否已经读取完成 if (!si.hasNext()) { v.iterators.remove(key); FileMetaData fmd = queue.peek(); if (fmd != null) { pos.fileNumber(fmd.getNumber()); } else { pos.fileNumber(pos.curMaxFileNumber + 1); // +1意味着该version不存在该文件 } } // 继续读取下一个文件的数据 if (entrys.size() < batchSize) { readSst(standby, bucket, pos, batchSize, v, queue, entrys, false, ++deep); } }