use of org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord in project neo4j by neo4j.
the class TransactionRecordState method extractCommands.
@Override
public void extractCommands(Collection<StorageCommand> commands) throws TransactionFailureException {
assert !prepared : "Transaction has already been prepared";
integrityValidator.validateTransactionStartKnowledge(lastCommittedTxWhenTransactionStarted);
int noOfCommands = recordChangeSet.changeSize() + (neoStoreRecord != null ? neoStoreRecord.changeSize() : 0);
for (RecordProxy<Integer, LabelTokenRecord, Void> record : recordChangeSet.getLabelTokenChanges().changes()) {
commands.add(new Command.LabelTokenCommand(record.getBefore(), record.forReadingLinkage()));
}
for (RecordProxy<Integer, RelationshipTypeTokenRecord, Void> record : recordChangeSet.getRelationshipTypeTokenChanges().changes()) {
commands.add(new Command.RelationshipTypeTokenCommand(record.getBefore(), record.forReadingLinkage()));
}
for (RecordProxy<Integer, PropertyKeyTokenRecord, Void> record : recordChangeSet.getPropertyKeyTokenChanges().changes()) {
commands.add(new Command.PropertyKeyTokenCommand(record.getBefore(), record.forReadingLinkage()));
}
// Collect nodes, relationships, properties
Command[] nodeCommands = EMPTY_COMMANDS;
int skippedCommands = 0;
if (recordChangeSet.getNodeRecords().changeSize() > 0) {
nodeCommands = new Command[recordChangeSet.getNodeRecords().changeSize()];
int i = 0;
for (RecordProxy<Long, NodeRecord, Void> change : recordChangeSet.getNodeRecords().changes()) {
NodeRecord record = prepared(change, nodeStore);
integrityValidator.validateNodeRecord(record);
nodeCommands[i++] = new Command.NodeCommand(change.getBefore(), record);
}
Arrays.sort(nodeCommands, COMMAND_SORTER);
}
Command[] relCommands = EMPTY_COMMANDS;
if (recordChangeSet.getRelRecords().changeSize() > 0) {
relCommands = new Command[recordChangeSet.getRelRecords().changeSize()];
int i = 0;
for (RecordProxy<Long, RelationshipRecord, Void> change : recordChangeSet.getRelRecords().changes()) {
relCommands[i++] = new Command.RelationshipCommand(change.getBefore(), prepared(change, relationshipStore));
}
Arrays.sort(relCommands, COMMAND_SORTER);
}
Command[] propCommands = EMPTY_COMMANDS;
if (recordChangeSet.getPropertyRecords().changeSize() > 0) {
propCommands = new Command[recordChangeSet.getPropertyRecords().changeSize()];
int i = 0;
for (RecordProxy<Long, PropertyRecord, PrimitiveRecord> change : recordChangeSet.getPropertyRecords().changes()) {
propCommands[i++] = new Command.PropertyCommand(change.getBefore(), prepared(change, propertyStore));
}
Arrays.sort(propCommands, COMMAND_SORTER);
}
Command[] relGroupCommands = EMPTY_COMMANDS;
if (recordChangeSet.getRelGroupRecords().changeSize() > 0) {
relGroupCommands = new Command[recordChangeSet.getRelGroupRecords().changeSize()];
int i = 0;
for (RecordProxy<Long, RelationshipGroupRecord, Integer> change : recordChangeSet.getRelGroupRecords().changes()) {
if (change.isCreated() && !change.forReadingLinkage().inUse()) {
/*
* This is an edge case that may come up and which we must handle properly. Relationship groups are
* not managed by the tx state, since they are created as side effects rather than through
* direct calls. However, they differ from say, dynamic records, in that their management can happen
* through separate code paths. What we are interested in here is the following scenario.
* 0. A node has one less relationship that is required to transition to dense node. The relationships
* it has belong to at least two different types
* 1. In the same tx, a relationship is added making the node dense and all the relationships of a type
* are removed from that node. Regardless of the order these operations happen, the creation of the
* relationship (and the transition of the node to dense) will happen first.
* 2. A relationship group will be created because of the transition to dense and then deleted because
* all the relationships it would hold are no longer there. This results in a relationship group
* command that appears in the tx as not in use. Depending on the final order of operations, this
* can end up using an id that is higher than the highest id seen so far. This may not be a problem
* for a single instance, but it can result in errors in cases where transactions are applied
* externally, such as backup or HA.
*
* The way we deal with this issue here is by not issuing a command for that offending record. This is
* safe, since the record is not in use and never was, so the high id is not necessary to change and
* the store remains consistent.
*/
skippedCommands++;
continue;
}
relGroupCommands[i++] = new Command.RelationshipGroupCommand(change.getBefore(), prepared(change, relationshipGroupStore));
}
relGroupCommands = i < relGroupCommands.length ? Arrays.copyOf(relGroupCommands, i) : relGroupCommands;
Arrays.sort(relGroupCommands, COMMAND_SORTER);
}
addFiltered(commands, Mode.CREATE, propCommands, relCommands, relGroupCommands, nodeCommands);
addFiltered(commands, Mode.UPDATE, propCommands, relCommands, relGroupCommands, nodeCommands);
addFiltered(commands, Mode.DELETE, propCommands, relCommands, relGroupCommands, nodeCommands);
if (neoStoreRecord != null) {
for (RecordProxy<Long, NeoStoreRecord, Void> change : neoStoreRecord.changes()) {
commands.add(new Command.NeoStoreCommand(change.getBefore(), change.forReadingData()));
}
}
for (RecordProxy<Long, SchemaRecord, SchemaRule> change : recordChangeSet.getSchemaRuleChanges().changes()) {
integrityValidator.validateSchemaRule(change.getAdditionalData());
commands.add(new Command.SchemaRuleCommand(change.getBefore(), change.forChangingData(), change.getAdditionalData()));
}
assert commands.size() == noOfCommands - skippedCommands : format("Expected %d final commands, got %d " + "instead, with %d skipped", noOfCommands, commands.size(), skippedCommands);
prepared = true;
}
use of org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord in project neo4j by neo4j.
the class PhysicalLogCommandReaderV3_0_2 method readPropertyKeyTokenRecord.
private PropertyKeyTokenRecord readPropertyKeyTokenRecord(int id, ReadableChannel channel) throws IOException {
// in_use(byte)+count(int)+key_blockId(int)
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());
if (readDynamicRecords(channel, record, PROPERTY_INDEX_DYNAMIC_RECORD_ADDER) == -1) {
return null;
}
return record;
}
use of org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord in project neo4j by neo4j.
the class PhysicalLogCommandReaderV2_2 method visitPropertyKeyTokenCommand.
private Command visitPropertyKeyTokenCommand(ReadableChannel channel) 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());
if (readDynamicRecords(channel, record, PROPERTY_INDEX_DYNAMIC_RECORD_ADDER) == -1) {
return null;
}
return new Command.PropertyKeyTokenCommand(null, record);
}
use of org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord in project neo4j by neo4j.
the class WriteTransactionCommandOrderingTest method injectAllPossibleCommands.
private TransactionRecordState injectAllPossibleCommands() {
RecordChangeSet recordChangeSet = mock(RecordChangeSet.class);
RecordChanges<Integer, LabelTokenRecord, Void> labelTokenChanges = mock(RecordChanges.class);
RecordChanges<Integer, RelationshipTypeTokenRecord, Void> relationshipTypeTokenChanges = mock(RecordChanges.class);
RecordChanges<Integer, PropertyKeyTokenRecord, Void> propertyKeyTokenChanges = mock(RecordChanges.class);
RecordChanges<Long, NodeRecord, Void> nodeRecordChanges = mock(RecordChanges.class);
RecordChanges<Long, RelationshipRecord, Void> relationshipRecordChanges = mock(RecordChanges.class);
RecordChanges<Long, PropertyRecord, PrimitiveRecord> propertyRecordChanges = mock(RecordChanges.class);
RecordChanges<Long, RelationshipGroupRecord, Integer> relationshipGroupChanges = mock(RecordChanges.class);
RecordChanges<Long, SchemaRecord, SchemaRule> schemaRuleChanges = mock(RecordChanges.class);
when(recordChangeSet.getLabelTokenChanges()).thenReturn(labelTokenChanges);
when(recordChangeSet.getRelationshipTypeTokenChanges()).thenReturn(relationshipTypeTokenChanges);
when(recordChangeSet.getPropertyKeyTokenChanges()).thenReturn(propertyKeyTokenChanges);
when(recordChangeSet.getNodeRecords()).thenReturn(nodeRecordChanges);
when(recordChangeSet.getRelRecords()).thenReturn(relationshipRecordChanges);
when(recordChangeSet.getPropertyRecords()).thenReturn(propertyRecordChanges);
when(recordChangeSet.getRelGroupRecords()).thenReturn(relationshipGroupChanges);
when(recordChangeSet.getSchemaRuleChanges()).thenReturn(schemaRuleChanges);
List<RecordProxy<Long, NodeRecord, Void>> nodeChanges = new LinkedList<>();
RecordChange<Long, NodeRecord, Void> deletedNode = mock(RecordChange.class);
when(deletedNode.getBefore()).thenReturn(inUseNode());
when(deletedNode.forReadingLinkage()).thenReturn(missingNode());
nodeChanges.add(deletedNode);
RecordChange<Long, NodeRecord, Void> createdNode = mock(RecordChange.class);
when(createdNode.getBefore()).thenReturn(missingNode());
when(createdNode.forReadingLinkage()).thenReturn(createdNode());
nodeChanges.add(createdNode);
RecordChange<Long, NodeRecord, Void> updatedNode = mock(RecordChange.class);
when(updatedNode.getBefore()).thenReturn(inUseNode());
when(updatedNode.forReadingLinkage()).thenReturn(inUseNode());
nodeChanges.add(updatedNode);
when(nodeRecordChanges.changes()).thenReturn(nodeChanges);
when(nodeRecordChanges.changeSize()).thenReturn(3);
when(recordChangeSet.changeSize()).thenReturn(3);
when(labelTokenChanges.changes()).thenReturn(Collections.<RecordProxy<Integer, LabelTokenRecord, Void>>emptyList());
when(relationshipTypeTokenChanges.changes()).thenReturn(Collections.<RecordProxy<Integer, RelationshipTypeTokenRecord, Void>>emptyList());
when(propertyKeyTokenChanges.changes()).thenReturn(Collections.<RecordProxy<Integer, PropertyKeyTokenRecord, Void>>emptyList());
when(relationshipRecordChanges.changes()).thenReturn(Collections.<RecordProxy<Long, RelationshipRecord, Void>>emptyList());
when(propertyRecordChanges.changes()).thenReturn(Collections.<RecordProxy<Long, PropertyRecord, PrimitiveRecord>>emptyList());
when(relationshipGroupChanges.changes()).thenReturn(Collections.<RecordProxy<Long, RelationshipGroupRecord, Integer>>emptyList());
when(schemaRuleChanges.changes()).thenReturn(Collections.<RecordProxy<Long, SchemaRecord, SchemaRule>>emptyList());
NeoStores neoStores = mock(NeoStores.class);
when(neoStores.getNodeStore()).thenReturn(mock(NodeStore.class));
when(neoStores.getRelationshipGroupStore()).thenReturn(mock(RelationshipGroupStore.class));
when(neoStores.getRelationshipStore()).thenReturn(mock(RelationshipStore.class));
return new TransactionRecordState(neoStores, mock(IntegrityValidator.class), recordChangeSet, 0, null, null, null, null, null);
}
use of org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord in project neo4j by neo4j.
the class LogCommandSerializationV4_0 method readPropertyKeyTokenRecord.
private static PropertyKeyTokenRecord readPropertyKeyTokenRecord(int id, ReadableChannel channel) throws IOException {
// in_use(byte)+count(int)+key_blockId(int)
byte headerByte = channel.get();
boolean inUse = false;
boolean internal = false;
if ((headerByte & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue()) {
inUse = true;
internal = (headerByte & Record.ADDITIONAL_FLAG_1) == Record.ADDITIONAL_FLAG_1;
} else if (headerByte != Record.NOT_IN_USE.byteValue()) {
throw new IOException("Illegal in use flag: " + headerByte);
}
PropertyKeyTokenRecord record = new PropertyKeyTokenRecord(id);
record.setInUse(inUse);
record.setPropertyCount(channel.getInt());
record.setNameId(channel.getInt());
record.setInternal(internal);
if (readDynamicRecords(channel, record, PROPERTY_INDEX_DYNAMIC_RECORD_ADDER) == -1) {
return null;
}
return record;
}
Aggregations