Details
-
Improvement
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
None
-
None
-
None
Description
For general context please check IGNITE-17252. In order to specify request-specific handling logic that will map particular actionRequest to corresponding set of operations it's required to introduce such mapping rules in a similar way that is used within raft listeners, in other words it's required to introduce a sort of state machine for replica
As tx design document notes common flow for major tx requests is following:
On receiving OpRequest 1. Check primary replica lease. Return the failure if not valid. 2. Try to acquire a shared or exclusive lock, depending on the op type. 3. If failed to acquire the lock due to a conflict, return the failure. 4. When the lock is acquired, return an OpResponse to a coordinator with a value, if op type is read or read-write.The OpResponse structure is: opCode:int // 0 - ok, !0 - error code result:Array readLeases:Map<partitionId, LeaseInterval> timestamp:HLC 5. Replicate a write intent asynchronously if op type is write or read-write As soon as the write intent is replicated, send WriteAckResponse to the coordinator. The WriteAckReponse structure is: opCode:int // 0 - ok, !0 - error code opId:int timestamp:HLC 6. Return the replication ack response to a coordinator.
Given steps should be managed from within ReplicaListener. Why? Because concrete set of locks to acquire depends on operation type:
The required locks on the row store are the following: 1. Tuple get(RowId rowId, UUID txId) IS_commit(table) S_commit(rowId) 2.Tuple get(RowId rowId, @Nullable Timestamp timestamp) No locks. Null timestamp is used to read the latest committed value for a single get. 3.Tuple getForUpdate(RowId rowId, UUID txId) IX_commit(table) X_commit(rowId) 4. RowId insert(Tuple row, UUID txId) IX_commit(table) 5. boolean update(RowId rowId, Tuple newRow, UUID txId) IX_commit(table) X_commit(rowId) 6. Tuple remove(RowId rowId, UUID txId) IX_commit(table) X_commit(rowId) 7. void commitWrite(RowId rowId, Timestamp timestamp, UUID txId) 8. void abortWrite(RowId rowId, UUID txId) 9. Iterator<Tuple> scan(Predicate<Tuple> filter, UUID txId) S_commit(table) - if a predicate can produce phantom reads, IS_commit(table) - otherwise 10. Iterator<Tuple> scan(Predicate<Tuple> filter, Timestamp timestamp) No locks 11. <T> Iterator<T> invoke(Predicate<Tuple> filter, InvokeClosure<T> clo, UUID txId) SIX_commit(table) - if a predicate can produce phantom reads, IX_commit(table) otherwise X_commit on each updated row.
Please check ts design for full set of required actions for lock management, e.g. index-based locks.
Besides that there are some actions, like commit/abort transaction (replicateTxnState) that have dedicated handling logic.
! Given ticket should be validated with SE_team in order to check whether whey are fine with proposed index managing actors.
Attachments
Issue Links
- blocks
-
IGNITE-17255 Implement ReplicaService
- Resolved
- is blocked by
-
IGNITE-17252 Introduce Replica, ReplicaServer(?), ReplicaService and ReplicaListener interfaces
- Resolved
-
IGNITE-17257 Implement Replica server-side logic
- Resolved