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); } }