01: /**
02: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
03: */package com.tc.util.sequence;
04:
05: import com.tc.exception.TCRuntimeException;
06: import com.tc.util.sequence.BatchSequenceProvider;
07:
08: /**
09: * This Sequence deals with batches. It keeps a next batch around to avoid
10: * pauses and always requests a new next batch as soon as the old next batch is
11: * promoted to current batch
12: *
13: * @author steve, orion
14: */
15: public final class BatchSequence implements BatchSequenceReceiver,
16: Sequence {
17:
18: private static final SequenceBatch NULL_SEQUENCE_BATCH = new SequenceBatch(
19: 0, 0);
20:
21: private SequenceBatch current = NULL_SEQUENCE_BATCH;
22: private SequenceBatch nextBatch = NULL_SEQUENCE_BATCH;
23: private boolean requestInProgress;
24: private final BatchSequenceProvider remoteProvider;
25: private final int batchSize;
26:
27: public BatchSequence(BatchSequenceProvider sequenceProvider,
28: int batchSize) {
29: this .remoteProvider = sequenceProvider;
30: this .batchSize = batchSize;
31: }
32:
33: public synchronized long next() {
34: requestMoreIDsIfNecessary();
35: return current.next();
36: }
37:
38: public synchronized long current() {
39: return current.current();
40: }
41:
42: private void requestMoreIDsIfNecessary() {
43:
44: // This should only happen the first time
45: while (!current.hasNext() && !nextBatch.hasNext()) {
46: if (!requestInProgress)
47: requestNextBatch();
48: try {
49: this .wait();
50: } catch (InterruptedException ie) {
51: throw new TCRuntimeException(ie);
52: }
53: }
54:
55: // This is the more normal case
56: if (!current.hasNext()) {
57: this .current = nextBatch;
58: this .nextBatch = NULL_SEQUENCE_BATCH;
59: requestNextBatch();
60: }
61: }
62:
63: private void requestNextBatch() {
64: remoteProvider.requestBatch(this , batchSize);
65: this .requestInProgress = true;
66: }
67:
68: public synchronized void setNextBatch(long start, long end) {
69: this .nextBatch = new SequenceBatch(start, end);
70: this .requestInProgress = false;
71: this .notifyAll();
72: }
73:
74: // The currentBatch is not considered here as we want to greedily get the next set even if the
75: // current set has some available.
76: public synchronized boolean hasNext() {
77: return nextBatch.hasNext();
78: }
79: }
|