@Override public boolean visitLabelTokenCommand(Command.LabelTokenCommand command) throws IOException { // id+in_use(byte)+type_blockId(int)+nr_type_records(int) int id = channel.getInt(); byte inUseFlag = channel.get(); boolean inUse = false; if ((inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue()) { inUse = true; } else if (inUseFlag != Record.NOT_IN_USE.byteValue()) { throw new IOException("Illegal in use flag: " + inUseFlag); } LabelTokenRecord record = new LabelTokenRecord(id); record.setInUse(inUse); record.setNameId(channel.getInt()); int nrTypeRecords = channel.getInt(); for (int i = 0; i < nrTypeRecords; i++) { DynamicRecord dr = readDynamicRecord(); if (dr == null) { return true; } record.addNameRecord(dr); } command.init(record); return false; }
@Override public boolean visitRelationshipCommand(Command.RelationshipCommand command) throws IOException { RelationshipRecord record = command.getRecord(); byte flags = bitFlags( bitFlag(record.inUse(), Record.IN_USE.byteValue()), bitFlag(record.isCreated(), Record.CREATED_IN_TX)); channel.put(NeoCommandType.REL_COMMAND); channel.putLong(record.getId()); channel.put(flags); if (record.inUse()) { channel .putLong(record.getFirstNode()) .putLong(record.getSecondNode()) .putInt(record.getType()) .putLong(record.getFirstPrevRel()) .putLong(record.getFirstNextRel()) .putLong(record.getSecondPrevRel()) .putLong(record.getSecondNextRel()) .putLong(record.getNextProp()) .put( (byte) ((record.isFirstInFirstChain() ? 1 : 0) | (record.isFirstInSecondChain() ? 2 : 0))); } else { channel.putInt(record.getType()); } return false; }
private void writePropertyRecord(PropertyRecord record) throws IOException { byte inUse = record.inUse() ? Record.IN_USE.byteValue() : Record.NOT_IN_USE.byteValue(); if (record.getRelId() != -1) { // Here we add 2, i.e. set the second lsb. inUse += Record.REL_PROPERTY.byteValue(); } channel.put(inUse); // 1 channel.putLong(record.getNextProp()).putLong(record.getPrevProp()); // 8 + 8 long nodeId = record.getNodeId(); long relId = record.getRelId(); if (nodeId != -1) { channel.putLong(nodeId); // 8 or } else if (relId != -1) { channel.putLong(relId); // 8 or } else { // means this records value has not changed, only place in // prop chain channel.putLong(-1); // 8 } channel.put((byte) record.numberOfProperties()); // 1 for (PropertyBlock block : record) { assert block.getSize() > 0 : record + " seems kinda broken"; writePropertyBlock(block); } writeDynamicRecords(record.getDeletedRecords()); }
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; }
private NodeRecord readNodeRecord(long id) throws IOException { byte inUseFlag = channel.get(); boolean inUse = false; if (inUseFlag == Record.IN_USE.byteValue()) { inUse = true; } else if (inUseFlag != Record.NOT_IN_USE.byteValue()) { throw new IOException("Illegal in use flag: " + inUseFlag); } NodeRecord record; if (inUse) { record = new NodeRecord(id, false, channel.getLong(), channel.getLong()); // labels long labelField = channel.getLong(); Collection<DynamicRecord> dynamicLabelRecords = new ArrayList<>(); readDynamicRecords(dynamicLabelRecords, COLLECTION_DYNAMIC_RECORD_ADDER); record.setLabelField(labelField, dynamicLabelRecords); } else { record = new NodeRecord( id, false, Record.NO_NEXT_RELATIONSHIP.intValue(), Record.NO_NEXT_PROPERTY.intValue()); } record.setInUse(inUse); return record; }
private PropertyRecord readPropertyRecord(long id) throws IOException { // in_use(byte)+type(int)+key_indexId(int)+prop_blockId(long)+ // prev_prop_id(long)+next_prop_id(long) PropertyRecord record = new PropertyRecord(id); byte inUseFlag = channel.get(); // 1 long nextProp = channel.getLong(); // 8 long prevProp = channel.getLong(); // 8 record.setNextProp(nextProp); record.setPrevProp(prevProp); boolean inUse = false; if ((inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue()) { inUse = true; } boolean nodeProperty = true; if ((inUseFlag & Record.REL_PROPERTY.byteValue()) == Record.REL_PROPERTY.byteValue()) { nodeProperty = false; } long primitiveId = channel.getLong(); // 8 if (primitiveId != -1 && nodeProperty) { record.setNodeId(primitiveId); } else if (primitiveId != -1) { record.setRelId(primitiveId); } int nrPropBlocks = channel.get(); assert nrPropBlocks >= 0; if (nrPropBlocks > 0) { record.setInUse(true); } while (nrPropBlocks-- > 0) { PropertyBlock block = readPropertyBlock(); if (block == null) { return null; } record.addPropertyBlock(block); } if (readDynamicRecords(record, PROPERTY_DELETED_DYNAMIC_RECORD_ADDER) == -1) { return null; } if ((inUse && !record.inUse()) || (!inUse && record.inUse())) { throw new IllegalStateException( "Weird, inUse was read in as " + inUse + " but the record is " + record); } return record; }
@Override public boolean visitLabelTokenCommand(Command.LabelTokenCommand command) throws IOException { LabelTokenRecord record = command.getRecord(); // id+in_use(byte)+type_blockId(int)+nr_type_records(int) byte inUse = record.inUse() ? Record.IN_USE.byteValue() : Record.NOT_IN_USE.byteValue(); channel.put(NeoCommandType.LABEL_KEY_COMMAND); channel.putInt(record.getId()).put(inUse).putInt(record.getNameId()); writeDynamicRecords(record.getNameRecords()); return false; }
@Override public boolean visitRelationshipGroupCommand(Command.RelationshipGroupCommand command) throws IOException { long id = channel.getLong(); byte inUseByte = channel.get(); boolean inUse = inUseByte == Record.IN_USE.byteValue(); if (inUseByte != Record.IN_USE.byteValue() && inUseByte != Record.NOT_IN_USE.byteValue()) { throw new IOException("Illegal in use flag: " + inUseByte); } int type = channel.getShort(); RelationshipGroupRecord record = new RelationshipGroupRecord(id, type); record.setInUse(inUse); record.setNext(channel.getLong()); record.setFirstOut(channel.getLong()); record.setFirstIn(channel.getLong()); record.setFirstLoop(channel.getLong()); record.setOwningNode(channel.getLong()); command.init(record); return false; }
@Override public boolean visitRelationshipCommand(Command.RelationshipCommand command) throws IOException { long id = channel.getLong(); byte inUseFlag = channel.get(); boolean inUse = false; if ((inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue()) { inUse = true; } else if ((inUseFlag & Record.IN_USE.byteValue()) != Record.NOT_IN_USE.byteValue()) { throw new IOException("Illegal in use flag: " + inUseFlag); } RelationshipRecord record; if (inUse) { record = new RelationshipRecord(id, channel.getLong(), channel.getLong(), channel.getInt()); record.setInUse(inUse); record.setFirstPrevRel(channel.getLong()); record.setFirstNextRel(channel.getLong()); record.setSecondPrevRel(channel.getLong()); record.setSecondNextRel(channel.getLong()); record.setNextProp(channel.getLong()); /* * Logs for version 2.0 do not contain the proper values for the following two flags. Also, * the defaults won't do, because the pointers for prev in the fist record will not be interpreted * properly. So we need to set the flags explicitly here. * * Note that this leaves the prev field for the first record in the chain having a value of -1, * which is not correct, as it should contain the relationship count instead. However, we cannot * determine this value from the contents of the log alone. */ record.setFirstInFirstChain( record.getFirstPrevRel() == Record.NO_PREV_RELATIONSHIP.intValue()); record.setFirstInSecondChain( record.getSecondPrevRel() == Record.NO_PREV_RELATIONSHIP.intValue()); } else { record = new RelationshipRecord(id, -1, -1, -1); record.setInUse(false); } command.init(record); return false; }
private boolean writeNodeRecord(NodeRecord record) throws IOException { byte inUse = record.inUse() ? Record.IN_USE.byteValue() : Record.NOT_IN_USE.byteValue(); channel.put(inUse); if (record.inUse()) { channel.put(record.isDense() ? (byte) 1 : (byte) 0); channel.putLong(record.getNextRel()).putLong(record.getNextProp()); channel.putLong(record.getLabelField()); } // Always write dynamic label records because we want to know which ones have been deleted // especially if the node has been deleted. writeDynamicRecords(record.getDynamicLabelRecords()); return false; }
@Override public boolean visitPropertyKeyTokenCommand(Command.PropertyKeyTokenCommand command) throws IOException { // id+in_use(byte)+count(int)+key_blockId(int) int id = channel.getInt(); byte inUseFlag = channel.get(); boolean inUse = false; if ((inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue()) { inUse = true; } else if (inUseFlag != Record.NOT_IN_USE.byteValue()) { throw new IOException("Illegal in use flag: " + inUseFlag); } PropertyKeyTokenRecord record = new PropertyKeyTokenRecord(id); record.setInUse(inUse); record.setPropertyCount(channel.getInt()); record.setNameId(channel.getInt()); int recordNr = readDynamicRecords(record, PROPERTY_INDEX_DYNAMIC_RECORD_ADDER); if (recordNr == -1) { return true; } command.init(record); return false; }
@Override public boolean visitPropertyKeyTokenCommand(Command.PropertyKeyTokenCommand command) throws IOException { PropertyKeyTokenRecord record = command.getRecord(); // id+in_use(byte)+count(int)+key_blockId(int)+nr_key_records(int) byte inUse = record.inUse() ? Record.IN_USE.byteValue() : Record.NOT_IN_USE.byteValue(); channel.put(NeoCommandType.PROP_INDEX_COMMAND); channel.putInt(record.getId()); channel.put(inUse); channel.putInt(record.getPropertyCount()).putInt(record.getNameId()); if (record.isLight()) { channel.putInt(0); } else { writeDynamicRecords(record.getNameRecords()); } return false; }
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); } }