DynamicRecord readDynamicRecord() throws IOException {
      // id+type+in_use(byte)+nr_of_bytes(int)+next_block(long)
      long id = channel.getLong();
      assert id >= 0 && id <= (1l << 36) - 1 : id + " is not a valid dynamic record id";
      int type = channel.getInt();
      byte inUseFlag = channel.get();
      boolean inUse = (inUseFlag & Record.IN_USE.byteValue()) != 0;

      DynamicRecord record = new DynamicRecord(id);
      record.setInUse(inUse, type);
      if (inUse) {
        record.setStartRecord((inUseFlag & Record.FIRST_IN_CHAIN.byteValue()) != 0);
        int nrOfBytes = channel.getInt();
        assert nrOfBytes >= 0 && nrOfBytes < ((1 << 24) - 1)
            : nrOfBytes + " is not valid for a number of bytes field of " + "a dynamic record";
        long nextBlock = channel.getLong();
        assert (nextBlock >= 0 && nextBlock <= (1l << 36 - 1))
                || (nextBlock == Record.NO_NEXT_BLOCK.intValue())
            : nextBlock + " is not valid for a next record field of " + "a dynamic record";
        record.setNextBlock(nextBlock);
        byte data[] = new byte[nrOfBytes];
        channel.get(data, nrOfBytes);
        record.setData(data);
      }
      return record;
    }
    @Override
    public boolean visitSchemaRuleCommand(Command.SchemaRuleCommand command) throws IOException {
      Collection<DynamicRecord> recordsBefore = new ArrayList<>();
      readDynamicRecords(recordsBefore, COLLECTION_DYNAMIC_RECORD_ADDER);

      Collection<DynamicRecord> recordsAfter = new ArrayList<>();
      readDynamicRecords(recordsAfter, COLLECTION_DYNAMIC_RECORD_ADDER);

      byte isCreated = channel.get();
      if (1 == isCreated) {
        for (DynamicRecord record : recordsAfter) {
          record.setCreated();
        }
      }

      // read and ignore transaction id which is not used anymore
      channel.getLong();

      SchemaRule rule =
          first(recordsAfter).inUse()
              ? readSchemaRule(recordsAfter)
              : readSchemaRule(recordsBefore);

      command.init(recordsBefore, recordsAfter, rule);
      return false;
    }
  @Test
  public void shouldReportEmptyName() throws Exception {
    // given
    LabelTokenRecord key = inUse(new LabelTokenRecord(42));
    DynamicRecord name = addLabelName(inUse(new DynamicRecord(6)));
    key.setNameId((int) name.getId());

    // when
    ConsistencyReport.LabelTokenConsistencyReport report = check(key);

    // then
    verify(report).emptyName(name);
    verifyNoMoreInteractions(report);
  }
 @Override
 public void checkReference(
     RECORD record,
     DynamicRecord name,
     CheckerEngine<RECORD, REPORT> engine,
     RecordAccess records) {
   if (!name.inUse()) {
     nameNotInUse(engine.report(), name);
   } else {
     if (name.getLength() <= 0) {
       emptyName(engine.report(), name);
     }
   }
 }
 private Collection<DynamicRecord> serialize(
     SchemaRule rule, long id, boolean inUse, boolean created) {
   RecordSerializer serializer = new RecordSerializer();
   serializer = serializer.append(rule);
   DynamicRecord record = new DynamicRecord(id);
   record.setData(serializer.serialize());
   if (created) {
     record.setCreated();
   }
   if (inUse) {
     record.setInUse(true);
   }
   return Arrays.asList(record);
 }
  @Test
  public void shouldNotReportAnythingForConsistentlyChangedRecord() throws Exception {
    // given
    LabelTokenRecord oldRecord = notInUse(new LabelTokenRecord(42));
    LabelTokenRecord newRecord = inUse(new LabelTokenRecord(42));
    DynamicRecord name = addLabelName(inUse(new DynamicRecord(6)));
    name.setData(new byte[1]);
    newRecord.setNameId((int) name.getId());

    // when
    ConsistencyReport.LabelTokenConsistencyReport report = checkChange(oldRecord, newRecord);

    // then
    verifyNoMoreInteractions(report);
  }
  @Test
  public void shouldReportProblemsWithTheNewStateWhenCheckingChanges() throws Exception {
    // given
    LabelTokenRecord oldRecord = notInUse(new LabelTokenRecord(42));
    LabelTokenRecord newRecord = inUse(new LabelTokenRecord(42));
    DynamicRecord name = addLabelName(notInUse(new DynamicRecord(6)));
    newRecord.setNameId((int) name.getId());

    // when
    ConsistencyReport.LabelTokenConsistencyReport report = checkChange(oldRecord, newRecord);

    // then
    verify(report).nameBlockNotInUse(name);
    verifyNoMoreInteractions(report);
  }
 void writeDynamicRecord(DynamicRecord record) throws IOException {
   // id+type+in_use(byte)+nr_of_bytes(int)+next_block(long)
   if (record.inUse()) {
     byte inUse = Record.IN_USE.byteValue();
     if (record.isStartRecord()) {
       inUse |= Record.FIRST_IN_CHAIN.byteValue();
     }
     channel
         .putLong(record.getId())
         .putInt(record.getType())
         .put(inUse)
         .putInt(record.getLength())
         .putLong(record.getNextBlock());
     byte[] data = record.getData();
     assert data != null;
     channel.put(data, data.length);
   } else {
     byte inUse = Record.NOT_IN_USE.byteValue();
     channel.putLong(record.getId()).putInt(record.getType()).put(inUse);
   }
 }