CommitProcessor
事務提交處理器。對於非事務請求,直接交給下一級處理器進行處理;而對於事務請求,等待集羣內針對Proposal的投票,直到該Proposal可以被提交,然後再交給下一級處理器處理。
使用LinkedList和ArrayList來保證請求處理的順序性。
使用wait()和notifyAll()控制等待和喚醒。
源碼分析
public class CommitProcessor extends Thread implements RequestProcessor
@Override
public void run() {
try {
Request nextPending = null;
/* volatile boolean類型 */
while (!finished) {
/* Request的ArrayList集合,實際上是非事務請求 */
int len = toProcess.size();
for (int i = 0; i < len; i++) {
/* 對於非事務請求,直接交給下一級處理器處理,使用ArrayList來保證處理請求的順序性 */
nextProcessor.processRequest(toProcess.get(i));
}
toProcess.clear();
synchronized (this) {
/* queuedRequests是LinkedList,表示持有的未提交的請求 */
/* committedRequests是LinkedList,表示已經提交的請求 */
if ((queuedRequests.size() == 0 || nextPending != null)
&& committedRequests.size() == 0) {
wait();
continue;
}
// First check and see if the commit came in for the pending
// request
if ((queuedRequests.size() == 0 || nextPending != null)
&& committedRequests.size() > 0) {
Request r = committedRequests.remove();
/*
* We match with nextPending so that we can move to the
* next request when it is committed. We also want to
* use nextPending because it has the cnxn member set
* properly.
*/
if (nextPending != null
&& nextPending.sessionId == r.sessionId
&& nextPending.cxid == r.cxid) {
// we want to send our version of the request.
// the pointer to the connection in the request
nextPending.hdr = r.hdr;
nextPending.txn = r.txn;
nextPending.zxid = r.zxid;
/* 將匹配的nextPending加入到toProcess中 */
toProcess.add(nextPending);
nextPending = null;
} else {
// this request came from someone else so just
// send the commit packet
/* 從committedRequests取出第一個元素,加入到toProcess中 */
toProcess.add(r);
}
}
}
// We haven't matched the pending requests, so go back to
// waiting
if (nextPending != null) {
continue;
}
synchronized (this) {
// Process the next requests in the queuedRequests
while (nextPending == null && queuedRequests.size() > 0) {
Request request = queuedRequests.remove();
switch (request.type) {
/* 對於事務請求,將request作爲nextPending */
/* 對於sync請求,判斷matchSyncs參數,再做處理 */
/* 對於非事務請求,將request加入到toProcess中 */
case OpCode.create:
case OpCode.delete:
case OpCode.setData:
case OpCode.multi:
case OpCode.setACL:
case OpCode.createSession:
case OpCode.closeSession:
nextPending = request;
break;
case OpCode.sync:
if (matchSyncs) {
nextPending = request;
} else {
toProcess.add(request);
}
break;
default:
toProcess.add(request);
}
}
}
}
} catch (InterruptedException e) {
LOG.warn("Interrupted exception while waiting", e);
} catch (Throwable e) {
LOG.error("Unexpected exception causing CommitProcessor to exit", e);
}
LOG.info("CommitProcessor exited loop!");
}
synchronized public void commit(Request request) {
if (!finished) {
if (request == null) {
LOG.warn("Committed a null!",
new Exception("committing a null! "));
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug("Committing request:: " + request);
}
committedRequests.add(request);
notifyAll();
}
}
synchronized public void processRequest(Request request) {
// request.addRQRec(">commit");
if (LOG.isDebugEnabled()) {
LOG.debug("Processing request:: " + request);
}
if (!finished) {
queuedRequests.add(request);
notifyAll();
}
}
public void shutdown() {
LOG.info("Shutting down");
synchronized (this) {
finished = true;
queuedRequests.clear();
notifyAll();
}
if (nextProcessor != null) {
nextProcessor.shutdown();
}
}