|
@@ -34,42 +34,44 @@ import org.apache.log4j.Logger;
|
|
*/
|
|
*/
|
|
public class SyncRequestProcessor extends Thread implements RequestProcessor {
|
|
public class SyncRequestProcessor extends Thread implements RequestProcessor {
|
|
private static final Logger LOG = Logger.getLogger(SyncRequestProcessor.class);
|
|
private static final Logger LOG = Logger.getLogger(SyncRequestProcessor.class);
|
|
- private ZooKeeperServer zks;
|
|
|
|
- private LinkedBlockingQueue<Request> queuedRequests = new LinkedBlockingQueue<Request>();
|
|
|
|
- private RequestProcessor nextProcessor;
|
|
|
|
- Thread snapInProcess = null;
|
|
|
|
-
|
|
|
|
|
|
+ private final ZooKeeperServer zks;
|
|
|
|
+ private final LinkedBlockingQueue<Request> queuedRequests =
|
|
|
|
+ new LinkedBlockingQueue<Request>();
|
|
|
|
+ private final RequestProcessor nextProcessor;
|
|
|
|
+
|
|
|
|
+ private Thread snapInProcess = null;
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Transactions that have been written and are waiting to be flushed to
|
|
* Transactions that have been written and are waiting to be flushed to
|
|
* disk. Basically this is the list of SyncItems whose callbacks will be
|
|
* disk. Basically this is the list of SyncItems whose callbacks will be
|
|
* invoked after flush returns successfully.
|
|
* invoked after flush returns successfully.
|
|
*/
|
|
*/
|
|
- private LinkedList<Request> toFlush = new LinkedList<Request>();
|
|
|
|
- private Random r = new Random(System.nanoTime());
|
|
|
|
- private int logCount = 0;
|
|
|
|
|
|
+ private final LinkedList<Request> toFlush = new LinkedList<Request>();
|
|
|
|
+ private final Random r = new Random(System.nanoTime());
|
|
/**
|
|
/**
|
|
* The number of log entries to log before starting a snapshot
|
|
* The number of log entries to log before starting a snapshot
|
|
*/
|
|
*/
|
|
private static int snapCount = ZooKeeperServer.getSnapCount();
|
|
private static int snapCount = ZooKeeperServer.getSnapCount();
|
|
|
|
|
|
- private Request requestOfDeath = Request.requestOfDeath;
|
|
|
|
|
|
+ private final Request requestOfDeath = Request.requestOfDeath;
|
|
|
|
|
|
public SyncRequestProcessor(ZooKeeperServer zks,
|
|
public SyncRequestProcessor(ZooKeeperServer zks,
|
|
- RequestProcessor nextProcessor) {
|
|
|
|
|
|
+ RequestProcessor nextProcessor)
|
|
|
|
+ {
|
|
super("SyncThread:" + zks.getServerId());
|
|
super("SyncThread:" + zks.getServerId());
|
|
this.zks = zks;
|
|
this.zks = zks;
|
|
this.nextProcessor = nextProcessor;
|
|
this.nextProcessor = nextProcessor;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- * used by tests to check for changing
|
|
|
|
|
|
+ * used by tests to check for changing
|
|
* snapcounts
|
|
* snapcounts
|
|
* @param count
|
|
* @param count
|
|
*/
|
|
*/
|
|
public static void setSnapCount(int count) {
|
|
public static void setSnapCount(int count) {
|
|
snapCount = count;
|
|
snapCount = count;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* used by tests to get the snapcount
|
|
* used by tests to get the snapcount
|
|
* @return the snapcount
|
|
* @return the snapcount
|
|
@@ -77,10 +79,14 @@ public class SyncRequestProcessor extends Thread implements RequestProcessor {
|
|
public static int getSnapCount() {
|
|
public static int getSnapCount() {
|
|
return snapCount;
|
|
return snapCount;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public void run() {
|
|
public void run() {
|
|
try {
|
|
try {
|
|
|
|
+ int logCount = 0;
|
|
|
|
+
|
|
|
|
+ // we do this in an attempt to ensure that not all of the servers
|
|
|
|
+ // in the ensemble take a snapshot at the same time
|
|
int randRoll = r.nextInt(snapCount/2);
|
|
int randRoll = r.nextInt(snapCount/2);
|
|
while (true) {
|
|
while (true) {
|
|
Request si = null;
|
|
Request si = null;
|
|
@@ -97,7 +103,8 @@ public class SyncRequestProcessor extends Thread implements RequestProcessor {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
if (si != null) {
|
|
if (si != null) {
|
|
- zks.getLogWriter().append(si);
|
|
|
|
|
|
+ // track the number of records written to the log
|
|
|
|
+ if (zks.getLogWriter().append(si)) {
|
|
logCount++;
|
|
logCount++;
|
|
if (logCount > (snapCount / 2 + randRoll)) {
|
|
if (logCount > (snapCount / 2 + randRoll)) {
|
|
randRoll = r.nextInt(snapCount/2);
|
|
randRoll = r.nextInt(snapCount/2);
|
|
@@ -106,21 +113,31 @@ public class SyncRequestProcessor extends Thread implements RequestProcessor {
|
|
// take a snapshot
|
|
// take a snapshot
|
|
if (snapInProcess != null && snapInProcess.isAlive()) {
|
|
if (snapInProcess != null && snapInProcess.isAlive()) {
|
|
LOG.warn("Too busy to snap, skipping");
|
|
LOG.warn("Too busy to snap, skipping");
|
|
- }
|
|
|
|
- else {
|
|
|
|
|
|
+ } else {
|
|
snapInProcess = new Thread("Snapshot Thread") {
|
|
snapInProcess = new Thread("Snapshot Thread") {
|
|
- public void run() {
|
|
|
|
- try {
|
|
|
|
- zks.takeSnapshot();
|
|
|
|
- } catch(Exception e) {
|
|
|
|
- LOG.warn("Unexpected exception", e);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
|
|
+ public void run() {
|
|
|
|
+ try {
|
|
|
|
+ zks.takeSnapshot();
|
|
|
|
+ } catch(Exception e) {
|
|
|
|
+ LOG.warn("Unexpected exception", e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
snapInProcess.start();
|
|
snapInProcess.start();
|
|
}
|
|
}
|
|
logCount = 0;
|
|
logCount = 0;
|
|
}
|
|
}
|
|
|
|
+ } else if (toFlush.isEmpty()) {
|
|
|
|
+ // optimization for read heavy workloads
|
|
|
|
+ // iff this is a read, and there are no pending
|
|
|
|
+ // flushes (writes), then just pass this to the next
|
|
|
|
+ // processor
|
|
|
|
+ nextProcessor.processRequest(si);
|
|
|
|
+ if (nextProcessor instanceof Flushable) {
|
|
|
|
+ ((Flushable)nextProcessor).flush();
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
toFlush.add(si);
|
|
toFlush.add(si);
|
|
if (toFlush.size() > 1000) {
|
|
if (toFlush.size() > 1000) {
|
|
flush(toFlush);
|
|
flush(toFlush);
|
|
@@ -135,11 +152,11 @@ public class SyncRequestProcessor extends Thread implements RequestProcessor {
|
|
}
|
|
}
|
|
|
|
|
|
private void flush(LinkedList<Request> toFlush) throws IOException {
|
|
private void flush(LinkedList<Request> toFlush) throws IOException {
|
|
- if (toFlush.size() == 0)
|
|
|
|
|
|
+ if (toFlush.isEmpty())
|
|
return;
|
|
return;
|
|
|
|
|
|
zks.getLogWriter().commit();
|
|
zks.getLogWriter().commit();
|
|
- while (toFlush.size() > 0) {
|
|
|
|
|
|
+ while (!toFlush.isEmpty()) {
|
|
Request i = toFlush.remove();
|
|
Request i = toFlush.remove();
|
|
nextProcessor.processRequest(i);
|
|
nextProcessor.processRequest(i);
|
|
}
|
|
}
|