public override bool VisitSchemaRuleCommand(Command.SchemaRuleCommand command) { // This shows that this transaction is a schema transaction, so it cannot have commands // updating any counts anyway. Therefore the counts updater is closed right away. // This also breaks an otherwise deadlocking scenario between check pointer, this applier // and an index population thread wanting to apply index sampling to the counts store. Debug.Assert(!_haveUpdates, "Assumed that a schema transaction wouldn't also contain data commands affecting " +); "counts store, but was proven wrong with this transaction"; CloseCountsUpdaterIfOpen(); return(false); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public void extractCommands(java.util.Collection<org.neo4j.storageengine.api.StorageCommand> commands) throws org.neo4j.internal.kernel.api.exceptions.TransactionFailureException public override void ExtractCommands(ICollection <StorageCommand> commands) { Debug.Assert(!_prepared, "Transaction has already been prepared"); _integrityValidator.validateTransactionStartKnowledge(_lastCommittedTxWhenTransactionStarted); int noOfCommands = _recordChangeSet.changeSize() + (_neoStoreRecord != null ? _neoStoreRecord.changeSize() : 0); foreach (RecordAccess_RecordProxy <LabelTokenRecord, Void> record in _recordChangeSet.LabelTokenChanges.changes()) { commands.Add(new Command.LabelTokenCommand(record.Before, record.ForReadingLinkage())); } foreach (RecordAccess_RecordProxy <RelationshipTypeTokenRecord, Void> record in _recordChangeSet.RelationshipTypeTokenChanges.changes()) { commands.Add(new Command.RelationshipTypeTokenCommand(record.Before, record.ForReadingLinkage())); } foreach (RecordAccess_RecordProxy <PropertyKeyTokenRecord, Void> record in _recordChangeSet.PropertyKeyTokenChanges.changes()) { commands.Add(new Command.PropertyKeyTokenCommand(record.Before, record.ForReadingLinkage())); } // Collect nodes, relationships, properties Command[] nodeCommands = _emptyCommands; int skippedCommands = 0; if (_recordChangeSet.NodeRecords.changeSize() > 0) { nodeCommands = new Command[_recordChangeSet.NodeRecords.changeSize()]; int i = 0; foreach (RecordAccess_RecordProxy <NodeRecord, Void> change in _recordChangeSet.NodeRecords.changes()) { NodeRecord record = Prepared(change, _nodeStore); _integrityValidator.validateNodeRecord(record); nodeCommands[i++] = new Command.NodeCommand(change.Before, record); } Arrays.sort(nodeCommands, _commandComparator); } Command[] relCommands = _emptyCommands; if (_recordChangeSet.RelRecords.changeSize() > 0) { relCommands = new Command[_recordChangeSet.RelRecords.changeSize()]; int i = 0; foreach (RecordAccess_RecordProxy <RelationshipRecord, Void> change in _recordChangeSet.RelRecords.changes()) { relCommands[i++] = new Command.RelationshipCommand(change.Before, Prepared(change, _relationshipStore)); } Arrays.sort(relCommands, _commandComparator); } Command[] propCommands = _emptyCommands; if (_recordChangeSet.PropertyRecords.changeSize() > 0) { propCommands = new Command[_recordChangeSet.PropertyRecords.changeSize()]; int i = 0; foreach (RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> change in _recordChangeSet.PropertyRecords.changes()) { propCommands[i++] = new Command.PropertyCommand(change.Before, Prepared(change, _propertyStore)); } Arrays.sort(propCommands, _commandComparator); } Command[] relGroupCommands = _emptyCommands; if (_recordChangeSet.RelGroupRecords.changeSize() > 0) { relGroupCommands = new Command[_recordChangeSet.RelGroupRecords.changeSize()]; int i = 0; foreach (RecordAccess_RecordProxy <RelationshipGroupRecord, int> change in _recordChangeSet.RelGroupRecords.changes()) { if (change.Created && !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.Before, Prepared(change, _relationshipGroupStore)); } relGroupCommands = i < relGroupCommands.Length ? Arrays.copyOf(relGroupCommands, i) : relGroupCommands; Arrays.sort(relGroupCommands, _commandComparator); } AddFiltered(commands, Command.Mode.CREATE, propCommands, relCommands, relGroupCommands, nodeCommands); AddFiltered(commands, Command.Mode.UPDATE, propCommands, relCommands, relGroupCommands, nodeCommands); AddFiltered(commands, Command.Mode.DELETE, propCommands, relCommands, relGroupCommands, nodeCommands); if (_neoStoreRecord != null) { foreach (RecordAccess_RecordProxy <NeoStoreRecord, Void> change in _neoStoreRecord.changes()) { commands.Add(new Command.NeoStoreCommand(change.Before, change.ForReadingData())); } } //noinspection unchecked IList <Command>[] schemaChangeByMode = new System.Collections.IList[Command.Mode.values().length]; for (int i = 0; i < schemaChangeByMode.Length; i++) { schemaChangeByMode[i] = new List <Command>(); } foreach (RecordAccess_RecordProxy <SchemaRecord, SchemaRule> change in _recordChangeSet.SchemaRuleChanges.changes()) { if (change.ForReadingLinkage().inUse()) { _integrityValidator.validateSchemaRule(change.AdditionalData); } Command.SchemaRuleCommand cmd = new Command.SchemaRuleCommand(change.Before, change.ForChangingData(), change.AdditionalData); schemaChangeByMode[cmd.Mode.ordinal()].Add(cmd); } commands.addAll(schemaChangeByMode[Command.Mode.DELETE.ordinal()]); commands.addAll(schemaChangeByMode[Command.Mode.CREATE.ordinal()]); commands.addAll(schemaChangeByMode[Command.Mode.UPDATE.ordinal()]); Debug.Assert(commands.Count == noOfCommands - skippedCommands, format("Expected %d final commands, got %d " + "instead, with %d skipped", noOfCommands, commands.Count, skippedCommands)); _prepared = true; }