Ejemplo n.º 1
0
  private int readWriteBatch(int bucket, SliceInput record, int updateSize, Entrys entries)
      throws IOException {
    List<Entry<Slice, Slice>> list = Lists.newArrayListWithCapacity(updateSize);
    int count = 0;
    while (record.isReadable()) {
      count++;
      ValueType valueType = ValueType.getValueTypeByPersistentId(record.readByte());
      if (valueType == VALUE) {
        Slice key = readLengthPrefixedBytes(record);
        Slice value = readLengthPrefixedBytes(record);
        list.add(new BlockEntry(key, value));
      } else if (valueType == DELETION) {
        Slice key = readLengthPrefixedBytes(record);
        list.add(new BlockEntry(key, Slices.EMPTY_SLICE));
      } else {
        throw new IllegalStateException("Unexpected value type " + valueType);
      }
    }

    if (count != updateSize) {
      throw new IOException(
          String.format(
              "Expected %d entries in log record but found %s entries", updateSize, entries));
    }

    int available = 0;
    for (Entry<Slice, Slice> e : list) {
      InternalKey iKey =
          new InternalKey(e.getKey(), 0, e.getValue().length() != 0 ? VALUE : DELETION);
      if (bucket == iKey.bucket()) {
        entries.add(e);
        available++;
      }
    }
    return available;
  }
Ejemplo n.º 2
0
  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);
    }
  }