-
Notifications
You must be signed in to change notification settings - Fork 7.3k
ZOOKEEPER-3594: Ability to skip proposing requests with error transactions #1172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,8 @@ | |
| import org.apache.zookeeper.data.Id; | ||
| import org.apache.zookeeper.metrics.Summary; | ||
| import org.apache.zookeeper.metrics.SummarySet; | ||
| import org.apache.zookeeper.server.quorum.LearnerHandler; | ||
| import org.apache.zookeeper.server.quorum.SkipRequestHandler; | ||
| import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier; | ||
| import org.apache.zookeeper.server.util.AuthUtil; | ||
| import org.apache.zookeeper.txn.TxnHeader; | ||
|
|
@@ -48,6 +50,8 @@ public class Request { | |
| // associated session timeout. Disabled by default. | ||
| private static volatile boolean staleLatencyCheck = Boolean.parseBoolean(System.getProperty("zookeeper.request_stale_latency_check", "false")); | ||
|
|
||
| private SkipRequestHandler skipRequestHandler; | ||
|
|
||
| public Request(ServerCnxn cnxn, long sessionId, int xid, int type, ByteBuffer bb, List<Id> authInfo) { | ||
| this.cnxn = cnxn; | ||
| this.sessionId = sessionId; | ||
|
|
@@ -87,6 +91,8 @@ public Request(long sessionId, int xid, int type, TxnHeader hdr, Record txn, lon | |
|
|
||
| public final List<Id> authInfo; | ||
|
|
||
| private boolean isSkipped = false; | ||
|
|
||
| public final long createTime = Time.currentElapsedTime(); | ||
|
|
||
| public long prepQueueStartTime = -1; | ||
|
|
@@ -105,6 +111,14 @@ public Request(long sessionId, int xid, int type, TxnHeader hdr, Record txn, lon | |
|
|
||
| public QuorumVerifier qv = null; | ||
|
|
||
| public boolean isFromLeader() { | ||
| return owner == ServerCnxn.me; | ||
| } | ||
|
|
||
| public boolean isFromFollower() { | ||
| return owner instanceof LearnerHandler; | ||
| } | ||
|
|
||
| /** | ||
| * If this is a create or close request for a local-only session. | ||
| */ | ||
|
|
@@ -462,4 +476,48 @@ public String getUsers() { | |
| } | ||
| return users.toString(); | ||
| } | ||
|
|
||
| /** | ||
| * This will check if the request's handler supports skip feature, | ||
| * the information that is passed from Learner to LearnerMaster using protocol version info | ||
| * | ||
| * See org.apache.zookeeper.server.quorum.QuorumZooKeeperServer.PROTOCOL_VERSION | ||
| * | ||
| */ | ||
| public boolean canSkip() { | ||
| return skipRequestHandler != null; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this always return true? As far as I can see skipRequestHandler will never be null as it's set by
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, this is related to learner protocol version, something outside the scope of this. This is not required to be in this pull request. |
||
| } | ||
|
|
||
| /** | ||
| * Will mark this request for request skipping | ||
| */ | ||
| public void setSkipped() { | ||
| isSkipped = true; | ||
| } | ||
|
|
||
| /** | ||
| * Once we mark request as skipped this method will be returning true | ||
| */ | ||
| public boolean isSkipped() { | ||
| return isSkipped; | ||
| } | ||
|
|
||
| /** | ||
| * Each request has access to its handler so know who is this requests owner | ||
| * and interact with it when we need to | ||
| */ | ||
| public void setSkipRequestHandler(SkipRequestHandler skipRequestHandler) { | ||
| this.skipRequestHandler = skipRequestHandler; | ||
| } | ||
|
|
||
| public SkipRequestHandler getSkipRequestHandler() { | ||
| return skipRequestHandler; | ||
| } | ||
|
|
||
| /** | ||
| * Check the result of the PrepRequestProcessor validations for write requests. | ||
| */ | ||
| public boolean hasError() { | ||
| return hdr != null && e != null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -561,7 +561,11 @@ public SessionTracker getSessionTracker() { | |
| } | ||
|
|
||
| long getNextZxid() { | ||
| return hzxid.incrementAndGet(); | ||
| return hzxid.get() + 1; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will not be thread safe, right? would this be a concern?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't be a concern as long as we keep processing requests in order inside PrepRequestProcessor. If that changes this can break but that is not likely to happen. |
||
| } | ||
|
|
||
| void incrementZxid() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. another idea - instead of having this to increase the zxid we can instead have a decrementZxid, which will only be called if we have an error transaction. By doing that, we can keep the existing implementation of
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a great alternative and it was my first approach but then I though we need to remember the decrement zxid which I wanted to eliminate. But that was early when I started working on this. I will take another look and see how things look now if I use decrement zxid. |
||
| hzxid.incrementAndGet(); | ||
| } | ||
|
|
||
| public void setZxid(long zxid) { | ||
|
|
@@ -1716,7 +1720,7 @@ public ProcessTxnResult processTxn(Request request) { | |
| } | ||
|
|
||
| // do not add non quorum packets to the queue. | ||
| if (quorumRequest) { | ||
| if (quorumRequest && !request.isSkipped()) { | ||
| getZKDatabase().addCommittedProposal(request); | ||
| } | ||
| return rc; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,8 +31,10 @@ | |
| import org.apache.zookeeper.server.RequestProcessor; | ||
| import org.apache.zookeeper.server.ServerMetrics; | ||
| import org.apache.zookeeper.server.SyncRequestProcessor; | ||
| import org.apache.zookeeper.server.TxnLogEntry; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see where this is defined. Maybe in a new file that's forgot to be included as part of this PR?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one should not be here. |
||
| import org.apache.zookeeper.server.ZKDatabase; | ||
| import org.apache.zookeeper.server.persistence.FileTxnSnapLog; | ||
| import org.apache.zookeeper.server.util.SerializeUtils; | ||
| import org.apache.zookeeper.txn.TxnHeader; | ||
| import org.apache.zookeeper.util.ServiceUtils; | ||
| import org.slf4j.Logger; | ||
|
|
@@ -108,6 +110,19 @@ public void commit(long zxid) { | |
| commitProcessor.commit(request); | ||
| } | ||
|
|
||
|
|
||
| public void skip(byte[] data) { | ||
| try { | ||
| TxnHeader hdr = new TxnHeader(); | ||
| Record txn = SerializeUtils.deserializeTxn(data, hdr); | ||
| Request request = new Request(hdr.getClientId(), hdr.getCxid(), hdr.getType(), hdr, txn, 0); | ||
| request.logLatency(ServerMetrics.getMetrics().SKIP_PROPAGATION_LATENCY); | ||
| commitProcessor.commit(request); | ||
| } catch (IOException e) { | ||
| LOG.error("Could not deserialize SKIP request"); | ||
| } | ||
| } | ||
|
|
||
| public synchronized void sync() { | ||
| if (pendingSyncs.size() == 0) { | ||
| LOG.warn("Not expecting a sync."); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method is not used.. is this needed?