This list is closed, nobody may subscribe to it.
2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(139) |
Aug
(94) |
Sep
(232) |
Oct
(143) |
Nov
(138) |
Dec
(55) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(127) |
Feb
(90) |
Mar
(101) |
Apr
(74) |
May
(148) |
Jun
(241) |
Jul
(169) |
Aug
(121) |
Sep
(157) |
Oct
(199) |
Nov
(281) |
Dec
(75) |
2012 |
Jan
(107) |
Feb
(122) |
Mar
(184) |
Apr
(73) |
May
(14) |
Jun
(49) |
Jul
(26) |
Aug
(103) |
Sep
(133) |
Oct
(61) |
Nov
(51) |
Dec
(55) |
2013 |
Jan
(59) |
Feb
(72) |
Mar
(99) |
Apr
(62) |
May
(92) |
Jun
(19) |
Jul
(31) |
Aug
(138) |
Sep
(47) |
Oct
(83) |
Nov
(95) |
Dec
(111) |
2014 |
Jan
(125) |
Feb
(60) |
Mar
(119) |
Apr
(136) |
May
(270) |
Jun
(83) |
Jul
(88) |
Aug
(30) |
Sep
(47) |
Oct
(27) |
Nov
(23) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(3) |
Oct
|
Nov
|
Dec
|
2016 |
Jan
|
Feb
|
Mar
(4) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <tho...@us...> - 2013-05-20 17:32:30
|
Revision: 7151 http://bigdata.svn.sourceforge.net/bigdata/?rev=7151&view=rev Author: thompsonbry Date: 2013-05-20 17:32:22 +0000 (Mon, 20 May 2013) Log Message: ----------- AbstractJournal: Added logic to make AbstractJournal.commit() spin for up to 5000ms if required to obtain a commitTime that moves forward with respect to the then current lastCommitTime. This addresses a potential source of problems with clock skew in HA and could permit us to allow more skew to be present among the nodes of an HA cluster (though I have not yet relaxed that constraint in Journal.assertBefore()). AbstractJournal: added getRootBlockWithLock() variant. HAJournalServer.awaitJournalToken(): modified to use getRootBlockWithLock() to ensure atomicity of the state changes that awaitJournalToken() is monitoring. Journal: More cleanup on the consensus release time protocol. Changes improve reporting of the root cause of an exception in the release time consensus protocol and shift reporting of clock synchronization problems entirely to the leader (based on the timestamps obtain on the leader and the followers). @see https://sourceforge.net/apps/trac/bigdata/ticket/530 (Journal HA) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-20 17:13:24 UTC (rev 7150) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-20 17:32:22 UTC (rev 7151) @@ -168,6 +168,7 @@ import com.bigdata.service.IBigdataFederation; import com.bigdata.stream.Stream; import com.bigdata.util.ChecksumUtility; +import com.bigdata.util.ClocksNotSynchronizedException; import com.bigdata.util.NT; /** @@ -2452,7 +2453,44 @@ // } } + + /** + * Variant of {@link #getRootBlockView()} that takes the internal lock in + * order to provide an appropriate synchronization barrier when installing + * new root blocks onto an empty journal in HA. + * + * @see #installRootBlocks(IRootBlockView, IRootBlockView) + */ + final public IRootBlockView getRootBlockViewWithLock() { + final ReadLock lock = _fieldReadWriteLock.readLock(); + + lock.lock(); + + try { + + if (_rootBlock == null) { + + /* + * This can happen before the journal file has been created. + * Once it has been created the root block will always be + * non-null when viewed while holding the lock. + */ + + throw new IllegalStateException(); + + } + + return _rootBlock; + + } finally { + + lock.unlock(); + + } + + } + final public long getLastCommitTime() { // final ReadLock lock = _fieldReadWriteLock.readLock(); @@ -2805,17 +2843,75 @@ } + /** + * Get timestamp that will be assigned to this commit point. + * <P> + * Note: This will spin until commit time advances over + * <code>lastCommitTime</code>, but not for more than N milliseconds. This + * will allow us to ensure that time moves forward when the leader fails + * over to another node with modest clock skew. If there is a large clock + * skew, the operator intervention will be required. + * <p> + * Note: This also makes sense for a non-HA deployment since we still want + * time to move forward at each commit point. + * + * TODO This also makes sense when the Journal is opened since we often + * issue queries against historical commit points on the journal based on + * the clock. [Unit test for this in standalone and HA modes?] + */ + private long nextCommitTimestamp() { + final IRootBlockView rootBlock = _rootBlock; + final long lastCommitTime = rootBlock.getLastCommitTime(); + if (lastCommitTime < 0) + throw new RuntimeException( + "Last commit time is invalid in rootBlock: " + rootBlock); + final long commitTime; + { + final ILocalTransactionManager transactionManager = getLocalTransactionManager(); + + boolean warned = false; + while (true) { + final long t = transactionManager.nextTimestamp(); + if (t > lastCommitTime) { + /* + * We have a distinct timestamp. Time is moving forward. + */ + commitTime = t; + break; + } + /* + * Time is going backwards. Figure out by how much. + * + * Note: delta is in ms. + */ + final long delta = Math.abs(t - lastCommitTime); + if (delta > 5000/* ms */) + throw new ClocksNotSynchronizedException("Clocks off by " + + delta + " ms: lastCommitTime=" + lastCommitTime + + ", but localTimestamp=" + t); + if (!warned) { + log.warn("Clocks off by " + delta + " ms: lastCommitTime=" + + lastCommitTime + ", but localTimestamp=" + t); + warned = true; + } + try { + // Wait for the delta to expire. + Thread.sleep(delta/* ms */); + } catch (InterruptedException ex) { + // Propagate interrupt. + Thread.currentThread().interrupt(); + } + } + } + return commitTime; + } + @Override public long commit() { - final ILocalTransactionManager transactionManager = getLocalTransactionManager(); + // The timestamp to be assigned to this commit point. + final long commitTime = nextCommitTimestamp(); - /* - * Get timestamp that will be assigned to this commit (RMI if the - * journal is part of a distributed federation). - */ - final long commitTime = transactionManager.nextTimestamp(); - // do the commit. final IRootBlockView lastRootBlock = _rootBlock; final long commitTime2; @@ -2845,7 +2941,7 @@ * e.g., due to a service outage. */ - transactionManager.notifyCommit(commitTime); + getLocalTransactionManager().notifyCommit(commitTime); return commitTime; Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-20 17:13:24 UTC (rev 7150) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-20 17:32:22 UTC (rev 7151) @@ -27,6 +27,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.Collection; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; @@ -359,6 +360,13 @@ * This is the earliest visible commit point on the leader. */ final private IHANotifyReleaseTimeRequest leadersValue; + + /** + * Exception is set by {@link #run()} if there is a problem when the + * barrier breaks. The exception is then thrown out to the thread on + * the leader that is running commitNow(), forcing the commit to fail. + */ + volatile Throwable cause = null; /** * The message from each of those followers providing their local @@ -462,12 +470,20 @@ @Override public void run() { + try { + if (log.isInfoEnabled()) log.info("leader: " + leadersValue); // This is the timestamp from the BarrierState ctor. final long timeLeader = leadersValue.getTimestamp(); + // This is the timestamp for right now. + final long timeNow = newConsensusProtocolTimestamp(); + + // The local clock must be moving forward. + assertBefore(timeLeader, timeNow); + // Start with the leader's value (from ctor). minimumResponse = leadersValue; @@ -485,10 +501,17 @@ /* * Verify that the timestamp from the ctor is BEFORE the - * timestamp assigned by the follower for its response. + * timestamp assigned by the follower in the GatherTask. */ assertBefore(timeLeader, response.getTimestamp()); + /* + * Verify that the timestamp from the GatherTask on the follower + * is before the timestamp obtained at the top of this run() + * method. + */ + assertBefore(response.getTimestamp(), timeNow); + } // Restate the consensus as an appropriate message object. @@ -499,6 +522,13 @@ if (log.isInfoEnabled()) log.info("consensus: " + consensus); + } catch(Throwable t) { + + // Set the cause. + cause = t; + + } + } /** @@ -553,26 +583,46 @@ // final Future<Void>[] remoteFutures = new Future[joinedServiceIds.length]; // final boolean[] remoteDone = new boolean[joinedServiceIds.length]; + final List<Future<Void>> futures = new LinkedList<Future<Void>>(); + try { final IHAGatherReleaseTimeRequest msg = new HAGatherReleaseTimeRequest( token, timestampOnLeader); - + // Do not send message to self (leader is at index 0). for (int i = 1; i < joinedServiceIds.length; i++) { final UUID serviceId = joinedServiceIds[i]; /* - * Runnable which will execute this message on the remote - * service. + * Message each follower. + * + * Note: The invoked RMI method submits the GatherTask that + * executes on the follower and returns. It does not block + * waiting for the outcome of the task on the follower. + * Instead, we wait until the barrier breaks. A thread will + * monitor the quorum state and break the barrier if the + * quorum breaks or if a joined service leaves during the + * consensus protocol. + * + * Note: This uses multiple threads to issue the requests in + * parallel against the followers in order to minimize the + * latency of the protocol. */ - - // Resolve joined service. - final HATXSGlue service = getService(serviceId); - - // Message joined service (can throw NPE if service is gone). - service.gatherMinimumVisibleCommitTime(msg); + // Note: throws RejectedExecutionException if shutdown. + futures.add(getExecutorService().submit( + new Callable<Void>() { + public Void call() throws Exception { + // Resolve joined service. + final HATXSGlue service = getService(serviceId); + // Message remote service. + // Note: NPE if [service] is gone. + service.gatherMinimumVisibleCommitTime(msg); + // Done. + return null; + } + })); // // add to list of futures we will check. // remoteFutures[i] = rf; @@ -741,21 +791,17 @@ // } } finally { -// /* -// * Regardless of outcome or errors above, ensure that all remote -// * futures are cancelled. -// */ -// for (int i = 0; i < remoteFutures.length; i++) { -// final Future<Void> rf = remoteFutures[i]; -// if (!remoteDone[i]) { -// // Cancel the request on the remote service (RMI). -// try { -// rf.cancel(true/* mayInterruptIfRunning */); -// } catch (Throwable t) { -// // ignored. -// } -// } -// } + /* + * Cancel local futures for RMI messages to followers. + * + * Note: Regardless of outcome or errors above, ensure that the + * futures used to initiate the GatherTask on the followers are + * cancelled. These are local Futures that do RMIs. The RMIs + * should not block when the execute on the follower. + */ + for (Future<Void> f : futures) { + f.cancel(true/* mayInterruptIfRunning */); + } if (!barrier.isBroken()) { /* * If there were any followers that did not message the @@ -773,10 +819,8 @@ * "vote yes". Thus, a single node failure during the * release time consensus protocol will cause the commit to * fail. [Actually, we could use getNumberWaiting(). If it - * is a bare majority, then we could force the barrier to - * meet break (either with reset or with running an await() - * in other threads) and take the barrier break action - * ourselves. E.g., in the thread that calls + * is a bare majority, then we could take the barrier break + * action ourselves. E.g., in the thread that calls * barrier.reset()]. */ barrier.reset(); @@ -933,11 +977,14 @@ * Assert that t1 LT t2. * * @param t1 + * A timestamp from one service. * @param t2 + * A timestamp from another service. * * @throws ClocksNotSynchronizedException */ - private void assertBefore(final long t1, final long t2) { + private void assertBefore(final long t1, final long t2) + throws ClocksNotSynchronizedException { if (t1 < t2) return; @@ -945,8 +992,20 @@ throw new ClocksNotSynchronizedException(); } - + /** + * Note: This deliberately uses the (non-remote) method + * {@link BasicHA#nextTimestamp()}. This is done so we can write a unit test + * of the {@link GatherTask} that imposes clock skew by overridding the next + * value to be returned by that method. + */ + private long newConsensusProtocolTimestamp() { + + return ((BasicHA) getQuorum().getClient().getService()).nextTimestamp(); + + } + + /** * {@inheritDoc} * <p> * Extends the {@link JournalTransactionService} to provide protection for @@ -1112,6 +1171,17 @@ } + if (barrierState.cause != null) { + + /* + * If an exception was recorded, re-throw it in the thread + * that invoked commitNow(). + */ + + throw new RuntimeException(barrierState.cause); + + } + /** * Update the release time on the leader. * @@ -1286,7 +1356,8 @@ final long commitTime = commitRecord == null ? 0 : commitRecord.getTimestamp(); - final long now = getLocalTransactionManager().nextTimestamp(); +// final long now = getLocalTransactionManager().nextTimestamp(); + final long now = newConsensusProtocolTimestamp(); final IHANotifyReleaseTimeRequest req = new HANotifyReleaseTimeRequest( serviceId, commitTime, commitCounter, now); @@ -1407,14 +1478,8 @@ /* * This timestamp is used to help detect clock skew. - * - * Note: This deliberately uses the (non-remote) - * nextTimestamp() method on BasicHA. This is being done so - * we can write a unit test of the GatherTask that imposes - * clock skew by overridding the next value to be returned - * by that method. */ - now = ((BasicHA)quorumService.getService()).nextTimestamp(); + now = newConsensusProtocolTimestamp(); /* * If the token is invalid, making it impossible for us to @@ -1428,10 +1493,16 @@ * our response. If we hit an assertion, we will still * respond in the finally {} block below. */ - - /* Verify event on leader occurs before event on follower. + + /* + * Note: This assert has been moved to the leader when it + * analyzes the messages from the followers. This allows us + * to report out the nature of the exception on the leader + * and thence back to the client. */ - assertBefore(req.getTimestampOnLeader(), now); +// /* Verify event on leader occurs before event on follower. +// */ +// assertBefore(req.getTimestampOnLeader(), now); if (!quorumService.isFollower(token)) throw new QuorumException(); @@ -1601,17 +1672,29 @@ // Make a note of the message from this follower. barrierState.responses.put(followerId, req); + } catch(RuntimeException e) { + + /* + * Note: The try {} block can throw RuntimeException but not + * Exception. If anything is thrown, then reset the barrier and + * rethrow the exception. + */ + + haLog.error(e, e); + + // Reset the barrier (barrier will break). + barrierState.barrier.reset(); + + // Rethrow the exception. + throw new RuntimeException(e); + } finally { /* * Block until barrier breaks. * - * Note: We want to await() on the barrier even if there is an - * error in the try{} block. This is necessary to decrement the - * barrier count down to zero. - * - * TODO If there is an error, we could reset() the barrier - * instead. + * Note: The barrier will break immediately if it was reset in + * the catch{} block above. */ // follower blocks on Thread on the leader here. @@ -1619,6 +1702,23 @@ } + /* + * Check for an error in the consensus protocol. + */ + final Throwable t = barrierState.cause; + + if (t != null) { + + /* + * Log error. + */ + haLog.error(t, t); + + // rethrow cause. + throw new RuntimeException(t); + + } + // Return the consensus. final IHANotifyReleaseTimeResponse resp = barrierState.consensus; @@ -1630,7 +1730,7 @@ } return resp; - + } /** Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java 2013-05-20 17:13:24 UTC (rev 7150) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java 2013-05-20 17:32:22 UTC (rev 7151) @@ -1566,6 +1566,10 @@ * yet. */ // server.haGlueService.bounceZookeeperConnection(); + /* + * Note: Try moving to doRejectedCommit() so this will be + * synchronous. + */ logLock.lock(); try { if (journal.getHALogNexus().isHALogOpen()) { @@ -3525,7 +3529,8 @@ continue; } if (isFollower(token)) {// if (awaitRootBlocks) { - final IRootBlockView rbSelf = journal.getRootBlockView(); + // Check root block, using lock for synchronization barrier. + final IRootBlockView rbSelf = journal.getRootBlockViewWithLock(); if (rbSelf.getCommitCounter() == 0L) { /* * Only wait if this is an empty Journal. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-20 17:13:30
|
Revision: 7150 http://bigdata.svn.sourceforge.net/bigdata/?rev=7150&view=rev Author: thompsonbry Date: 2013-05-20 17:13:24 +0000 (Mon, 20 May 2013) Log Message: ----------- Modified QuorumMember to expose an ExecutorService rather than an Executor so we can use invokeAll(). Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumServiceBase.java branches/READ_CACHE/bigdata/src/java/com/bigdata/quorum/QuorumMember.java branches/READ_CACHE/bigdata/src/test/com/bigdata/io/writecache/TestWORMWriteCacheService.java branches/READ_CACHE/bigdata/src/test/com/bigdata/quorum/MockQuorumFixture.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/quorum/zk/MockQuorumMember.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumServiceBase.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumServiceBase.java 2013-05-20 17:11:14 UTC (rev 7149) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumServiceBase.java 2013-05-20 17:13:24 UTC (rev 7150) @@ -30,7 +30,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.UUID; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeoutException; @@ -184,7 +184,7 @@ } @Override - public Executor getExecutor() { + public ExecutorService getExecutor() { return getLocalService().getExecutorService(); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/quorum/QuorumMember.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/quorum/QuorumMember.java 2013-05-20 17:11:14 UTC (rev 7149) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/quorum/QuorumMember.java 2013-05-20 17:13:24 UTC (rev 7150) @@ -29,7 +29,7 @@ import java.rmi.Remote; import java.util.UUID; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import com.bigdata.ha.HACommitGlue; import com.bigdata.ha.QuorumCommit; @@ -80,10 +80,10 @@ S getService(); /** - * An {@link Executor} which may be used by the {@link QuorumMember} to run - * various asynchronous tasks. + * An {@link ExecutorService} which may be used by the {@link QuorumMember} + * to run various asynchronous tasks. */ - Executor getExecutor(); + ExecutorService getExecutor(); /** * Return the actor for this {@link QuorumMember}. Modified: branches/READ_CACHE/bigdata/src/test/com/bigdata/io/writecache/TestWORMWriteCacheService.java =================================================================== --- branches/READ_CACHE/bigdata/src/test/com/bigdata/io/writecache/TestWORMWriteCacheService.java 2013-05-20 17:11:14 UTC (rev 7149) +++ branches/READ_CACHE/bigdata/src/test/com/bigdata/io/writecache/TestWORMWriteCacheService.java 2013-05-20 17:13:24 UTC (rev 7150) @@ -36,7 +36,7 @@ import java.text.NumberFormat; import java.util.Random; import java.util.UUID; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.RunnableFuture; @@ -393,7 +393,7 @@ } @Override - public Executor getExecutor() { + public ExecutorService getExecutor() { return fixture.getExecutor(); Modified: branches/READ_CACHE/bigdata/src/test/com/bigdata/quorum/MockQuorumFixture.java =================================================================== --- branches/READ_CACHE/bigdata/src/test/com/bigdata/quorum/MockQuorumFixture.java 2013-05-20 17:11:14 UTC (rev 7149) +++ branches/READ_CACHE/bigdata/src/test/com/bigdata/quorum/MockQuorumFixture.java 2013-05-20 17:13:24 UTC (rev 7150) @@ -60,7 +60,6 @@ import com.bigdata.ha.msg.IHALogRootBlocksRequest; import com.bigdata.ha.msg.IHALogRootBlocksResponse; import com.bigdata.ha.msg.IHARebuildRequest; -import com.bigdata.ha.msg.IHARootBlockResponse; import com.bigdata.ha.msg.IHASendStoreResponse; import com.bigdata.ha.msg.IHASyncRequest; import com.bigdata.ha.msg.IHAWriteMessage; @@ -195,11 +194,11 @@ private final ConcurrentHashMap<UUID, QuorumMember<?>> known = new ConcurrentHashMap<UUID, QuorumMember<?>>(); /** - * An {@link Executor} which can be used by the unit tests. + * An {@link ExecutorService} which can be used by the unit tests. * * @see QuorumMember#getExecutor() */ - public Executor getExecutor() { + public ExecutorService getExecutor() { return executorService; } @@ -1208,10 +1207,12 @@ } } - public Executor getExecutor() { + @Override + public ExecutorService getExecutor() { return executorService; } + @Override public S getService() { return service; } Modified: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/quorum/zk/MockQuorumMember.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/quorum/zk/MockQuorumMember.java 2013-05-20 17:11:14 UTC (rev 7149) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/quorum/zk/MockQuorumMember.java 2013-05-20 17:13:24 UTC (rev 7150) @@ -95,7 +95,7 @@ } } - public Executor getExecutor() { + public ExecutorService getExecutor() { return executorService; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-20 17:11:20
|
Revision: 7149 http://bigdata.svn.sourceforge.net/bigdata/?rev=7149&view=rev Author: thompsonbry Date: 2013-05-20 17:11:14 +0000 (Mon, 20 May 2013) Log Message: ----------- Added alternate constructor. Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/util/ClocksNotSynchronizedException.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/util/ClocksNotSynchronizedException.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/util/ClocksNotSynchronizedException.java 2013-05-20 17:10:50 UTC (rev 7148) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/util/ClocksNotSynchronizedException.java 2013-05-20 17:11:14 UTC (rev 7149) @@ -25,7 +25,8 @@ /** * An instance of this class is thrown if we observe that the timestamps - * generated by two services violate a requirement for synchronized clocks. + * generated by two or more services violate a requirement for synchronized + * clocks. * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> */ @@ -36,4 +37,12 @@ */ private static final long serialVersionUID = 1L; + public ClocksNotSynchronizedException() { + super(); + } + + public ClocksNotSynchronizedException(String msg) { + super(msg); + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-20 17:10:57
|
Revision: 7148 http://bigdata.svn.sourceforge.net/bigdata/?rev=7148&view=rev Author: thompsonbry Date: 2013-05-20 17:10:50 +0000 (Mon, 20 May 2013) Log Message: ----------- ClientFuture : Modified cancel() to report [false] immediately if the Future is already done. Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/service/proxy/ClientFuture.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/service/proxy/ClientFuture.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/service/proxy/ClientFuture.java 2013-05-20 17:08:39 UTC (rev 7147) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/service/proxy/ClientFuture.java 2013-05-20 17:10:50 UTC (rev 7148) @@ -134,6 +134,17 @@ */ public boolean cancel(final boolean mayInterruptIfRunning) { + if (done) { + + /* + * The task could not be cancelled (because it is already known to + * be done). + */ + + return false; + + } + try { return proxy.cancel(mayInterruptIfRunning); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-20 17:08:45
|
Revision: 7147 http://bigdata.svn.sourceforge.net/bigdata/?rev=7147&view=rev Author: thompsonbry Date: 2013-05-20 17:08:39 +0000 (Mon, 20 May 2013) Log Message: ----------- license header typo Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumPipeline.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumPipeline.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumPipeline.java 2013-05-18 13:12:53 UTC (rev 7146) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumPipeline.java 2013-05-20 17:08:39 UTC (rev 7147) @@ -1,6 +1,6 @@ /** -wCopyright (C) SYSTAP, LLC 2006-2010. All rights reserved. +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. Contact: SYSTAP, LLC This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-18 13:12:59
|
Revision: 7146 http://bigdata.svn.sourceforge.net/bigdata/?rev=7146&view=rev Author: thompsonbry Date: 2013-05-18 13:12:53 +0000 (Sat, 18 May 2013) Log Message: ----------- cleanup serviceId in /status for pipeline display. Modified Paths: -------------- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-18 13:07:04 UTC (rev 7145) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-18 13:12:53 UTC (rev 7146) @@ -1795,9 +1795,9 @@ + journal.getRootBlockView().getCommitCounter()); innerRunStateStr.append(", haReady=" + getHAReady()); innerRunStateStr.append(", haStatus=" + getHAStatus()); - innerRunStateStr - .append(", serviceId=" + quorumService == null ? "N/A" - : quorumService.getServiceId()); + innerRunStateStr.append(", serviceId=" + + (quorumService == null ? "N/A" : quorumService + .getServiceId())); /* * TODO This is not a TXS timestamp. That would be more useful but I * want to avoid taking the TXS lock. [It looks like the TXS does This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-18 13:07:13
|
Revision: 7145 http://bigdata.svn.sourceforge.net/bigdata/?rev=7145&view=rev Author: thompsonbry Date: 2013-05-18 13:07:04 +0000 (Sat, 18 May 2013) Log Message: ----------- Bug fix for the consensus releaseTime protocol. It was hitting a clock skew error and then failing to message back to the leader with an appropriate response such that the barrier would break and the commit could either proceed or be rejected. @see https://sourceforge.net/apps/trac/bigdata/ticket/677 (HA deadlock under UPDATE + QUERY) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHA3JournalServer.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-18 11:52:12 UTC (rev 7144) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-18 13:07:04 UTC (rev 7145) @@ -7010,12 +7010,15 @@ public void gatherMinimumVisibleCommitTime( final IHAGatherReleaseTimeRequest req) throws IOException { - if (haLog.isInfoEnabled()) haLog.info("req=" + req); + if (haLog.isInfoEnabled()) + haLog.info("req=" + req); // Clear the old outcome. Reference SHOULD be null. Ensure not running. final Future<Void> oldFuture = gatherFuture.getAndSet(null); - if(oldFuture!=null&&!oldFuture.isDone()) oldFuture.cancel(true/*mayInterruptIfRunning*/); + if (oldFuture != null && !oldFuture.isDone()) + oldFuture.cancel(true/* mayInterruptIfRunning */); + final Callable<Void> task = ((AbstractHATransactionService) AbstractJournal.this .getLocalTransactionManager() .getTransactionService()) @@ -7038,12 +7041,48 @@ final IHANotifyReleaseTimeRequest req) throws IOException, InterruptedException, BrokenBarrierException { + /* + * Note: Pass through [req] without checks. We need to get this + * message to the CyclicBarrier regardless of whether it is + * well-formed or valid. + */ + return ((HATXSGlue) AbstractJournal.this .getLocalTransactionManager().getTransactionService()) .notifyEarliestCommitTime(req); } + + /** + * This exposes the clock used to assign transaction identifiers and + * commit times. It is being exposed to support certain kinds of + * overrides for unit tests. + * <p> + * Note: This method is NOT exposed to RMI. However, it can still be + * overridden by the unit tests. + * + * @return The next timestamp from that clock. + */ + public long nextTimestamp() { + try { + + return AbstractJournal.this.getLocalTransactionManager() + .getTransactionService().nextTimestamp(); + + } catch (IOException ex) { + + /* + * Note: This is a local method call. IOException will not be + * thrown. + */ + + throw new RuntimeException(ex); + + } + + } + /* * IService */ Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-18 11:52:12 UTC (rev 7144) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-18 13:07:04 UTC (rev 7145) @@ -362,7 +362,17 @@ /** * The message from each of those followers providing their local - * earliest visible commit point. + * earliest visible commit point. + * <p> + * Note: The {@link ConcurrentHashMap} does NOT allow <code>null</code> + * values. Further the {@link IHANotifyReleaseTimeRequest} specifies the + * serviceId of the follower. Therefore, a follower whose + * {@link GatherTask} fails MUST provide a "mock" + * {@link IHANotifyReleaseTimeRequest} that it will use to wait at the + * {@link CyclicBarrier}. + * + * @see InnerJournalTransactionService#notifyEarliestCommitTime(IHANotifyReleaseTimeRequest) + * @see GatherTask */ final private Map<UUID, IHANotifyReleaseTimeRequest> responses = new ConcurrentHashMap<UUID, IHANotifyReleaseTimeRequest>(); @@ -1347,12 +1357,26 @@ this.req = req; } - + + /** + * Note: This needs to be robust to most kinds of errors. However, + * if the quorum breaks (leader leaves) of if a follower leaves that + * was joined with the met quorum as of the atomic decision point in + * commitNow(), then that change will be detected by the leader and + * it will break the {@link CyclicBarrier}. + */ public Void call() throws Exception { if (log.isInfoEnabled()) log.info("Running gather on follower"); + /* + * These variables are set in the try {} below. If we can + * discover the leader, then we will eventually respond either + * in the try{} or in the finally{}. + */ + long now = 0L; + UUID serviceId = null; HAGlue leader = null; boolean didNotifyLeader = false; @@ -1361,27 +1385,59 @@ try { - // This timestamp is used to help detect clock skew. - final long now = nextTimestamp(); - - // Verify event on leader occurs before event on follower. - assertBefore(req.getTimestampOnLeader(), now); - final long token = req.token(); + /* + * we do not need to handle the case where the token is + * invalid. The leader will reset() the CylicBarrier for + * this case. + */ getQuorum().assertQuorum(token); + /* + * If the quorumService is null because this service is + * shutting down then the leader will notice the + * serviceLeave() and reset() the CyclicBarrier. + */ final QuorumService<HAGlue> quorumService = getQuorum() .getClient(); + // The serviceId for this service. + serviceId = quorumService.getServiceId(); + + /* + * This timestamp is used to help detect clock skew. + * + * Note: This deliberately uses the (non-remote) + * nextTimestamp() method on BasicHA. This is being done so + * we can write a unit test of the GatherTask that imposes + * clock skew by overridding the next value to be returned + * by that method. + */ + now = ((BasicHA)quorumService.getService()).nextTimestamp(); + + /* + * If the token is invalid, making it impossible for us to + * discover and message the leader, then then leader will + * reset() the CyclicBarrier. + */ + leader = quorumService.getLeader(token); + + /* + * Note: At this point we have everything we need to form up + * our response. If we hit an assertion, we will still + * respond in the finally {} block below. + */ + + /* Verify event on leader occurs before event on follower. + */ + assertBefore(req.getTimestampOnLeader(), now); + if (!quorumService.isFollower(token)) throw new QuorumException(); - leader = quorumService.getLeader(token); + final IHANotifyReleaseTimeRequest req2 = newHANotifyReleaseTimeRequest(serviceId); - final IHANotifyReleaseTimeRequest req2 = newHANotifyReleaseTimeRequest(quorumService - .getServiceId()); - /* * RMI to leader. * @@ -1464,12 +1520,16 @@ if (!didNotifyLeader && leader != null) { /* - * Send a [null] to the leader so it does not block - * forever waiting for our response. + * Send mock response to the leader so it does not block + * forever waiting for our response. The mock response MUST + * include our correct serviceId. */ try { - leader.notifyEarliestCommitTime(null/* resp */); + final IHANotifyReleaseTimeRequest resp = new HANotifyReleaseTimeRequest( + serviceId, 0L/* pinnedCommitTime */, + 1L/* pinnedCommitCounter */, now/* timestamp */); + leader.notifyEarliestCommitTime(resp); } catch (Throwable t2) { log.error(t2, t2); } @@ -1503,18 +1563,33 @@ * request as this barrier instance. That will let us detect a service * that responds late (after a transient disconnect) when the leader has * moved on to another commit. See BarrierState#token for more on this. - * [Note that [req] can be [null if the follower was unable to produce a - * valid response.] + * [Note that [req] can not safely be [null] since the follower must + * self-report its serviceId.] */ @Override public IHANotifyReleaseTimeResponse notifyEarliestCommitTime( final IHANotifyReleaseTimeRequest req) throws IOException, InterruptedException, BrokenBarrierException { + /* + * Note: Do NOT error check [req] until we are in the try{} / + * finally {} below that will do the CyclicBarrier.await(). + */ + final BarrierState barrierState = barrierRef.get(); - if (barrierState == null) + if (barrierState == null) { + + /* + * If the BarrierState reference has been cleared then it is not + * possible for us to count down at the barrier for this message + * (since the CyclicBarrier is gone). Otherwise, we will await() + * at the CyclicBarrier regardless of the message. + */ + throw new IllegalStateException(); + + } try { @@ -1534,6 +1609,9 @@ * Note: We want to await() on the barrier even if there is an * error in the try{} block. This is necessary to decrement the * barrier count down to zero. + * + * TODO If there is an error, we could reset() the barrier + * instead. */ // follower blocks on Thread on the leader here. @@ -1545,9 +1623,10 @@ final IHANotifyReleaseTimeResponse resp = barrierState.consensus; if (resp == null) { - - throw new RuntimeException("No consensus"); - + /* + * Log error, but return anyway. + */ + haLog.error("No consensus"); } return resp; Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-18 11:52:12 UTC (rev 7144) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-18 13:07:04 UTC (rev 7145) @@ -1795,6 +1795,16 @@ + journal.getRootBlockView().getCommitCounter()); innerRunStateStr.append(", haReady=" + getHAReady()); innerRunStateStr.append(", haStatus=" + getHAStatus()); + innerRunStateStr + .append(", serviceId=" + quorumService == null ? "N/A" + : quorumService.getServiceId()); + /* + * TODO This is not a TXS timestamp. That would be more useful but I + * want to avoid taking the TXS lock. [It looks like the TXS does + * not need that synchronized keyword on nextTimestamp(). Try + * removing it and then using it here.] + */ + innerRunStateStr.append(", now=" + System.currentTimeMillis()); final String msg = server.getOperatorAlert(); if (msg != null) innerRunStateStr.append(", msg=[" + msg + "]"); Modified: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java 2013-05-18 11:52:12 UTC (rev 7144) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java 2013-05-18 13:07:04 UTC (rev 7145) @@ -42,6 +42,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; @@ -185,6 +186,22 @@ */ public void voteNo() throws IOException; + /** + * Set the next value to be reported by {@link BasicHA#nextTimestamp()}. + * <p> + * Note: Only a few specific methods call against + * {@link BasicHA#nextTimestamp()}. They do so precisely because they + * were written to allow us to override the clock in the test suite + * using this method. + * + * @param nextTimestamp + * when <code>-1L</code> the behavior will revert to the + * default. Any other value will be the next value reported + * by {@link BasicHA#nextTimestamp()}, after which the + * behavior will revert to the default. + */ + public void setNextTimestamp(long nextTimestamp) throws IOException; + } /** @@ -314,6 +331,8 @@ */ private final AtomicBoolean voteNo = new AtomicBoolean(false); + private final AtomicLong nextTimestamp = new AtomicLong(-1L); + private HAGlueTestImpl(final UUID serviceId) { super(serviceId); @@ -374,7 +393,14 @@ public void voteNo() throws IOException { voteNo.set(true); } + + @Override + public void setNextTimestamp(long nextTimestamp) throws IOException { + this.nextTimestamp.set(nextTimestamp); + + } + /** * Conditionally fail the method if (a) it is registered in the * {@link #failSet} and (b) it is due to fail on this invocation. @@ -720,7 +746,28 @@ return super.notifyEarliestCommitTime(req); } + + /** + * {@inheritDoc} + * <p> + * Note: This is NOT an RMI method, but we want to be able to override + * it anyway to test the releaseTime consensus protocol. + */ + @Override + public long nextTimestamp() { + final long t = nextTimestamp.getAndSet(-1L); + + if (t == -1L) { + + return super.nextTimestamp(); + + } + + return t; + + } + /* * HACommitGlue */ Modified: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHA3JournalServer.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHA3JournalServer.java 2013-05-18 11:52:12 UTC (rev 7144) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHA3JournalServer.java 2013-05-18 13:07:04 UTC (rev 7145) @@ -550,6 +550,24 @@ } /** + * This stress test was written after seeing rare failures in + * testStartAB_C_MultiTransactionResync_5tx_then_200ms_delay. + * + * Currently it offers a reliable failure. + * + * @throws Exception + */ + public void _testStressStartAB_C_MultiTransactionResync() + throws Exception { + + for (int i = 0; i < 50; i++) { + doStartAB_C_MultiTransactionResync(200, 5); + destroyAll(); + } + + } + + /** * Test where C starts after <i>initialTransactions</i> on A+B. A series of * transactions are issued with the specified delay. * Modified: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java 2013-05-18 11:52:12 UTC (rev 7144) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java 2013-05-18 13:07:04 UTC (rev 7145) @@ -27,6 +27,7 @@ package com.bigdata.journal.jini.ha; import java.util.UUID; +import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -36,6 +37,7 @@ import com.bigdata.ha.HAGlue; import com.bigdata.ha.HAStatusEnum; import com.bigdata.ha.msg.IHA2PhasePrepareMessage; +import com.bigdata.ha.msg.IHANotifyReleaseTimeRequest; import com.bigdata.journal.jini.ha.HAJournalTest.HAGlueTest; import com.bigdata.journal.jini.ha.HAJournalTest.SpuriousTestException; import com.bigdata.util.InnerCause; @@ -263,7 +265,7 @@ awaitCommitCounter(2L, startup.serverA, startup.serverC); /* - * FIXME Unlike the test above, if there is a problem making the RMI + * Note: Unlike the test above, if there is a problem making the RMI * call, then B will not go through its doRejectedCommit() handler and * will not enter the ERROR state directly. We need to have B notice * that it is no longer at the same commit point, e.g., by observing a @@ -273,20 +275,20 @@ * does not know that there was an attempt to PREPARE since it did not * get the prepare2Phase() message. * - * - Modify HAJournalServer to enter the error state if we observe a + * - Modified HAJournalServer to enter the error state if we observe a * live write cache block for a commitCounter != the expected * commitCounter. * - * - Modify commit2Phase() to accept the #of services that are + * - Modified commit2Phase() to accept the #of services that are * participating in the commit. If it is not a full quorum, then we can * not purge the HA logs in commit2Phase() regardless of what the quorum * state looks like. * - * - Modify this test to do another transaction. B can not notice the + * - Modified this test to do another transaction. B can not notice the * problem until there is another write cache flushed through the * pipeline. * - * - Modify this test to await B to move to the end of the pipeline, + * - Modified this test to await B to move to the end of the pipeline, * resync, and rejoin. */ @@ -320,5 +322,122 @@ assertEquals(token, quorum.token()); } - + + /** + * This test forces clock skew on one of the followers causing it to + * encounter an error in its GatherTask. This models the problem that was + * causing a deadlock in an HA3 cluster with BSBM UPDATE running on the + * leader (EXPLORE was running on the follower, but analysis of the root + * cause shows that this was not required to trip the deadlock). The + * deadlock was caused by clock skew resulting in an exception and either + * {@link IHANotifyReleaseTimeRequest} message that was <code>null</code> + * and thus could not be processed or a failure to send that message back to + * the leader. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/677" > HA + * deadlock under UPDATE + QUERY </a> + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/673" > DGC + * in release time consensus protocol causes native thread leak in + * HAJournalServer at each commit </a> + */ + public void testStartABC_releaseTimeConsensusProtocol_clockSkew() + throws Exception { + + // Enforce the join order. + final ABC startup = new ABC(true /*sequential*/); + + final long token = awaitFullyMetQuorum(); + + // Should be one commit point. + awaitCommitCounter(1L, startup.serverA, startup.serverB, + startup.serverC); + + /* + * Setup B with a significant clock skew to force an error during the + * GatherTask. + */ + ((HAGlueTest) startup.serverB).setNextTimestamp(10L); + + try { + + // Simple transaction. + simpleTransaction(); + + } catch (Throwable t) { + /* + * TODO This test is currently failing because the consensus + * releaseTime protocol will fail if one of the joined services + * reports an error. The protocol should be robust to an error and + * move forward if a consensus can be formed. If a consensus can not + * be formed (due to some curable error), then any queries running + * on that service should break (force a service leave). Else, if + * the remaining services were to advance the release time since + * otherwise the service could not get through another releaseTime + * consensus protocol exchange successfully if it is reading on a + * commit point that has been released by the other services. + */ + if (!InnerCause.isInnerCause(t, BrokenBarrierException.class)) { + /* + * Wrong inner cause. + */ + fail("Expecting " + BrokenBarrierException.class, t); + } + + } + + // Should be one commit point. + awaitCommitCounter(1L, startup.serverA, startup.serverB, + startup.serverC); + + final long token1 = awaitFullyMetQuorum(); + + /* + * Should have formed a new quorum (each service should have done a + * rejected commit, forced a service leave, and then cured that error + * through seek consensus). + */ + assertEquals(token + 1, token1); + +// // Verify quorum is unchanged. +// assertEquals(token, quorum.token()); +// +// // Should be two commit points on {A,C]. +// awaitCommitCounter(2L, startup.serverA, startup.serverC); +// +// // Should be ONE commit points on {B}. +// awaitCommitCounter(1L, startup.serverB); +// +// /* +// * We use a simple transaction to force B to notice that it missed a +// * commit. B will notice that it did not join in the 2-phase commit when +// * the next live write cache block flows through the pipeline and it is +// * associated with a commitCounter that is GT the commitCounter which B +// * is expecting. That will force B into an Error state. From the Error +// * state, it will then resync and re-join the met quourm. +// */ +// simpleTransaction(); +// +// /* +// * The pipeline should be reordered. B will do a service leave, then +// * enter seek consensus, and then re-enter the pipeline. +// */ +// awaitPipeline(new HAGlue[] { startup.serverA, startup.serverC, +// startup.serverB }); +// +// /* +// * There should be three commit points on {A,C,B} (note that this assert +// * does not pay attention to the pipeline order). +// */ +// awaitCommitCounter(3L, startup.serverA, startup.serverC, +// startup.serverB); +// +// // B should be a follower again. +// awaitHAStatus(startup.serverB, HAStatusEnum.Follower); +// +// // quorum token is unchanged. +// assertEquals(token, quorum.token()); + + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-18 11:52:27
|
Revision: 7144 http://bigdata.svn.sourceforge.net/bigdata/?rev=7144&view=rev Author: thompsonbry Date: 2013-05-18 11:52:12 +0000 (Sat, 18 May 2013) Log Message: ----------- Merging from dev branch to the READ_CACHE branch. @see https://sourceforge.net/apps/trac/bigdata/ticket/530 (Journal HA) Modified Paths: -------------- branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java Added Paths: ----------- branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java Property Changed: ---------------- branches/READ_CACHE/ branches/READ_CACHE/bigdata/lib/jetty/ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/aggregate/ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/joinGraph/ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/util/ branches/READ_CACHE/bigdata/src/java/com/bigdata/htree/raba/ branches/READ_CACHE/bigdata/src/java/com/bigdata/jsr166/ branches/READ_CACHE/bigdata/src/test/com/bigdata/bop/joinGraph/ branches/READ_CACHE/bigdata/src/test/com/bigdata/bop/util/ branches/READ_CACHE/bigdata/src/test/com/bigdata/jsr166/ branches/READ_CACHE/bigdata/src/test/com/bigdata/util/httpd/ branches/READ_CACHE/bigdata-compatibility/ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/attr/ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/disco/ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/util/config/ branches/READ_CACHE/bigdata-perf/ branches/READ_CACHE/bigdata-perf/btc/ branches/READ_CACHE/bigdata-perf/btc/src/resources/ branches/READ_CACHE/bigdata-perf/lubm/ branches/READ_CACHE/bigdata-perf/uniprot/ branches/READ_CACHE/bigdata-perf/uniprot/src/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/changesets/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/error/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/internal/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/relation/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/util/ branches/READ_CACHE/bigdata-rdf/src/samples/ branches/READ_CACHE/bigdata-rdf/src/test/com/bigdata/bop/rdf/aggregate/ branches/READ_CACHE/bigdata-rdf/src/test/com/bigdata/rdf/internal/ branches/READ_CACHE/bigdata-rdf/src/test/com/bigdata/rdf/relation/ branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/bench/ branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/ branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/bench/ branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/ branches/READ_CACHE/dsi-utils/ branches/READ_CACHE/dsi-utils/LEGAL/ branches/READ_CACHE/dsi-utils/lib/ branches/READ_CACHE/dsi-utils/src/ branches/READ_CACHE/dsi-utils/src/java/ branches/READ_CACHE/dsi-utils/src/java/it/ branches/READ_CACHE/dsi-utils/src/java/it/unimi/ branches/READ_CACHE/dsi-utils/src/test/ branches/READ_CACHE/dsi-utils/src/test/it/unimi/ branches/READ_CACHE/dsi-utils/src/test/it/unimi/dsi/ branches/READ_CACHE/lgpl-utils/src/java/it/unimi/dsi/fastutil/bytes/custom/ branches/READ_CACHE/lgpl-utils/src/test/it/unimi/dsi/fastutil/bytes/custom/ branches/READ_CACHE/osgi/ branches/READ_CACHE/src/resources/bin/config/ Property changes on: branches/READ_CACHE ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE:6769-6785 /branches/BIGDATA_RELEASE_1_2_0:6766-7138 /branches/BTREE_BUFFER_BRANCH:2004-2045 /branches/DEV_BRANCH_27_OCT_2009:2270-2546,2548-2782 /branches/INT64_BRANCH:4486-4522 /branches/JOURNAL_HA_BRANCH:2596-4066 /branches/LARGE_LITERALS_REFACTOR:4175-4387 /branches/LEXICON_REFACTOR_BRANCH:2633-3304 /branches/QUADS_QUERY_BRANCH:4525-4531,4550-4584,4586-4609,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH:4814-4836 /branches/bugfix-btm:2594-3237 /branches/dev-btm:2574-2730 /branches/fko:3150-3194 /trunk:3392-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE:6769-6785 /branches/BIGDATA_RELEASE_1_2_0:6766-7143 /branches/BTREE_BUFFER_BRANCH:2004-2045 /branches/DEV_BRANCH_27_OCT_2009:2270-2546,2548-2782 /branches/INT64_BRANCH:4486-4522 /branches/JOURNAL_HA_BRANCH:2596-4066 /branches/LARGE_LITERALS_REFACTOR:4175-4387 /branches/LEXICON_REFACTOR_BRANCH:2633-3304 /branches/QUADS_QUERY_BRANCH:4525-4531,4550-4584,4586-4609,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH:4814-4836 /branches/bugfix-btm:2594-3237 /branches/dev-btm:2574-2730 /branches/fko:3150-3194 /trunk:3392-3437,3656-4061 Property changes on: branches/READ_CACHE/bigdata/lib/jetty ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/lib/jetty:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/jetty:6766-7138 /branches/INT64_BRANCH/bigdata/lib/jetty:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/lib/jetty:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/lib/jetty:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/lib/jetty:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/lib/jetty:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/jetty:6766-7143 /branches/INT64_BRANCH/bigdata/lib/jetty:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/lib/jetty:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/lib/jetty:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/lib/jetty:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/aggregate ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/bop/aggregate:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/aggregate:6766-7138 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/bop/aggregate:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/bop/aggregate:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/aggregate:6766-7143 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/bop/aggregate:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/joinGraph ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/bop/joinGraph:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/joinGraph:6766-7138 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/bop/joinGraph:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/joinGraph:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/bop/joinGraph:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/bop/joinGraph:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/bop/joinGraph:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/joinGraph:6766-7143 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/bop/joinGraph:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/joinGraph:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/bop/joinGraph:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/bop/joinGraph:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/util ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/bop/util:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/util:6766-7138 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/bop/util:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/util:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/bop/util:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/bop/util:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/bop/util:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/util:6766-7143 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/bop/util:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/util:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/bop/util:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/bop/util:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/java/com/bigdata/htree/raba ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/htree/raba:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/raba:6766-7138 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/htree/raba:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/htree/raba:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/htree/raba:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/htree/raba:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/htree/raba:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/raba:6766-7143 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/htree/raba:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/htree/raba:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/htree/raba:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/htree/raba:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/java/com/bigdata/jsr166 ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/jsr166:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/jsr166:6766-7138 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/jsr166:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/jsr166:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/jsr166:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/jsr166:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/jsr166:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/jsr166:6766-7143 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/jsr166:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/jsr166:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/jsr166:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/jsr166:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/test/com/bigdata/bop/joinGraph ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/test/com/bigdata/bop/joinGraph:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/joinGraph:6766-7138 /branches/INT64_BRANCH/bigdata/src/test/com/bigdata/bop/joinGraph:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/bop/joinGraph:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/test/com/bigdata/bop/joinGraph:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/test/com/bigdata/bop/joinGraph:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/test/com/bigdata/bop/joinGraph:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/joinGraph:6766-7143 /branches/INT64_BRANCH/bigdata/src/test/com/bigdata/bop/joinGraph:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/bop/joinGraph:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/test/com/bigdata/bop/joinGraph:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/test/com/bigdata/bop/joinGraph:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/test/com/bigdata/bop/util ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/test/com/bigdata/bop/util:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/util:6766-7138 /branches/INT64_BRANCH/bigdata/src/test/com/bigdata/bop/util:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/bop/util:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/test/com/bigdata/bop/util:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/test/com/bigdata/bop/util:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/test/com/bigdata/bop/util:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/util:6766-7143 /branches/INT64_BRANCH/bigdata/src/test/com/bigdata/bop/util:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/bop/util:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/test/com/bigdata/bop/util:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/test/com/bigdata/bop/util:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/test/com/bigdata/jsr166 ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/test/com/bigdata/jsr166:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/jsr166:6766-7138 /branches/INT64_BRANCH/bigdata/src/test/com/bigdata/jsr166:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/jsr166:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/test/com/bigdata/jsr166:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/test/com/bigdata/jsr166:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/test/com/bigdata/jsr166:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/jsr166:6766-7143 /branches/INT64_BRANCH/bigdata/src/test/com/bigdata/jsr166:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/jsr166:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/test/com/bigdata/jsr166:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/test/com/bigdata/jsr166:4814-4836 Property changes on: branches/READ_CACHE/bigdata/src/test/com/bigdata/util/httpd ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/test/com/bigdata/util/httpd:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/util/httpd:6766-7138 /branches/INT64_BRANCH/bigdata/src/test/com/bigdata/util/httpd:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/util/httpd:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/test/com/bigdata/util/httpd:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/test/com/bigdata/util/httpd:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/test/com/bigdata/util/httpd:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/util/httpd:6766-7143 /branches/INT64_BRANCH/bigdata/src/test/com/bigdata/util/httpd:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/util/httpd:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/test/com/bigdata/util/httpd:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/test/com/bigdata/util/httpd:4814-4836 Property changes on: branches/READ_CACHE/bigdata-compatibility ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-compatibility:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-compatibility:6766-7138 /branches/INT64_BRANCH/bigdata-compatibility:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-compatibility:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-compatibility:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-compatibility:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-compatibility:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-compatibility:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-compatibility:6766-7143 /branches/INT64_BRANCH/bigdata-compatibility:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-compatibility:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-compatibility:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-compatibility:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-compatibility:4814-4836 Property changes on: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/attr ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-jini/src/java/com/bigdata/attr:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-jini/src/java/com/bigdata/attr:6766-7138 /branches/BTREE_BUFFER_BRANCH/bigdata-jini/src/java/com/bigdata/attr:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-jini/src/java/com/bigdata/attr:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-jini/src/java/com/bigdata/attr:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-jini/src/java/com/bigdata/attr:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-jini/src/java/com/bigdata/attr:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-jini/src/java/com/bigdata/attr:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-jini/src/java/com/bigdata/attr:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-jini/src/java/com/bigdata/attr:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-jini/src/java/com/bigdata/attr:4814-4836 /branches/bugfix-btm/bigdata-jini/src/java/com/bigdata/attr:2594-3237 /branches/dev-btm/bigdata-jini/src/java/com/bigdata/attr:2574-2730 /branches/fko/bigdata-jini/src/java/com/bigdata/attr:3150-3194 /trunk/bigdata-jini/src/java/com/bigdata/attr:2981-3282,3368-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-jini/src/java/com/bigdata/attr:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-jini/src/java/com/bigdata/attr:6766-7143 /branches/BTREE_BUFFER_BRANCH/bigdata-jini/src/java/com/bigdata/attr:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-jini/src/java/com/bigdata/attr:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-jini/src/java/com/bigdata/attr:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-jini/src/java/com/bigdata/attr:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-jini/src/java/com/bigdata/attr:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-jini/src/java/com/bigdata/attr:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-jini/src/java/com/bigdata/attr:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-jini/src/java/com/bigdata/attr:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-jini/src/java/com/bigdata/attr:4814-4836 /branches/bugfix-btm/bigdata-jini/src/java/com/bigdata/attr:2594-3237 /branches/dev-btm/bigdata-jini/src/java/com/bigdata/attr:2574-2730 /branches/fko/bigdata-jini/src/java/com/bigdata/attr:3150-3194 /trunk/bigdata-jini/src/java/com/bigdata/attr:2981-3282,3368-3437,3656-4061 Property changes on: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/disco ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-jini/src/java/com/bigdata/disco:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-jini/src/java/com/bigdata/disco:6766-7138 /branches/BTREE_BUFFER_BRANCH/bigdata-jini/src/java/com/bigdata/disco:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-jini/src/java/com/bigdata/disco:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-jini/src/java/com/bigdata/disco:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-jini/src/java/com/bigdata/disco:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-jini/src/java/com/bigdata/disco:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-jini/src/java/com/bigdata/disco:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-jini/src/java/com/bigdata/disco:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-jini/src/java/com/bigdata/disco:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-jini/src/java/com/bigdata/disco:4814-4836 /branches/bugfix-btm/bigdata-jini/src/java/com/bigdata/disco:2594-3237 /branches/dev-btm/bigdata-jini/src/java/com/bigdata/disco:2574-2730 /branches/fko/bigdata-jini/src/java/com/bigdata/disco:3150-3194 /trunk/bigdata-jini/src/java/com/bigdata/disco:2981-3282,3368-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-jini/src/java/com/bigdata/disco:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-jini/src/java/com/bigdata/disco:6766-7143 /branches/BTREE_BUFFER_BRANCH/bigdata-jini/src/java/com/bigdata/disco:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-jini/src/java/com/bigdata/disco:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-jini/src/java/com/bigdata/disco:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-jini/src/java/com/bigdata/disco:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-jini/src/java/com/bigdata/disco:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-jini/src/java/com/bigdata/disco:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-jini/src/java/com/bigdata/disco:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-jini/src/java/com/bigdata/disco:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-jini/src/java/com/bigdata/disco:4814-4836 /branches/bugfix-btm/bigdata-jini/src/java/com/bigdata/disco:2594-3237 /branches/dev-btm/bigdata-jini/src/java/com/bigdata/disco:2574-2730 /branches/fko/bigdata-jini/src/java/com/bigdata/disco:3150-3194 /trunk/bigdata-jini/src/java/com/bigdata/disco:2981-3282,3368-3437,3656-4061 Property changes on: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/util/config ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-jini/src/java/com/bigdata/util/config:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-jini/src/java/com/bigdata/util/config:6766-7138 /branches/BTREE_BUFFER_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-jini/src/java/com/bigdata/util/config:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-jini/src/java/com/bigdata/util/config:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-jini/src/java/com/bigdata/util/config:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:4814-4836 /branches/bugfix-btm/bigdata-jini/src/java/com/bigdata/util/config:2594-3237 /branches/dev-btm/bigdata-jini/src/java/com/bigdata/util/config:2574-2730 /branches/fko/bigdata-jini/src/java/com/bigdata/util/config:3150-3194 /trunk/bigdata-jini/src/java/com/bigdata/util/config:2981-3282,3368-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-jini/src/java/com/bigdata/util/config:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-jini/src/java/com/bigdata/util/config:6766-7143 /branches/BTREE_BUFFER_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-jini/src/java/com/bigdata/util/config:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-jini/src/java/com/bigdata/util/config:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-jini/src/java/com/bigdata/util/config:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-jini/src/java/com/bigdata/util/config:4814-4836 /branches/bugfix-btm/bigdata-jini/src/java/com/bigdata/util/config:2594-3237 /branches/dev-btm/bigdata-jini/src/java/com/bigdata/util/config:2574-2730 /branches/fko/bigdata-jini/src/java/com/bigdata/util/config:3150-3194 /trunk/bigdata-jini/src/java/com/bigdata/util/config:2981-3282,3368-3437,3656-4061 Property changes on: branches/READ_CACHE/bigdata-perf ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf:6766-7138 /branches/BTREE_BUFFER_BRANCH/bigdata-perf:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-perf:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-perf:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-perf:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-perf:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf:4814-4836 /branches/bugfix-btm/bigdata-perf:2594-3237 /branches/dev-btm/bigdata-perf:2574-2730 /branches/fko/bigdata-perf:3150-3194 /trunk/bigdata-perf:2981-3043,3368-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf:6766-7143 /branches/BTREE_BUFFER_BRANCH/bigdata-perf:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-perf:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-perf:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-perf:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-perf:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf:4814-4836 /branches/bugfix-btm/bigdata-perf:2594-3237 /branches/dev-btm/bigdata-perf:2574-2730 /branches/fko/bigdata-perf:3150-3194 /trunk/bigdata-perf:2981-3043,3368-3437,3656-4061 Property changes on: branches/READ_CACHE/bigdata-perf/btc ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/btc:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/btc:6766-7138 /branches/INT64_BRANCH/bigdata-perf/btc:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf/btc:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/btc:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/btc:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/btc:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/btc:4814-4836 /trunk/bigdata-perf/btc:2981-3043,3368-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/btc:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/btc:6766-7143 /branches/INT64_BRANCH/bigdata-perf/btc:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf/btc:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/btc:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/btc:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/btc:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/btc:4814-4836 /trunk/bigdata-perf/btc:2981-3043,3368-3437,3656-4061 Property changes on: branches/READ_CACHE/bigdata-perf/btc/src/resources ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/btc/src/resources:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/btc/src/resources:6766-7138 /branches/INT64_BRANCH/bigdata-perf/btc/src/resources:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf/btc/src/resources:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/btc/src/resources:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/btc/src/resources:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/btc/src/resources:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/btc/src/resources:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/btc/src/resources:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/btc/src/resources:6766-7143 /branches/INT64_BRANCH/bigdata-perf/btc/src/resources:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf/btc/src/resources:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/btc/src/resources:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/btc/src/resources:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/btc/src/resources:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/btc/src/resources:4814-4836 Property changes on: branches/READ_CACHE/bigdata-perf/lubm ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/lubm:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/lubm:6766-7138 /branches/INT64_BRANCH/bigdata-perf/lubm:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/lubm:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/lubm:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/lubm:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/lubm:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/lubm:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/lubm:6766-7143 /branches/INT64_BRANCH/bigdata-perf/lubm:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/lubm:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/lubm:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/lubm:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/lubm:4814-4836 Property changes on: branches/READ_CACHE/bigdata-perf/uniprot ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/uniprot:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/uniprot:6766-7138 /branches/INT64_BRANCH/bigdata-perf/uniprot:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf/uniprot:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/uniprot:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/uniprot:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/uniprot:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/uniprot:4814-4836 /trunk/bigdata-perf/uniprot:2981-3043,3368-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/uniprot:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/uniprot:6766-7143 /branches/INT64_BRANCH/bigdata-perf/uniprot:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf/uniprot:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/uniprot:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/uniprot:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/uniprot:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/uniprot:4814-4836 /trunk/bigdata-perf/uniprot:2981-3043,3368-3437,3656-4061 Property changes on: branches/READ_CACHE/bigdata-perf/uniprot/src ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/uniprot/src:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/uniprot/src:6766-7138 /branches/INT64_BRANCH/bigdata-perf/uniprot/src:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf/uniprot/src:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/uniprot/src:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/uniprot/src:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/uniprot/src:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/uniprot/src:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-perf/uniprot/src:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-perf/uniprot/src:6766-7143 /branches/INT64_BRANCH/bigdata-perf/uniprot/src:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-perf/uniprot/src:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-perf/uniprot/src:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-perf/uniprot/src:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-perf/uniprot/src:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-perf/uniprot/src:4814-4836 Property changes on: branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:6766-7138 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:6766-7143 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate:4814-4836 Property changes on: branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/changesets ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/changesets:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/changesets:6766-7138 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/changesets:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/java/com/bigdata/rdf/changesets:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/changesets:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/changesets:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/changesets:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/changesets:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/changesets:6766-7143 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/changesets:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/java/com/bigdata/rdf/changesets:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/changesets:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/changesets:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/changesets:4814-4836 Property changes on: branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/error ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/error:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/error:6766-7138 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/error:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/error:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/error:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/error:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/error:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/error:6766-7143 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/error:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/error:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/error:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/error:4814-4836 Property changes on: branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/internal ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/internal:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/internal:6766-7138 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/internal:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/java/com/bigdata/rdf/internal:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/internal:4525-4531,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/internal:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/internal:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/internal:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/internal:6766-7143 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/internal:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/java/com/bigdata/rdf/internal:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/internal:4525-4531,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/internal:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/internal:4814-4836 Property changes on: branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/relation ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/relation:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/relation:6766-7138 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/relation:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/java/com/bigdata/rdf/relation:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/relation:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/relation:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/relation:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/relation:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/relation:6766-7143 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/relation:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/java/com/bigdata/rdf/relation:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/relation:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/relation:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/relation:4814-4836 Copied: branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java (from rev 7143, branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java) =================================================================== --- branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java (rev 0) +++ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java 2013-05-18 11:52:12 UTC (rev 7144) @@ -0,0 +1,288 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Sep 9, 2011 + */ + +package com.bigdata.rdf.sparql.ast.eval; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.openrdf.model.Resource; +import org.openrdf.model.URI; +import org.openrdf.model.Value; +import org.openrdf.model.impl.URIImpl; + +import com.bigdata.bop.BOp; +import com.bigdata.bop.BOpContextBase; +import com.bigdata.bop.Constant; +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IConstant; +import com.bigdata.bop.IPredicate; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.NV; +import com.bigdata.bop.ap.SampleIndex; +import com.bigdata.bop.bindingSet.EmptyBindingSet; +import com.bigdata.bop.bindingSet.ListBindingSet; +import com.bigdata.bop.fed.QueryEngineFactory; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.sparql.ast.GroupNodeBase; +import com.bigdata.rdf.sparql.ast.IGroupMemberNode; +import com.bigdata.rdf.sparql.ast.TermNode; +import com.bigdata.rdf.sparql.ast.eval.SampleServiceFactory.SampleParams; +import com.bigdata.rdf.sparql.ast.service.BigdataNativeServiceOptions; +import com.bigdata.rdf.sparql.ast.service.BigdataServiceCall; +import com.bigdata.rdf.sparql.ast.service.IServiceOptions; +import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams; +import com.bigdata.rdf.sparql.ast.service.ServiceFactory; +import com.bigdata.rdf.sparql.ast.service.ServiceNode; +import com.bigdata.rdf.spo.ISPO; +import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.store.BD; +import com.bigdata.relation.accesspath.EmptyCloseableIterator; +import com.bigdata.relation.accesspath.ThickCloseableIterator; +import com.bigdata.striterator.ICloseableIterator; + +/** + * A factory for a service that simulates the VALUES syntax in SPARQL: + * + * service bd:values { + * # service params + * bd:serviceParam bd:values.var ?var . + * bd:serviceParam bd:values.val "val1" . + * bd:serviceParam bd:values.val "val2" . + * ... + * } + */ +public class ValuesServiceFactory extends AbstractServiceFactory + implements ServiceFactory { + + private static final Logger log = Logger + .getLogger(ValuesServiceFactory.class); + + /** + * The URI service key. + */ + public static final URI SERVICE_KEY = new URIImpl(BD.NAMESPACE+"values"); + + /** + * The service params for this service. + */ + public static interface ValuesParams { + + /** + * The limit on the sample. + */ + URI VAR = new URIImpl(SERVICE_KEY.stringValue() + ".var"); + + /** + * The seed on the sample. + */ + URI VAL = new URIImpl(SERVICE_KEY.stringValue() + ".val"); + + } + + + /* + * Note: This could extend the base class to allow for search service + * configuration options. + */ + private final BigdataNativeServiceOptions serviceOptions; + + public ValuesServiceFactory() { + + serviceOptions = new BigdataNativeServiceOptions(); + serviceOptions.setRunFirst(true); + + } + + @Override + public BigdataNativeServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + public BigdataServiceCall create( + final ServiceCallCreateParams params, + final ServiceParams serviceParams) { + + final AbstractTripleStore store = params.getTripleStore(); + + final ServiceNode serviceNode = params.getServiceNode(); + + /* + * Validate the predicates for a given service call. + */ + verifyGraphPattern(store, serviceNode.getGraphPattern(), serviceParams); + + /* + * Create and return the ServiceCall object which will execute this + * query. + */ + return new ValuesCall(store, getServiceOptions(), serviceParams); + + } + + /** + * Verify that there is only a single statement pattern node and that the + * service parameters are valid. + */ + private void verifyGraphPattern( + final AbstractTripleStore database, + final GroupNodeBase<IGroupMemberNode> group, + final ServiceParams serviceParams) { + + final Iterator<Map.Entry<URI, List<TermNode>>> it = serviceParams.iterator(); + + if (!serviceParams.contains(ValuesParams.VAR)) { + + throw new RuntimeException("must provide a variable for: " + ValuesParams.VAR); + + } + + if (!serviceParams.contains(ValuesParams.VAL)) { + + throw new RuntimeException("must provide at least one value for: " + ValuesParams.VAL); + + } + + while (it.hasNext()) { + + final URI param = it.next().getKey(); + + if (ValuesParams.VAR.equals(param)) { + + final List<TermNode> vars = serviceParams.get(param); + + if (vars == null || vars.size() != 1 || vars.get(0).isConstant()) { + throw new RuntimeException("must provide exactly one variable for: " + param); + } + + } else if (ValuesParams.VAL.equals(param)) { + + final List<TermNode> vals = serviceParams.get(param); + + if (vals == null || vals.size() == 0) { + throw new RuntimeException("must provide at least one value for: " + param); + } + + for (TermNode val : vals) { + if (val.isVariable()) { + throw new RuntimeException("must provide constant values for: " + param); + } + } + + } else { + + throw new RuntimeException("unrecognized param: " + param); + + } + + } + + } + + /** + * + * Note: This has the {@link AbstractTripleStore} reference attached. This + * is not a {@link Serializable} object. It MUST run on the query + * controller. + */ + private static class ValuesCall implements BigdataServiceCall { + + private final AbstractTripleStore db; + private final IServiceOptions serviceOptions; + private final ServiceParams serviceParams; + + public ValuesCall( + final AbstractTripleStore db, + final IServiceOptions serviceOptions, + final ServiceParams serviceParams) { + + if(db == null) + throw new IllegalArgumentException(); + + if(serviceOptions == null) + throw new IllegalArgumentException(); + + if(serviceParams == null) + throw new IllegalArgumentException(); + + this.db = db; + this.serviceOptions = serviceOptions; + this.serviceParams = serviceParams; + + } + + /** + * Run a sample index op over the access path. + */ + @Override + public ICloseableIterator<IBindingSet> call( + final IBindingSet[] bc) { + + if (log.isInfoEnabled()) { + log.info(bc.length); + log.info(Arrays.toString(bc)); + log.info(serviceParams); + } + + if (bc != null && bc.length > 0 && !bc[0].equals(EmptyBindingSet.INSTANCE)) { + throw new RuntimeException("cannot run with incoming bindings"); + } + + final IVariable<IV> var = serviceParams.getAsVar(ValuesParams.VAR); + + final List<TermNode> vals = serviceParams.get(ValuesParams.VAL); + + final IBindingSet[] bSets = new IBindingSet[vals.size()]; + + for (int i = 0; i < bSets.length; i++) { + + bSets[i] = new ListBindingSet(); + + bSets[i].set(var, (IConstant<IV>) vals.get(i).getValueExpression()); + + } + + return new ThickCloseableIterator<IBindingSet>(bSets, bSets.length); + + } + + @Override + public IServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + } + +} Modified: branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java =================================================================== --- branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java 2013-05-17 21:10:52 UTC (rev 7143) +++ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java 2013-05-18 11:52:12 UTC (rev 7144) @@ -10,13 +10,13 @@ import org.openrdf.model.URI; import org.openrdf.model.impl.URIImpl; -import com.bigdata.bop.ap.SampleIndex; import com.bigdata.rdf.sparql.ast.QueryHints; import com.bigdata.rdf.sparql.ast.cache.DescribeServiceFactory; import com.bigdata.rdf.sparql.ast.eval.SampleServiceFactory; import com.bigdata.rdf.sparql.ast.eval.SearchInSearchServiceFactory; import com.bigdata.rdf.sparql.ast.eval.SearchServiceFactory; import com.bigdata.rdf.sparql.ast.eval.SliceServiceFactory; +import com.bigdata.rdf.sparql.ast.eval.ValuesServiceFactory; import com.bigdata.rdf.sparql.ast.service.history.HistoryServiceFactory; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.rdf.store.BD; @@ -89,6 +89,9 @@ // Add the slice index service. add(SliceServiceFactory.SERVICE_KEY, new SliceServiceFactory()); + // Add the values service. + add(ValuesServiceFactory.SERVICE_KEY, new ValuesServiceFactory()); + if (QueryHints.DEFAULT_DESCRIBE_CACHE) { add(new URIImpl(BD.NAMESPACE + "describe"), Property changes on: branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/util ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/util:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/util:6766-7138 /branches/BTREE_BUFFER_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-rdf/src/java/com/bigdata/rdf/util:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/java/com/bigdata/rdf/util:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/util:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:4814-4836 /branches/bugfix-btm/bigdata-rdf/src/java/com/bigdata/rdf/util:2594-3237 /branches/dev-btm/bigdata-rdf/src/java/com/bigdata/rdf/util:2574-2730 /branches/fko/bigdata-rdf/src/java/com/bigdata/rdf/util:3150-3194 /trunk/bigdata-rdf/src/java/com/bigdata/rdf/util:2981-3110,3368-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/java/com/bigdata/rdf/util:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/util:6766-7143 /branches/BTREE_BUFFER_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:2004-2045 /branches/DEV_BRANCH_27_OCT_2009/bigdata-rdf/src/java/com/bigdata/rdf/util:2270-2546,2548-2782 /branches/INT64_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:4486-4522 /branches/JOURNAL_HA_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:2596-4066 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/java/com/bigdata/rdf/util:4175-4387 /branches/LEXICON_REFACTOR_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:2633-3304 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata-rdf/src/java/com/bigdata/rdf/util:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata-rdf/src/java/com/bigdata/rdf/util:4814-4836 /branches/bugfix-btm/bigdata-rdf/src/java/com/bigdata/rdf/util:2594-3237 /branches/dev-btm/bigdata-rdf/src/java/com/bigdata/rdf/util:2574-2730 /branches/fko/bigdata-rdf/src/java/com/bigdata/rdf/util:3150-3194 /trunk/bigdata-rdf/src/java/com/bigdata/rdf/util:2981-3110,3368-3437,3656-4061 Property changes on: branches/READ_CACHE/bigdata-rdf/src/samples ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata-rdf/src/samples:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/samples:6766-7138 /branches/INT64_BRANCH/bigdata-rdf/src/samples:4486-4522 /branches/LARGE_LITERALS_REFACTOR/bigdata-rdf/src/samples:4175-4387 /branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/samples:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/... [truncated message content] |
From: <mrp...@us...> - 2013-05-17 21:11:04
|
Revision: 7143 http://bigdata.svn.sourceforge.net/bigdata/?rev=7143&view=rev Author: mrpersonick Date: 2013-05-17 21:10:52 +0000 (Fri, 17 May 2013) Log Message: ----------- committing a ValuesService Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java 2013-05-17 21:10:52 UTC (rev 7143) @@ -0,0 +1,288 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Sep 9, 2011 + */ + +package com.bigdata.rdf.sparql.ast.eval; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.openrdf.model.Resource; +import org.openrdf.model.URI; +import org.openrdf.model.Value; +import org.openrdf.model.impl.URIImpl; + +import com.bigdata.bop.BOp; +import com.bigdata.bop.BOpContextBase; +import com.bigdata.bop.Constant; +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IConstant; +import com.bigdata.bop.IPredicate; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.NV; +import com.bigdata.bop.ap.SampleIndex; +import com.bigdata.bop.bindingSet.EmptyBindingSet; +import com.bigdata.bop.bindingSet.ListBindingSet; +import com.bigdata.bop.fed.QueryEngineFactory; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.sparql.ast.GroupNodeBase; +import com.bigdata.rdf.sparql.ast.IGroupMemberNode; +import com.bigdata.rdf.sparql.ast.TermNode; +import com.bigdata.rdf.sparql.ast.eval.SampleServiceFactory.SampleParams; +import com.bigdata.rdf.sparql.ast.service.BigdataNativeServiceOptions; +import com.bigdata.rdf.sparql.ast.service.BigdataServiceCall; +import com.bigdata.rdf.sparql.ast.service.IServiceOptions; +import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams; +import com.bigdata.rdf.sparql.ast.service.ServiceFactory; +import com.bigdata.rdf.sparql.ast.service.ServiceNode; +import com.bigdata.rdf.spo.ISPO; +import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.store.BD; +import com.bigdata.relation.accesspath.EmptyCloseableIterator; +import com.bigdata.relation.accesspath.ThickCloseableIterator; +import com.bigdata.striterator.ICloseableIterator; + +/** + * A factory for a service that simulates the VALUES syntax in SPARQL: + * + * service bd:values { + * # service params + * bd:serviceParam bd:values.var ?var . + * bd:serviceParam bd:values.val "val1" . + * bd:serviceParam bd:values.val "val2" . + * ... + * } + */ +public class ValuesServiceFactory extends AbstractServiceFactory + implements ServiceFactory { + + private static final Logger log = Logger + .getLogger(ValuesServiceFactory.class); + + /** + * The URI service key. + */ + public static final URI SERVICE_KEY = new URIImpl(BD.NAMESPACE+"values"); + + /** + * The service params for this service. + */ + public static interface ValuesParams { + + /** + * The limit on the sample. + */ + URI VAR = new URIImpl(SERVICE_KEY.stringValue() + ".var"); + + /** + * The seed on the sample. + */ + URI VAL = new URIImpl(SERVICE_KEY.stringValue() + ".val"); + + } + + + /* + * Note: This could extend the base class to allow for search service + * configuration options. + */ + private final BigdataNativeServiceOptions serviceOptions; + + public ValuesServiceFactory() { + + serviceOptions = new BigdataNativeServiceOptions(); + serviceOptions.setRunFirst(true); + + } + + @Override + public BigdataNativeServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + public BigdataServiceCall create( + final ServiceCallCreateParams params, + final ServiceParams serviceParams) { + + final AbstractTripleStore store = params.getTripleStore(); + + final ServiceNode serviceNode = params.getServiceNode(); + + /* + * Validate the predicates for a given service call. + */ + verifyGraphPattern(store, serviceNode.getGraphPattern(), serviceParams); + + /* + * Create and return the ServiceCall object which will execute this + * query. + */ + return new ValuesCall(store, getServiceOptions(), serviceParams); + + } + + /** + * Verify that there is only a single statement pattern node and that the + * service parameters are valid. + */ + private void verifyGraphPattern( + final AbstractTripleStore database, + final GroupNodeBase<IGroupMemberNode> group, + final ServiceParams serviceParams) { + + final Iterator<Map.Entry<URI, List<TermNode>>> it = serviceParams.iterator(); + + if (!serviceParams.contains(ValuesParams.VAR)) { + + throw new RuntimeException("must provide a variable for: " + ValuesParams.VAR); + + } + + if (!serviceParams.contains(ValuesParams.VAL)) { + + throw new RuntimeException("must provide at least one value for: " + ValuesParams.VAL); + + } + + while (it.hasNext()) { + + final URI param = it.next().getKey(); + + if (ValuesParams.VAR.equals(param)) { + + final List<TermNode> vars = serviceParams.get(param); + + if (vars == null || vars.size() != 1 || vars.get(0).isConstant()) { + throw new RuntimeException("must provide exactly one variable for: " + param); + } + + } else if (ValuesParams.VAL.equals(param)) { + + final List<TermNode> vals = serviceParams.get(param); + + if (vals == null || vals.size() == 0) { + throw new RuntimeException("must provide at least one value for: " + param); + } + + for (TermNode val : vals) { + if (val.isVariable()) { + throw new RuntimeException("must provide constant values for: " + param); + } + } + + } else { + + throw new RuntimeException("unrecognized param: " + param); + + } + + } + + } + + /** + * + * Note: This has the {@link AbstractTripleStore} reference attached. This + * is not a {@link Serializable} object. It MUST run on the query + * controller. + */ + private static class ValuesCall implements BigdataServiceCall { + + private final AbstractTripleStore db; + private final IServiceOptions serviceOptions; + private final ServiceParams serviceParams; + + public ValuesCall( + final AbstractTripleStore db, + final IServiceOptions serviceOptions, + final ServiceParams serviceParams) { + + if(db == null) + throw new IllegalArgumentException(); + + if(serviceOptions == null) + throw new IllegalArgumentException(); + + if(serviceParams == null) + throw new IllegalArgumentException(); + + this.db = db; + this.serviceOptions = serviceOptions; + this.serviceParams = serviceParams; + + } + + /** + * Run a sample index op over the access path. + */ + @Override + public ICloseableIterator<IBindingSet> call( + final IBindingSet[] bc) { + + if (log.isInfoEnabled()) { + log.info(bc.length); + log.info(Arrays.toString(bc)); + log.info(serviceParams); + } + + if (bc != null && bc.length > 0 && !bc[0].equals(EmptyBindingSet.INSTANCE)) { + throw new RuntimeException("cannot run with incoming bindings"); + } + + final IVariable<IV> var = serviceParams.getAsVar(ValuesParams.VAR); + + final List<TermNode> vals = serviceParams.get(ValuesParams.VAL); + + final IBindingSet[] bSets = new IBindingSet[vals.size()]; + + for (int i = 0; i < bSets.length; i++) { + + bSets[i] = new ListBindingSet(); + + bSets[i].set(var, (IConstant<IV>) vals.get(i).getValueExpression()); + + } + + return new ThickCloseableIterator<IBindingSet>(bSets, bSets.length); + + } + + @Override + public IServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + } + +} Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ValuesServiceFactory.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java 2013-05-17 18:05:59 UTC (rev 7142) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java 2013-05-17 21:10:52 UTC (rev 7143) @@ -10,13 +10,13 @@ import org.openrdf.model.URI; import org.openrdf.model.impl.URIImpl; -import com.bigdata.bop.ap.SampleIndex; import com.bigdata.rdf.sparql.ast.QueryHints; import com.bigdata.rdf.sparql.ast.cache.DescribeServiceFactory; import com.bigdata.rdf.sparql.ast.eval.SampleServiceFactory; import com.bigdata.rdf.sparql.ast.eval.SearchInSearchServiceFactory; import com.bigdata.rdf.sparql.ast.eval.SearchServiceFactory; import com.bigdata.rdf.sparql.ast.eval.SliceServiceFactory; +import com.bigdata.rdf.sparql.ast.eval.ValuesServiceFactory; import com.bigdata.rdf.sparql.ast.service.history.HistoryServiceFactory; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.rdf.store.BD; @@ -89,6 +89,9 @@ // Add the slice index service. add(SliceServiceFactory.SERVICE_KEY, new SliceServiceFactory()); + // Add the values service. + add(ValuesServiceFactory.SERVICE_KEY, new ValuesServiceFactory()); + if (QueryHints.DEFAULT_DESCRIBE_CACHE) { add(new URIImpl(BD.NAMESPACE + "describe"), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-17 18:06:55
|
Revision: 7142 http://bigdata.svn.sourceforge.net/bigdata/?rev=7142&view=rev Author: thompsonbry Date: 2013-05-17 18:05:59 +0000 (Fri, 17 May 2013) Log Message: ----------- This commit addresses several different issues. Added doRejectedCommit() into BasicHA and override in HAJournal. This provides the necessary hook to force the HAJournalServer into an Error state if the service fails a commit (specifically, if it votes NO in prepare2Phase). Significant cleanup around the access methods to the CommitRecordIndex in AbstractJournal. In particular, AbstractJournal.getCommitRecordIndex() was being used in several unsafe patterns (esp., getRootBlocks(startTime), getRootBlock(startTime)). In addition, DumpJournal was using this method can now be run with concurrent operations against the journal, making it unsafe. The only publically exposed method now returns a read-only committed view of the CommitRecordIndex. StoreManager was modified to support the new version of getCommitRecordIndex() that accepts a readOnly flag. {{{ CommitRecordIndex getCommitRecordIndex(long addr, boolean readOnly) }}} JournalTransactionService.findNextCommitTime() was modified to use AbstractJournal.getCommitRecordStrictlyGreaterThan(). That method provides appropriate synchronization for the CommitRecordIndex. Modified commit2Phase() to NOT purge the HALogs unless prepare2Phase voted YES for all services. This addresses a problem where one service could vote NO but the logs would be purged before the service left the quorum. The logs are now correctly retained if a service votes NO for prepare. The didAllServicesCommit flag was added to the IHA2PhaseCommitMessage. This was done in response to problems identified in TestHA3JournalServerOverrides. HAJournalServer.ErrorTask() was modified to force a service leave. This was done in response to problems identified in TestHA3JournalServerOverrides. QuorumCommitImpl.prepare2Phase() now interprets an error attempting to send the PREPARE message to a server as a "NO" vote (as opposed to only errors in processing the PREPARE message on the remote server). New tests were added to TestHAJournalServerOverride that examine failure modes where (a) a service votes "NO" for PREPARE; and (b) a service throws an exception out of prepare2Phase(). ---- I have observed occasional failures in the following stress test. See [1]. This looks like a failure to resolve the view of the database through the DefaultResourceLocator, thus passing a [null] view into BigdataSailConnection.attach(). It fails every so many runs through that stress test. I have some question about whether this a new failure or if it has been failing periodically. {{{ TestConcurrentCreateKB.test_concurrentKBCreateAndDiscoveryStressTestOnDistinctJournals() }}} The change in this commit to the DefaultResourceLocator is unlikely to be responsible since only read-only tx code paths were effected, but the test failure goes through a read-committed request: {{{ conn = getQueryConnection(indexManager, namespace, ITx.READ_COMMITTED); }}} The failure trace is: {{{ java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252) at java.util.concurrent.FutureTask.get(FutureTask.java:111) at com.bigdata.rdf.sail.TestConcurrentKBCreate.doConcurrentCreateAndDiscoveryTest(TestConcurrentKBCreate.java:312) at com.bigdata.rdf.sail.TestConcurrentKBCreate.test_concurrentKBCreateAndDiscovery(TestConcurrentKBCreate.java:172) at com.bigdata.rdf.sail.TestConcurrentKBCreate.test_concurrentKBCreateAndDiscoveryStressTestOnDistinctJournals(TestConcurrentKBCreate.java:227) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at junit.framework.TestCase.runTest(TestCase.java:154) at junit.framework.TestCase.runBare(TestCase.java:127) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException at com.bigdata.rdf.sail.TestConcurrentKBCreate$DiscoveryTask.call(TestConcurrentKBCreate.java:373) at com.bigdata.rdf.sail.TestConcurrentKBCreate$DiscoveryTask.call(TestConcurrentKBCreate.java:1) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722) Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException at com.bigdata.rdf.sail.BigdataSail$BigdataSailReadOnlyConnection.newTx(BigdataSail.java:4119) at com.bigdata.rdf.sail.BigdataSail$BigdataSailReadOnlyConnection.<init>(BigdataSail.java:3986) at com.bigdata.rdf.sail.BigdataSail._getReadOnlyConnection(BigdataSail.java:1424) at com.bigdata.rdf.sail.BigdataSail.getReadOnlyConnection(BigdataSail.java:1399) at com.bigdata.rdf.sail.BigdataSailRepository.getReadOnlyConnection(BigdataSailRepository.java:82) at com.bigdata.rdf.sail.TestConcurrentKBCreate.getQueryConnection(TestConcurrentKBCreate.java:434) at com.bigdata.rdf.sail.TestConcurrentKBCreate.access$0(TestConcurrentKBCreate.java:405) at com.bigdata.rdf.sail.TestConcurrentKBCreate$DiscoveryTask.call(TestConcurrentKBCreate.java:358) ... 6 more Caused by: java.lang.IllegalArgumentException at com.bigdata.rdf.sail.BigdataSail$BigdataSailConnection.attach(BigdataSail.java:1896) at com.bigdata.rdf.sail.BigdataSail$BigdataSailReadOnlyConnection.newTx(BigdataSail.java:4109) ... 13 more }}} [1] https://sourceforge.net/apps/trac/bigdata/ticket/617 (Concurrent KB create fails with "No axioms defined?) The TestRWJournal, journal.TestAll, TestBigdataSailWithQuads, and HA test suites are all 100% green. I did observe one zombie for the HA test suite. However, this was likely related to a previous run in which a bug (never committed) had caused all of that test suite to fail. See https://sourceforge.net/apps/trac/bigdata/ticket/530 (Journal HA) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/HA2PhaseCommitMessage.java branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/IHA2PhaseCommitMessage.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractTask.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/DumpJournal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/IAtomicStore.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/JournalDelegate.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/JournalTransactionService.java branches/READ_CACHE/bigdata/src/java/com/bigdata/resources/StoreManager.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -31,6 +31,7 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -219,9 +220,30 @@ /* * Runnable which will execute this message on the * remote service. + * + * FIXME Because async futures cause DGC native thread + * leaks this is no longer running the prepare + * asynchronously on the followers. Change the code + * here, and in commit2Phase and abort2Phase to use + * multiple threads to run the tasks on the followers. */ - final Future<Boolean> rf = getService(serviceId) - .prepare2Phase(msgForJoinedService); + + final HACommitGlue service = getService(serviceId); + + Future<Boolean> rf = null; + try { + // RMI. + rf = service.prepare2Phase(msgForJoinedService); + } catch (final Throwable t) { + // If anything goes wrong, wrap up exception as Future. + final FutureTask<Boolean> ft = new FutureTask<Boolean>(new Runnable() { + public void run() { + throw new RuntimeException(t); + } + }, Boolean.FALSE); + rf = ft; + ft.run(); // evaluate future. + } // add to list of futures we will check. remoteFutures.set(i, rf); @@ -317,7 +339,9 @@ /* * Note: prepare2Phase() is throwing exceptions if * preconditions are violated. These thrown exceptions are - * interpreted as a "NO" vote. + * interpreted as a "NO" vote. An exception can also appear + * here if there is an RMI failure or even a failure on this + * service when attempting to perform the RMI. */ log.error(ex, ex); done = true; // ExecutionException indicates isDone(). @@ -419,6 +443,11 @@ final long commitTime = preq.getRootBlock().getLastCommitTime(); final PrepareResponse presp = req.getPrepareResponse(); + + // true iff we have a full complement of services that vote YES for this + // commit. + final boolean didAllServicesPrepare = presp.getYesCount() == presp + .replicationFactor(); member.assertLeader(token); @@ -427,7 +456,7 @@ try { final IHA2PhaseCommitMessage msgJoinedService = new HA2PhaseCommitMessage( - true/* isJoinedService */, commitTime); + true/* isJoinedService */, commitTime, didAllServicesPrepare); for (int i = 1; i < joinedServiceIds.length; i++) { Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/HA2PhaseCommitMessage.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/HA2PhaseCommitMessage.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/HA2PhaseCommitMessage.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -32,12 +32,14 @@ private final boolean isJoinedService; private final long commitTime; + private final boolean didAllServicesPrepare; public HA2PhaseCommitMessage(final boolean isJoinedService, - final long commitTime) { + final long commitTime, final boolean didAllServicesPrepare) { this.isJoinedService = isJoinedService; this.commitTime = commitTime; + this.didAllServicesPrepare = didAllServicesPrepare; } @@ -51,4 +53,18 @@ return commitTime; } + @Override + public boolean didAllServicesPrepare() { + return didAllServicesPrepare; + } + + @Override + public String toString() { + + return super.toString() + "{isJoinedService=" + isJoinedService + + ",commitTime=" + commitTime + ",didAllServicesPrepare=" + + didAllServicesPrepare + "}"; + + } + } Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/IHA2PhaseCommitMessage.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/IHA2PhaseCommitMessage.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/IHA2PhaseCommitMessage.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -54,4 +54,11 @@ */ long getCommitTime(); + /** + * Return <code>true</code> iff all services voted "YES" for PREPARE. When + * <code>false</code>, not all services will participate in this commit (but + * the commit will still be performed). + */ + boolean didAllServicesPrepare(); + } Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -81,7 +81,6 @@ import com.bigdata.btree.ITuple; import com.bigdata.btree.ITupleIterator; import com.bigdata.btree.IndexMetadata; -import com.bigdata.btree.ReadOnlyIndex; import com.bigdata.btree.keys.ICUVersionRecord; import com.bigdata.btree.view.FusedView; import com.bigdata.cache.ConcurrentWeakValueCache; @@ -395,26 +394,34 @@ */ private final ReentrantReadWriteLock _fieldReadWriteLock = new ReentrantReadWriteLock(false/* fair */); - /** - * Used to cache the most recent {@link ICommitRecord} -- discarded on - * {@link #abort()}; set by {@link #commitNow(long)}. - */ + /** + * Used to cache the most recent {@link ICommitRecord} -- discarded on + * {@link #abort()}; set by {@link #commitNow(long)}. + * <p> + * Note: This is set in the constructor and modified by {@link #_abort()} + * but (once set by the constructor) it is never <code>null</code> until the + * store is closed. + */ private volatile ICommitRecord _commitRecord; - /** - * BTree mapping commit timestamps to the address of the corresponding - * {@link ICommitRecord}. The keys are timestamps (long integers). The - * values are the address of the {@link ICommitRecord} with that commit - * timestamp. - * <p> - * Note: The {@link CommitRecordIndex} object is NOT systematically - * protected by <code>synchronized</code> within this class. Therefore it is - * NOT safe for use by outside classes and CAN NOT be made safe simply by - * synchronizing their access on the {@link CommitRecordIndex} object - * itself. This is mainly for historical reasons and it may be possible to - * systematically protect access to this index within a synchronized block - * and then expose it to other classes. - */ + /** + * BTree mapping commit timestamps to the address of the corresponding + * {@link ICommitRecord}. The keys are timestamps (long integers). The + * values are the address of the {@link ICommitRecord} with that commit + * timestamp. + * <p> + * Note: The {@link CommitRecordIndex} object is NOT systematically + * protected by <code>synchronized</code> within this class. Therefore it is + * NOT safe for use by outside classes and CAN NOT be made safe simply by + * synchronizing their access on the {@link CommitRecordIndex} object + * itself. This is mainly for historical reasons and it may be possible to + * systematically protect access to this index within a synchronized block + * and then expose it to other classes. + * <p> + * Note: This is set in the constructor and modified by {@link #_abort()} + * but (once set by the constructor) it is never <code>null</code> until the + * store is closed. + */ private volatile CommitRecordIndex _commitRecordIndex; /** @@ -688,74 +695,92 @@ } - /** - * Return the root block view associated with the commitRecord for the - * provided commit time. This requires accessing the next commit record - * since the previous root block is stored with each record. - * - * @param commitTime - * A commit time. - * - * @return The root block view -or- <code>null</code> if there is no commit - * record for that commitTime. - * - */ - public IRootBlockView getRootBlock(final long commitTime) { +// /** +// * Return the root block view associated with the commitRecord for the +// * provided commit time. This requires accessing the next commit record +// * since the previous root block is stored with each record. +// * +// * @param commitTime +// * A commit time. +// * +// * @return The root block view -or- <code>null</code> if there is no commit +// * record for that commitTime. +// */ +// @Deprecated // This method is unused and lacks a unit test. +// IRootBlockView getRootBlock(final long commitTime) { +// +// /* +// * Note: getCommitRecordStrictlyGreaterThan() uses appropriate +// * synchronization for the CommitRecordIndex. +// */ +// final ICommitRecord commitRecord = getCommitRecordStrictlyGreaterThan(commitTime); +// +// if (commitRecord == null) { +// +// return null; +// +// } +// +// final long rootBlockAddr = commitRecord.getRootAddr(PREV_ROOTBLOCK); +// +// if (rootBlockAddr == 0) { +// +// return null; +// +// } else { +// +// final ByteBuffer bb = read(rootBlockAddr); +// +// return new RootBlockView(true /* rb0 - WTH */, bb, checker); +// +// } +// +// } +// +// /** +// * +// * @param startTime from which to begin iteration +// * +// * @return an iterator over the committed root blocks +// */ +// @Deprecated +// /* +// * This is UNUSED AND NOT SAFE (used only in test suite by +// * StressTestConcurrentTx, which I have commented out) and not safe (because +// * it lacks the necessary locks to access the CommitRecordIndex). The code +// * is also wrong since it visits GT the commitTime when it should visit GTE +// * the commitTime. +// */ +// Iterator<IRootBlockView> getRootBlocks(final long startTime) { +// return new Iterator<IRootBlockView>() { +// ICommitRecord commitRecord = getCommitRecordIndex().findNext(startTime); +// +// public boolean hasNext() { +// return commitRecord != null; +// } +// +// public IRootBlockView next() { +// final long rootBlockAddr = commitRecord.getRootAddr(PREV_ROOTBLOCK); +// +// commitRecord = getCommitRecordIndex().findNext(commitRecord.getTimestamp()); +// +// if (rootBlockAddr == 0) { +// return null; +// } else { +// ByteBuffer bb = read(rootBlockAddr); +// +// return new RootBlockView(true /* rb0 - WTH */, bb, checker); +// } +// } +// +// public void remove() { +// throw new UnsupportedOperationException(); +// } +// +// }; +// } - final ICommitRecord commitRecord = getCommitRecordIndex().findNext(commitTime); - - if (commitRecord == null) { - return null; - } - - final long rootBlockAddr = commitRecord.getRootAddr(PREV_ROOTBLOCK); - - if (rootBlockAddr == 0) { - return null; - } else { - ByteBuffer bb = read(rootBlockAddr); - - return new RootBlockView(true /* rb0 - WTH */, bb, checker); - } - - } - /** - * - * @param startTime from which to begin iteration - * - * @return an iterator over the committed root blocks - */ - public Iterator<IRootBlockView> getRootBlocks(final long startTime) { - return new Iterator<IRootBlockView>() { - ICommitRecord commitRecord = getCommitRecordIndex().findNext(startTime); - - public boolean hasNext() { - return commitRecord != null; - } - - public IRootBlockView next() { - final long rootBlockAddr = commitRecord.getRootAddr(PREV_ROOTBLOCK); - - commitRecord = getCommitRecordIndex().findNext(commitRecord.getTimestamp()); - - if (rootBlockAddr == 0) { - return null; - } else { - ByteBuffer bb = read(rootBlockAddr); - - return new RootBlockView(true /* rb0 - WTH */, bb, checker); - } - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } - - /** * True iff the journal was opened in a read-only mode. */ private final boolean readOnly; @@ -2924,7 +2949,25 @@ // The services joined with the met quorum, in their join order. joinedServiceIds = quorum.getJoined(); + + // The UUID for this service. + final UUID serviceId = quorum.getClient().getServiceId(); + if (joinedServiceIds.length == 0 + || !joinedServiceIds[0].equals(serviceId)) { + + /* + * Sanity check. Verify that the first service in the join + * order is *this* service. This is a precondition for the + * service to be the leader. + */ + + throw new RuntimeException("Not leader: serviceId=" + + serviceId + ", joinedServiceIds=" + + Arrays.toString(joinedServiceIds)); + + } + // The services in the write pipeline (in any order). nonJoinedPipelineServiceIds = new LinkedHashSet<UUID>( Arrays.asList(getQuorum().getPipeline())); @@ -2935,6 +2978,7 @@ nonJoinedPipelineServiceIds.remove(joinedServiceId); } + try { /** * CRITICAL SECTION. We need obtain a distributed consensus @@ -3924,7 +3968,7 @@ * * @return The read-only view of the {@link CommitRecordIndex}. */ - public IIndex getReadOnlyCommitRecordIndex() { + public CommitRecordIndex getReadOnlyCommitRecordIndex() { final ReadLock lock = _fieldReadWriteLock.readLock(); @@ -3933,12 +3977,13 @@ try { assertOpen(); - - final CommitRecordIndex commitRecordIndex = getCommitRecordIndex(_rootBlock - .getCommitRecordIndexAddr()); - return new ReadOnlyIndex(commitRecordIndex); + final CommitRecordIndex commitRecordIndex = getCommitRecordIndex( + _rootBlock.getCommitRecordIndexAddr(), true/* readOnly */); +// return new ReadOnlyIndex(commitRecordIndex); + return commitRecordIndex; + } finally { lock.unlock(); @@ -3946,48 +3991,40 @@ } } - - /** - * Return the current state of the index that resolves timestamps to - * {@link ICommitRecord}s. - * <p> - * Note: The returned object is NOT safe for concurrent operations and is - * NOT systematically protected by the use of synchronized blocks within - * this class. - * - * @return The {@link CommitRecordIndex}. - * - * @todo If you need access to this object in an outside class consider - * using {@link #getRootBlockView()}, - * {@link IRootBlockView#getCommitRecordIndexAddr()}, and - * {@link #getCommitRecord(long)} to obtain a distinct instance - * suitable for read-only access. - */ - protected CommitRecordIndex getCommitRecordIndex() { - final ReadLock lock = _fieldReadWriteLock.readLock(); +// /** +// * I have removed this method since the returned {@link CommitRecordIndex} +// * was being used without appropriate synchronization. There is a +// * {@link #getReadOnlyCommitRecordIndex()} which may be used in place of +// * this method. +// */ +// protected CommitRecordIndex getCommitRecordIndex() { +// +// final ReadLock lock = _fieldReadWriteLock.readLock(); +// +// lock.lock(); +// +// try { +// +// assertOpen(); +// +// final long commitRecordIndexAddr = _rootBlock.getCommitRecordIndexAddr(); +// +// final CommitRecordIndex commitRecordIndex = getCommitRecordIndex(addr); +// +// if (commitRecordIndex == null) +// throw new AssertionError(); +// +// return commitRecordIndex; +// +// } finally { +// +// lock.unlock(); +// +// } +// +// } - lock.lock(); - - try { - - assertOpen(); - - final CommitRecordIndex commitRecordIndex = _commitRecordIndex; - - if (commitRecordIndex == null) - throw new AssertionError(); - - return commitRecordIndex; - - } finally { - - lock.unlock(); - - } - - } - /** * Read and return the {@link CommitRecordIndex} from the current root * block. @@ -4007,7 +4044,8 @@ if (log.isDebugEnabled()) log.debug("Loading from addr=" + addr); - return getCommitRecordIndex(addr); + // Load the live index from the disk. + return getCommitRecordIndex(addr, false/* readOnly */); } catch (RuntimeException ex) { @@ -4023,30 +4061,31 @@ } /** - * Create or re-load the index that resolves timestamps to - * {@link ICommitRecord}s. - * <p> - * Note: The returned object is NOT cached. When addr is non-{@link #NULL}, - * each invocation will return a distinct {@link CommitRecordIndex} object. - * This behavior is partly for historical reasons but it does serve to - * protect the live {@link CommitRecordIndex} from outside access. This is - * important since access to the live {@link CommitRecordIndex} is NOT - * systematically protected by <code>synchronized</code> within this class. + * Create or load and return the index that resolves timestamps to + * {@link ICommitRecord}s. This method is capable of returning either the + * live {@link CommitRecordIndex} or a read-only view of any committed + * version of that index. * + * <strong>CAUTION: DO NOT EXPOSE THE LIVE COMMIT RECORD INDEX OUTSIDE OF + * THIS CLASS. IT IS NOT POSSIBLE TO HAVE CORRECT SYNCHRONIZATION ON THAT + * INDEX IN ANOTHER CLASS.</code> + * * @param addr * The root address of the index -or- 0L if the index has not - * been created yet. + * been created yet. When addr is non-{@link #NULL}, each + * invocation will return a distinct {@link CommitRecordIndex} + * object. * + * @param readOnly + * When <code>false</code> the returned is NOT cached. + * * @return The {@link CommitRecordIndex} for that address or a new index if - * 0L was specified as the address. + * <code>0L</code> was specified as the address. * * @see #_commitRecordIndex - * - * TODO We could modify getCommitRecordIndex() to accept - * readOnly:boolean and let it load/create a read-only view rather than - * wrapping it with a ReadOnlyIndex. */ - protected CommitRecordIndex getCommitRecordIndex(final long addr) { + protected CommitRecordIndex getCommitRecordIndex(final long addr, + final boolean readOnly) { if (log.isInfoEnabled()) log.info("addr=" + toString(addr)); @@ -4067,7 +4106,7 @@ * Note: if the journal is not the quorum leader then it is * effectively read-only. */ - if (isReadOnly()) { + if (isReadOnly() || readOnly) { ndx = CommitRecordIndex.createTransient(); @@ -4079,12 +4118,26 @@ } else { - /* - * Reload the mutable btree from its root address. - */ + if (readOnly) { - ndx = (CommitRecordIndex) BTree.load(this, addr, false/* readOnly */); + /* + * Read only view of the most CommitRecordIndex having + * that checkpointAddr. + */ + + ndx = (CommitRecordIndex) getIndexWithCheckpointAddr(addr); + + } else { + + /* + * Reload the mutable btree from its root address. + * + * Note: For this code path we DO NOT cache the index view. + */ + ndx = (CommitRecordIndex) BTree.load(this, addr, false/* readOnly */); + + } } assert ndx != null; @@ -6118,6 +6171,8 @@ // Vote NO. vote.set(false); + doRejectedCommit(); + return vote.get(); } @@ -6125,6 +6180,16 @@ } // class VoteNoTask /** + * Method must be extended by subclass to coordinate the rejected + * commit. + */ + protected void doRejectedCommit() { + + doLocalAbort(); + + } + + /** * Task prepares for a 2-phase commit (syncs to the disk) and votes YES * iff if is able to prepare successfully. * @@ -6156,6 +6221,8 @@ */ public Boolean call() throws Exception { + try { + final IRootBlockView rootBlock = prepareMessage.getRootBlock(); if (haLog.isInfoEnabled()) @@ -6253,7 +6320,17 @@ vote.set(true); return vote.get(); + + } finally { + if(!vote.get()) { + + doRejectedCommit(); + + } + + } + } } @@ -6515,14 +6592,27 @@ + rootBlock); } - /* - * The HA log files are purged on each node any time the - * quorum is fully met and goes through a commit point. - * Leaving only the current open log file. - */ + if (commitMessage.didAllServicesPrepare()) { - localService.purgeHALogs(rootBlock.getQuorumToken()); + /* + * The HALog files are conditionally purged (depending + * on the IRestorePolicy) on each node any time the + * quorum is fully met and goes through a commit point. + * The current HALog always remains open. + * + * Note: This decision needs to be made in awareness of + * whether all services voted to PREPARE. Otherwise we + * can hit a problem where some service did not vote to + * prepare, but the other services did, and we wind up + * purging the HALogs even though one of the services + * did not go through the commit2Phase(). This issue is + * fixed by the didAllServicesPrepare() flag. + */ + localService.purgeHALogs(rootBlock.getQuorumToken()); + + } + } catch (Throwable t) { try { Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractTask.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractTask.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractTask.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -2746,14 +2746,14 @@ return delegate.toString(addr); } - public IRootBlockView getRootBlock(final long commitTime) { - return delegate.getRootBlock(commitTime); - } +// public IRootBlockView getRootBlock(final long commitTime) { +// return delegate.getRootBlock(commitTime); +// } +// +// public Iterator<IRootBlockView> getRootBlocks(final long startTime) { +// return delegate.getRootBlocks(startTime); +// } - public Iterator<IRootBlockView> getRootBlocks(final long startTime) { - return delegate.getRootBlocks(startTime); - } - /* * IAllocationContext * @@ -3257,14 +3257,14 @@ return delegate.toString(addr); } - public IRootBlockView getRootBlock(long commitTime) { - return delegate.getRootBlock(commitTime); - } +// public IRootBlockView getRootBlock(long commitTime) { +// return delegate.getRootBlock(commitTime); +// } +// +// public Iterator<IRootBlockView> getRootBlocks(long startTime) { +// return delegate.getRootBlocks(startTime); +// } - public Iterator<IRootBlockView> getRootBlocks(long startTime) { - return delegate.getRootBlocks(startTime); - } - public ScheduledFuture<?> addScheduledTask(Runnable task, long initialDelay, long delay, TimeUnit unit) { return delegate.addScheduledTask(task, initialDelay, delay, unit); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/DumpJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/DumpJournal.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/DumpJournal.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -526,10 +526,14 @@ } } - - final CommitRecordIndex commitRecordIndex = journal - .getCommitRecordIndex(); + /* + * Note: A read-only view is used since the Journal could be exposed to + * concurrent operations through the NSS. + */ + final CommitRecordIndex commitRecordIndex = journal + .getReadOnlyCommitRecordIndex(); + out.println("There are " + commitRecordIndex.getEntryCount() + " commit points."); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/IAtomicStore.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/IAtomicStore.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/IAtomicStore.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -27,8 +27,6 @@ package com.bigdata.journal; -import java.util.Iterator; - import com.bigdata.rawstore.IRawStore; /** @@ -122,24 +120,31 @@ */ public ICommitRecord getCommitRecord(long timestamp); - /** - * Return the root block view associated with the commitRecord for the - * provided commit time. This requires accessing the next commit record - * since it is the previous root block that is referenced from each record. - * - * @param commitTime - * A commit time. - * - * @return The root block view -or- <code>null</code> if there is no commit - * record for that commitTime. - */ - public IRootBlockView getRootBlock(final long commitTime); - - /** - * - * @param startTime from which to begin iteration - * - * @return an iterator over the committed root blocks - */ - public Iterator<IRootBlockView> getRootBlocks(final long startTime); + /* + * These methods have been removed from the public interface. They were only + * used by the test suite. Further, there were problems with the + * implementations. + */ + +// /** +// * Return the root block view associated with the commitRecord for the +// * provided commit time. This requires accessing the next commit record +// * since it is the previous root block that is referenced from each record. +// * +// * @param commitTime +// * A commit time. +// * +// * @return The root block view -or- <code>null</code> if there is no commit +// * record for that commitTime. +// */ +// public IRootBlockView getRootBlock(final long commitTime); +// +// /** +// * +// * @param startTime from which to begin iteration +// * +// * @return an iterator over the committed root blocks +// */ +// public Iterator<IRootBlockView> getRootBlocks(final long startTime); + } Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -520,6 +520,7 @@ final long nanos = timeoutNanos; long remaining = nanos; + // Verify that this service is still the leader. getQuorum().assertLeader(token); // /* @@ -2320,7 +2321,7 @@ // final Tx tx = (Tx) (isReadWriteTx ? getConcurrencyManager() // .getTransactionManager().getTx(timestamp) : null); - final Tx tx = (Tx) getConcurrencyManager().getTransactionManager() + final Tx tx = (Tx) /*getConcurrencyManager().*/getTransactionManager() .getTx(timestamp); if (isReadWriteTx) { Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/JournalDelegate.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/JournalDelegate.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/JournalDelegate.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -40,7 +40,6 @@ import com.bigdata.btree.IndexMetadata; import com.bigdata.counters.CounterSet; import com.bigdata.mdi.IResourceMetadata; -import com.bigdata.rawstore.IAllocationContext; import com.bigdata.rawstore.IPSOutputStream; import com.bigdata.relation.locator.IResourceLocator; import com.bigdata.sparse.SparseRowStore; @@ -86,17 +85,17 @@ return delegate.getRootAddr(index); } - public IRootBlockView getRootBlock(long commitTime) { - return delegate.getRootBlock(commitTime); - } - public IRootBlockView getRootBlockView() { return delegate.getRootBlockView(); } - public Iterator<IRootBlockView> getRootBlocks(long startTime) { - return delegate.getRootBlocks(startTime); - } +// public IRootBlockView getRootBlock(long commitTime) { +// return delegate.getRootBlock(commitTime); +// } +// +// public Iterator<IRootBlockView> getRootBlocks(long startTime) { +// return delegate.getRootBlocks(startTime); +// } public void setCommitter(int index, ICommitter committer) { delegate.setCommitter(index, committer); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/JournalTransactionService.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/JournalTransactionService.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/JournalTransactionService.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -127,10 +127,19 @@ } protected long findNextCommitTime(final long commitTime) { - - final ICommitRecord commitRecord = journal.getCommitRecordIndex() - .findNext(commitTime); - + + /* + * Note: The following code did not obtain the appropriate lock to + * access the CommitRecordIndex. It was replaced by the + * getCommitRecordStrictlyGreaterThan() call, which does take the + * necessary lock and does the same thing. + */ +// final ICommitRecord commitRecord = journal.getCommitRecordIndex() +// .findNext(commitTime); + + final ICommitRecord commitRecord = journal + .getCommitRecordStrictlyGreaterThan(commitTime); + if(commitRecord == null) { return -1L; Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/resources/StoreManager.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/resources/StoreManager.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/resources/StoreManager.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -2556,10 +2556,11 @@ * for the live journal. */ @Override - public CommitRecordIndex getCommitRecordIndex(final long addr) { + public CommitRecordIndex getCommitRecordIndex(final long addr, + final boolean readOnly) { + + return super.getCommitRecordIndex(addr, readOnly); - return super.getCommitRecordIndex(addr); - } @Override @@ -4438,7 +4439,7 @@ */ final CommitRecordIndex commitRecordIndex = journal .getCommitRecordIndex(journal.getRootBlockView() - .getCommitRecordIndexAddr()); + .getCommitRecordIndexAddr(),true/*readOnly*/); /* * A per-journal hash set of the [checkpointAddr] for the Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -447,7 +447,7 @@ super.setQuorumToken(newValue); - if (newValue == Quorum.NO_QUORUM) { + if (getHAReady() == Quorum.NO_QUORUM) { /* * If there is a running snapshot, then cancel it since the quorum @@ -1500,25 +1500,22 @@ if (f == null) return null; - haLog.warn("Started REBUILD"); + haLog.warn("Started REBUILD: runState=" + innerRunState); return getProxy(f, true/* async */); } case Rebuild: // Already running rebuild. - return null; case Restore: // Running restore. Can not do rebuild. - return null; case Resync: // Running resync. Can not do rebuild. - return null; case RunMet: // RunMet. Can not do rebuild. - return null; case Shutdown: // Shutting down. Can not do rebuild. + haLog.warn("Can not REBUILD: runState=" + innerRunState); return null; default: // Unknown run state. @@ -1731,6 +1728,21 @@ } /** + * {@inheritDoc} + * <p> + * Extended to kick the {@link HAJournalServer} into an error state. It + * will recover from that error state by re-entering seek consensus. + */ + @Override + protected void doRejectedCommit() { + + super.doRejectedCommit(); + + getQuorumService().enterErrorState(); + + } + + /** * Return this quorum member, appropriately cast. * * @return The quorum member -or- <code>null</code> if the quorum is not Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -1579,6 +1579,33 @@ } finally { logLock.unlock(); } + + // Force a service leave. + getQuorum().getActor().serviceLeave(); + +// /* +// * Set token. Journal will notice that it is no longer +// * "HA Ready" +// * +// * Note: AbstractJournal.setQuorumToken() will detect case where +// * it transitions from a met quorum through a service leave and +// * will clear its haReady token and update its haStatus field +// * appropriately. +// * +// * FIXME There may be a data race here. The quorum.token() might +// * be be cleared by the time we call +// * setQuorumToken(quorum.token()) so we may have to explicitly +// * "clear" the journal token by passing in NO_QUORUM. +// */ +// journal.setQuorumToken(Quorum.NO_QUORUM); +// +// try { +// journal.getHALogNexus().disableHALog(); +// } catch (IOException e) { +// haLog.error(e, e); +// } + + // Seek consensus. enterRunState(new SeekConsensusTask()); return null; Modified: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java 2013-05-17 17:40:53 UTC (rev 7141) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java 2013-05-17 18:05:59 UTC (rev 7142) @@ -161,18 +161,17 @@ * {@link HACommitGlue#prepare2Phase(IHA2PhasePrepareMessage)} to throw an * exeption. A simple transaction is performed. We verify that the * transaction completes successfully, that the quorum token is unchanged, - * and that [A,C] both participated in the commit. + * and that [A,C] both participated in the commit. We also verify that B is + * moved to the end of the pipeline (by doing a serviceLeave and then + * re-entering the pipeline) and that it resyncs with the met quorum and + * finally re-joins with the met quorum. The quorum should not break across + * this test. * - * TODO Spot check the {@link HAStatusEnum} on all services after the B - * fails the prepare2Phase request. + * FIXME Variant where the GATHER failed. * - * FIXME Extend test and its variant to verify that B RESYNCs and joins the - * met quourum. (B should do a serviceLeave() then SeekConsensus, RESYNC, - * and serviceJoin()). - * - * FIXME Variant where B votes "NO" rather than throwing an exception. + * FIXME Variant where the commit2Phase fails. */ - public void testStartABC_prepare2Phase_B_throws_exception() + public void testStartABC_prepare2Phase_B_votes_NO() throws Exception { // Enforce the join order. @@ -187,12 +186,73 @@ // Setup B to vote "NO" on the next PREPARE request. ((HAGlueTest) startup.serverB).voteNo(); -// // Setup B to fail the next PREPARE request. -// ((HAGlueTest) startup.serverB) -// .failNext("prepare2Phase", -// new Class[] { IHA2PhasePrepareMessage.class }, -// 0/* nwait */, 1/* nfail */); + // Simple transaction. + simpleTransaction(); + + // Verify quorum is unchanged. + assertEquals(token, quorum.token()); + + // Should be two commit points on {A,C]. + awaitCommitCounter(2L, startup.serverA, startup.serverC); + + /* + * B should go into an ERROR state and then into SeekConsensus and from + * there to RESYNC and finally back to RunMet. We can not reliably + * observe the intervening states. So what we really need to do is watch + * for B to move to the end of the pipeline and catch up to the same + * commit point. + */ + /* + * The pipeline should be reordered. B will do a service leave, then + * enter seek consensus, and then re-enter the pipeline. + */ + awaitPipeline(new HAGlue[] { startup.serverA, startup.serverC, + startup.serverB }); + + /* + * There should be two commit points on {A,C,B} (note that this assert + * does not pay attention to the pipeline order). + */ + awaitCommitCounter(2L, startup.serverA, startup.serverC, + startup.serverB); + + // B should be a follower again. + awaitHAStatus(startup.serverB, HAStatusEnum.Follower); + + // quorum token is unchanged. + assertEquals(token, quorum.token()); + + } + + /** + * Three services are started in [A,B,C] order. B is setup for + * {@link HACommitGlue#prepare2Phase(IHA2PhasePrepareMessage)} to vote "NO". + * A simple transaction is performed. We verify that the transaction + * completes successfully, that the quorum token is unchanged, and that + * [A,C] both participated in the commit. We also verify that B is moved to + * the end of the pipeline (by doing a serviceLeave and then re-entering the + * pipeline) and that it resyncs with the met quorum and finally re-joins + * with the met quorum. The quorum should not break across this test. + */ + public void testStartABC_prepare2Phase_B_throws_exception() + throws Exception { + + // Enforce the join order. + final ABC startup = new ABC(true /*sequential*/); + + final long token = awaitFullyMetQuorum(); + + // Should be one commit point. + awaitCommitCounter(1L, startup.serverA, startup.serverB, + startup.serverC); + + // Setup B to fail the next PREPARE request. + ((HAGlueTest) startup.serverB) + .failNext("prepare2Phase", + new Class[] { IHA2PhasePrepareMessage.class }, + 0/* nwait */, 1/* nfail */); + // Simple transaction. simpleTransaction(); @@ -202,6 +262,63 @@ // Should be two commit points on {A,C]. awaitCommitCounter(2L, startup.serverA, startup.serverC); + /* + * FIXME Unlike the test above, if there is a problem making the RMI + * call, then B will not go through its doRejectedCommit() handler and + * will not enter the ERROR state directly. We need to have B notice + * that it is no longer at the same commit point, e.g., by observing a + * LIVE write cache message with an unexpected value for the + * commitCounter (especially, GT its current expected value). That is + * the indication that B needs to enter an error state. Until then it + * does not know that there was an attempt to PREPARE since it did not + * get the prepare2Phase() message. + * + * - Modify HAJournalServer to enter the error state if we observe a + * live write cache block for a commitCounter != the expected + * commitCounter. + * + * - Modify commit2Phase() to accept the #of services that are + * participating in the commit. If it is not a full quorum, then we can + * not purge the HA logs in commit2Phase() regardless of what the quorum + * state looks like. + * + * - Modify this test to do another transaction. B can not notice the + * problem until there is another write cache flushed through the + * pipeline. + * + * - Modify this test to await B to move to the end of the pipeline, + * resync, and rejoin. + */ + + // Should be two commit points on {A,C}. + awaitCommitCounter(2L, startup.serverA, startup.serverC); + + // Should be ONE commit points on {B}. + awaitCommitCounter(1L, startup.serverB); + + // A commit is necessary for B to notice that it did not prepare. + simpleTransaction(); + + /* + * The pipeline should be reordered. B will do a service leave, then + * enter seek consensus, and then re-enter the pipeline. + */ + awaitPipeline(new HAGlue[] { startup.serverA, startup.serverC, + startup.serverB }); + + /* + * There should be three commit points on {A,C,B} (note that this assert + * does not pay attention to the pipeline order). + */ + awaitCommitCounter(3L, startup.serverA, startup.serverC, + startup.serverB); + + // B should be a follower again. + awaitHAStatus(startup.serverB, HAStatusEnum.Follower); + + // quorum token is unchanged. + assertEquals(token, quorum.token()); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-17 17:41:10
|
Revision: 7141 http://bigdata.svn.sourceforge.net/bigdata/?rev=7141&view=rev Author: thompsonbry Date: 2013-05-17 17:40:53 +0000 (Fri, 17 May 2013) Log Message: ----------- I have re-enabled the fail() (vs warn) in StressTestConcurrentTx. It is running green. See https://sourceforge.net/apps/trac/bigdata/ticket/557 (StressTestConcurrentTx may ignore real errors) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/test/com/bigdata/journal/StressTestConcurrentTx.java Modified: branches/READ_CACHE/bigdata/src/test/com/bigdata/journal/StressTestConcurrentTx.java =================================================================== --- branches/READ_CACHE/bigdata/src/test/com/bigdata/journal/StressTestConcurrentTx.java 2013-05-17 14:44:41 UTC (rev 7140) +++ branches/READ_CACHE/bigdata/src/test/com/bigdata/journal/StressTestConcurrentTx.java 2013-05-17 17:40:53 UTC (rev 7141) @@ -276,6 +276,7 @@ int ncommitted = 0; // #of transactions that successfully committed. int nuncommitted = 0; // #of transactions that did not complete in time. + try { while(itr.hasNext()) { final Future<Long> future = itr.next(); @@ -333,8 +334,8 @@ * Other kinds of exceptions are errors. */ - // fail("Not expecting: "+ex, ex); - log.warn("Not expecting: "+ex, ex); + fail("Not expecting: "+ex, ex); +// log.warn("Not expecting: "+ex, ex); } @@ -342,18 +343,22 @@ } - // Now test rootBlocks - int rootBlockCount = 0; - final Iterator<IRootBlockView> rbvs = journal.getRootBlocks(10); // cannot use 0 - while (rbvs.hasNext()) { - final IRootBlockView rbv = rbvs.next(); - rootBlockCount++; - } - + /* + * Note: Code was commented out (also see report below) because + * journal.getRootBlocks() was not implemented correctly. + */ +// // Now test rootBlocks +// int rootBlockCount = 0; +// final Iterator<IRootBlockView> rbvs = journal.getRootBlocks(1); +// while (rbvs.hasNext()) { +// final IRootBlockView rbv = rbvs.next(); +// rootBlockCount++; +// } + } finally { // immediately terminate any tasks that are still running. log.warn("Shutting down now!"); journal.shutdownNow(); - + } final Result ret = new Result(); /* @@ -369,7 +374,7 @@ ret.put("naborted",""+naborted); ret.put("ncommitted",""+ncommitted); ret.put("nuncommitted", ""+nuncommitted); - ret.put("rootBlocks found", ""+rootBlockCount); +// ret.put("rootBlocks found", ""+rootBlockCount); ret.put("elapsed(ms)", ""+elapsed); ret.put("tps", ""+(ncommitted * 1000 / elapsed)); ret.put("bytesWritten", ""+bytesWritten); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-17 14:45:25
|
Revision: 7140 http://bigdata.svn.sourceforge.net/bigdata/?rev=7140&view=rev Author: thompsonbry Date: 2013-05-17 14:44:41 +0000 (Fri, 17 May 2013) Log Message: ----------- Removing a hot spot in DefaultResourceLocator per [1] [1] https://sourceforge.net/apps/trac/bigdata/ticket/677 (HA deadlock under UPDATE + QUERY) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/relation/locator/DefaultResourceLocator.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/relation/locator/DefaultResourceLocator.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/relation/locator/DefaultResourceLocator.java 2013-05-16 20:24:56 UTC (rev 7139) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/relation/locator/DefaultResourceLocator.java 2013-05-17 14:44:41 UTC (rev 7140) @@ -651,6 +651,27 @@ final Journal journal = (Journal) indexManager; + /* + * Note: Using the local transaction manager to resolve a + * read-only transaction identifer to the ITx object and then + * retrieving the readsOnCommitTime from that ITx is a + * non-blocking code path. It is preferrable to looking up the + * commitRecord in the CommitRecordIndex, which can be + * contended. This non-blocking code path will handle any + * read-only tx, but it will not be able to locate a timestamp + * not protected by a tx. + */ + + final ITx tx = journal.getTransactionManager().getTx( + timestamp); + + if (tx != null) { + + // Fast path. + commitTime2 = readTime = tx.getReadsOnCommitTime(); + + } else { + // find the commit record on which we need to read. final ICommitRecord commitRecord = journal .getCommitRecord(TimestampUtility @@ -676,6 +697,8 @@ commitTime2 = readTime = commitRecord.getTimestamp(); + } + } else { /* This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-16 20:25:08
|
Revision: 7139 http://bigdata.svn.sourceforge.net/bigdata/?rev=7139&view=rev Author: thompsonbry Date: 2013-05-16 20:24:56 +0000 (Thu, 16 May 2013) Log Message: ----------- Merging changes from the development branch into the HA branch (READ_CACHE). @r7138. See [1] for details on the previous merge. {{{ merge https://bigdata.svn.sourceforge.net/svnroot/bigdata/branches/BIGDATA_RELEASE_1_2_0 /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE --- Merging r7077 through r7138 into /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/pom.xml U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/build.properties U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/search/FullTextIndex.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/solutions/JVMDistinctBindingSetsOp.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/ModifiableBOpBase.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/IDistinctFilter.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinUtility.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMDistinctFilter.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/SolutionSetHashJoinOp.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashJoinAnnotations.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashIndexOp.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashIndex.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMSolutionSetHashJoinOp.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/journal/Name2Addr.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/journal/Tx.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractTask.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/.classpath A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestTicket669.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailWithSids.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailWithoutSids.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestTicket647.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailWithQuads.java --- Merging r7077 through r7138 into /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/InsertServlet.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/UpdateServlet.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/client/RemoteRepository.java --- Merging r7077 through r7138 into /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/remote/BigdataSailRemoteRepositoryConnection.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/lib/nxparser-1.2.3.jar D /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/lib/nxparser-1.2.2.jar U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTSubGroupJoinVarOptimizer.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestNegation.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/store/BD.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicIntQueryHint.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractQueryHint.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicDoubleQueryHint.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicBooleanQueryHint.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractStringQueryHint.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/CutoffLimitHint.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicLongQueryHint.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicStringQueryHint.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/GraphPatternGroup.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SliceServiceFactory.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AbstractServiceFactory.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SampleServiceFactory.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUtility.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/FunctionNode.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/AbstractJoinGroupOptimizer.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTRangeOptimizer.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTSparql11SubqueryOptimizer.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/DefaultOptimizerList.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTComplexOptionalOptimizer.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTSubGroupJoinVarOptimizer.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTCardinalityOptimizer.java A /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTFlattenJoinGroupsOptimizer.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/GroupNodeBase.java U /Users/bryan/Documents/workspace/BIGDATA_READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java Merge complete. ===== File Statistics: ===== Deleted: 1 Added: 16 Updated: 46 }}} No conflicts. [1] https://sourceforge.net/apps/trac/bigdata/ticket/530#comment:111 Revision Links: -------------- http://bigdata.svn.sourceforge.net/bigdata/?rev=7138&view=rev http://bigdata.svn.sourceforge.net/bigdata/?rev=7077&view=rev http://bigdata.svn.sourceforge.net/bigdata/?rev=7138&view=rev http://bigdata.svn.sourceforge.net/bigdata/?rev=7077&view=rev http://bigdata.svn.sourceforge.net/bigdata/?rev=7138&view=rev http://bigdata.svn.sourceforge.net/bigdata/?rev=7077&view=rev http://bigdata.svn.sourceforge.net/bigdata/?rev=7138&view=rev Modified Paths: -------------- branches/READ_CACHE/.classpath branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/ModifiableBOpBase.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashJoinAnnotations.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashIndexOp.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinUtility.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMSolutionSetHashJoinOp.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/SolutionSetHashJoinOp.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/solutions/JVMDistinctBindingSetsOp.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractTask.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Name2Addr.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Tx.java branches/READ_CACHE/bigdata/src/java/com/bigdata/search/FullTextIndex.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/FunctionNode.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/GraphPatternGroup.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/GroupNodeBase.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUtility.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractQueryHint.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/CutoffLimitHint.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTCardinalityOptimizer.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTComplexOptionalOptimizer.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTRangeOptimizer.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTSparql11SubqueryOptimizer.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTSubGroupJoinVarOptimizer.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/AbstractJoinGroupOptimizer.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/DefaultOptimizerList.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/store/BD.java branches/READ_CACHE/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestNegation.java branches/READ_CACHE/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTSubGroupJoinVarOptimizer.java branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/remote/BigdataSailRemoteRepositoryConnection.java branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/InsertServlet.java branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/UpdateServlet.java branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/client/RemoteRepository.java branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailWithQuads.java branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailWithSids.java branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailWithoutSids.java branches/READ_CACHE/build.properties branches/READ_CACHE/pom.xml Added Paths: ----------- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/IDistinctFilter.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMDistinctFilter.java branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashIndex.java branches/READ_CACHE/bigdata-rdf/lib/nxparser-1.2.3.jar branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AbstractServiceFactory.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SampleServiceFactory.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SliceServiceFactory.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractStringQueryHint.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicBooleanQueryHint.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicDoubleQueryHint.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicIntQueryHint.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicLongQueryHint.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicStringQueryHint.java branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTFlattenJoinGroupsOptimizer.java branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestTicket647.java branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/TestTicket669.java Removed Paths: ------------- branches/READ_CACHE/bigdata-rdf/lib/nxparser-1.2.2.jar Property Changed: ---------------- branches/READ_CACHE/ branches/READ_CACHE/bigdata/lib/jetty/ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/aggregate/ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/joinGraph/ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/util/ branches/READ_CACHE/bigdata/src/java/com/bigdata/htree/raba/ branches/READ_CACHE/bigdata/src/java/com/bigdata/jsr166/ branches/READ_CACHE/bigdata/src/test/com/bigdata/bop/joinGraph/ branches/READ_CACHE/bigdata/src/test/com/bigdata/bop/util/ branches/READ_CACHE/bigdata/src/test/com/bigdata/jsr166/ branches/READ_CACHE/bigdata/src/test/com/bigdata/util/httpd/ branches/READ_CACHE/bigdata-compatibility/ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/attr/ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/disco/ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/util/config/ branches/READ_CACHE/bigdata-perf/ branches/READ_CACHE/bigdata-perf/btc/ branches/READ_CACHE/bigdata-perf/btc/src/resources/ branches/READ_CACHE/bigdata-perf/lubm/ branches/READ_CACHE/bigdata-perf/uniprot/ branches/READ_CACHE/bigdata-perf/uniprot/src/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/bop/rdf/aggregate/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/changesets/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/error/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/internal/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/relation/ branches/READ_CACHE/bigdata-rdf/src/java/com/bigdata/rdf/util/ branches/READ_CACHE/bigdata-rdf/src/samples/ branches/READ_CACHE/bigdata-rdf/src/test/com/bigdata/bop/rdf/aggregate/ branches/READ_CACHE/bigdata-rdf/src/test/com/bigdata/rdf/internal/ branches/READ_CACHE/bigdata-rdf/src/test/com/bigdata/rdf/relation/ branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/bench/ branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/ branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/bench/ branches/READ_CACHE/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/ branches/READ_CACHE/dsi-utils/ branches/READ_CACHE/dsi-utils/LEGAL/ branches/READ_CACHE/dsi-utils/lib/ branches/READ_CACHE/dsi-utils/src/ branches/READ_CACHE/dsi-utils/src/java/ branches/READ_CACHE/dsi-utils/src/java/it/ branches/READ_CACHE/dsi-utils/src/java/it/unimi/ branches/READ_CACHE/dsi-utils/src/test/ branches/READ_CACHE/dsi-utils/src/test/it/unimi/ branches/READ_CACHE/dsi-utils/src/test/it/unimi/dsi/ branches/READ_CACHE/lgpl-utils/src/java/it/unimi/dsi/fastutil/bytes/custom/ branches/READ_CACHE/lgpl-utils/src/test/it/unimi/dsi/fastutil/bytes/custom/ branches/READ_CACHE/osgi/ branches/READ_CACHE/src/resources/bin/config/ Property changes on: branches/READ_CACHE ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE:6769-6785 /branches/BIGDATA_RELEASE_1_2_0:6766-7077 /branches/BTREE_BUFFER_BRANCH:2004-2045 /branches/DEV_BRANCH_27_OCT_2009:2270-2546,2548-2782 /branches/INT64_BRANCH:4486-4522 /branches/JOURNAL_HA_BRANCH:2596-4066 /branches/LARGE_LITERALS_REFACTOR:4175-4387 /branches/LEXICON_REFACTOR_BRANCH:2633-3304 /branches/QUADS_QUERY_BRANCH:4525-4531,4550-4584,4586-4609,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH:4814-4836 /branches/bugfix-btm:2594-3237 /branches/dev-btm:2574-2730 /branches/fko:3150-3194 /trunk:3392-3437,3656-4061 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE:6769-6785 /branches/BIGDATA_RELEASE_1_2_0:6766-7138 /branches/BTREE_BUFFER_BRANCH:2004-2045 /branches/DEV_BRANCH_27_OCT_2009:2270-2546,2548-2782 /branches/INT64_BRANCH:4486-4522 /branches/JOURNAL_HA_BRANCH:2596-4066 /branches/LARGE_LITERALS_REFACTOR:4175-4387 /branches/LEXICON_REFACTOR_BRANCH:2633-3304 /branches/QUADS_QUERY_BRANCH:4525-4531,4550-4584,4586-4609,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH:4814-4836 /branches/bugfix-btm:2594-3237 /branches/dev-btm:2574-2730 /branches/fko:3150-3194 /trunk:3392-3437,3656-4061 Modified: branches/READ_CACHE/.classpath =================================================================== --- branches/READ_CACHE/.classpath 2013-05-16 20:16:19 UTC (rev 7138) +++ branches/READ_CACHE/.classpath 2013-05-16 20:24:56 UTC (rev 7139) @@ -32,7 +32,6 @@ <classpathentry exported="true" kind="lib" path="bigdata/lib/dsi-utils-1.0.6-020610.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/lgpl-utils-1.0.6-020610.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-jini/lib/apache/zookeeper-3.3.3.jar"/> - <classpathentry exported="true" kind="lib" path="bigdata-rdf/lib/nxparser-1.2.2.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-continuation-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-http-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-io-7.2.2.v20101205.jar"/> @@ -84,5 +83,6 @@ <classpathentry kind="lib" path="bigdata-rdf/lib/sesame-rio-testsuite-2.6.10.jar"/> <classpathentry kind="lib" path="bigdata-sails/lib/sesame-sparql-testsuite-2.6.10.jar"/> <classpathentry kind="lib" path="bigdata-sails/lib/sesame-store-testsuite-2.6.10.jar"/> + <classpathentry kind="lib" path="bigdata-rdf/lib/nxparser-1.2.3.jar"/> <classpathentry kind="output" path="bin"/> </classpath> Property changes on: branches/READ_CACHE/bigdata/lib/jetty ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/lib/jetty:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/jetty:6766-7077 /branches/INT64_BRANCH/bigdata/lib/jetty:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/lib/jetty:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/lib/jetty:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/lib/jetty:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/lib/jetty:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/jetty:6766-7138 /branches/INT64_BRANCH/bigdata/lib/jetty:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/lib/jetty:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/lib/jetty:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/lib/jetty:4814-4836 Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/ModifiableBOpBase.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/ModifiableBOpBase.java 2013-05-16 20:16:19 UTC (rev 7138) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/ModifiableBOpBase.java 2013-05-16 20:24:56 UTC (rev 7139) @@ -164,6 +164,16 @@ return args.get(index); } + + /** + * Return the index of the bop in the args. Returns -1 if bop is not + * present in the args. + */ + public int indexOf(final BOp bop) { + + return args.indexOf(bop); + + } /** * Invoked automatically any time a mutation operation occurs. The default @@ -254,7 +264,7 @@ * Add a new argument (core mutation method) at the specified index. * * @param index - * The index of the child expression to be replaced. + * The index at which the child expression is to be inserted. * @param newArg * The argument. * Property changes on: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/aggregate ___________________________________________________________________ Modified: svn:mergeinfo - /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/bop/aggregate:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/aggregate:6766-7077 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/bop/aggregate:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4814-4836 + /branches/BIGDATA_OPENRDF_2_6_9_UPDATE/bigdata/src/java/com/bigdata/bop/aggregate:6769-6785 /branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/aggregate:6766-7138 /branches/INT64_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4486-4522 /branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4525-4531,4533-4548,4550-4584,4586-4609,4611-4632,4634-4643,4646-4672,4674-4685,4687-4693,4697-4735,4737-4782,4784-4792,4794-4796,4798-4801 /branches/RWSTORE_1_1_0_DEBUG/bigdata/src/java/com/bigdata/bop/aggregate:5896-5935 /branches/TIDS_PLUS_BLOBS_BRANCH/bigdata/src/java/com/bigdata/bop/aggregate:4814-4836 Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java 2013-05-16 20:16:19 UTC (rev 7138) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java 2013-05-16 20:24:56 UTC (rev 7139) @@ -53,7 +53,7 @@ HTreeHashJoinAnnotations { } - + /** * Deep copy constructor. */ Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java 2013-05-16 20:16:19 UTC (rev 7138) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java 2013-05-16 20:24:56 UTC (rev 7139) @@ -40,6 +40,7 @@ import com.bigdata.bop.BOpContext; import com.bigdata.bop.Constant; import com.bigdata.bop.HTreeAnnotations; +import com.bigdata.bop.HashMapAnnotations; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IConstant; import com.bigdata.bop.IConstraint; @@ -202,6 +203,14 @@ private final AtomicBoolean open = new AtomicBoolean(true); /** + * The operator whose annotations are used to initialize this object. + * <p> + * Note: This was added to support the DISTINCT FILTER in + * {@link #outputSolutions(IBuffer)}. + */ + private final PipelineOp op; + + /** * This basically controls the vectoring of the hash join. * * TODO parameter from operator annotations. Note that 10k tends to put too @@ -259,6 +268,16 @@ private final IVariable<?>[] selectVars; /** + * The variables to be projected into a join group. When non- + * <code>null</code> variables that are NOT in this array are NOT flowed + * into the join group. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/668" > + * JoinGroup optimizations </a> + */ + private final IVariable<?>[] projectedInVars; + + /** * The join constraints (optional). */ private final IConstraint[] constraints; @@ -344,6 +363,8 @@ if (askVar != null) sb.append(",askVar=" + askVar); sb.append(",joinVars=" + Arrays.toString(joinVars)); + if (projectedInVars != null) + sb.append(",projectedInVars=" + Arrays.toString(projectedInVars)); if (selectVars != null) sb.append(",selectVars=" + Arrays.toString(selectVars)); if (constraints != null) @@ -497,7 +518,7 @@ if(joinType == null) throw new IllegalArgumentException(); -// this.op = op; + this.op = op; this.joinType = joinType; this.optional = joinType == JoinTypeEnum.Optional; this.filter = joinType == JoinTypeEnum.Filter; @@ -516,6 +537,12 @@ .getProperty(JoinAnnotations.SELECT); /* + * The variables that are projected IN to the join group. + */ + this.projectedInVars = (IVariable<?>[]) op + .getProperty(HashJoinAnnotations.PROJECT_IN_VARS); + + /* * This wraps an efficient raw store interface around a child memory * manager created from the IMemoryManager which will back the named * solution set. @@ -1524,82 +1551,179 @@ } + /** + * DISTINCT solutions filter for + * {@link HTreeHashJoinUtility#outputSolutions(IBuffer)} + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/668" > + * JoinGroup optimizations </a> + */ + private class HTreeDistinctFilter implements IDistinctFilter { + + /** + * The variables used to impose a distinct constraint. + */ + private final IVariable<?>[] vars; + + private final HTreeHashJoinUtility state; + + public HTreeDistinctFilter(final IVariable<?>[] vars, final PipelineOp op) { + + this.vars = vars; + + this.state = new HTreeHashJoinUtility( + ((MemStore) store).getMemoryManager(), op, + JoinTypeEnum.Filter); + + } + + @Override + public IVariable<?>[] getProjectedVars() { + + return vars; + + } + + @Override + public IBindingSet accept(final IBindingSet bset) { + // FIXME Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public long filterSolutions(ICloseableIterator<IBindingSet[]> itr, + BOpStats stats, IBuffer<IBindingSet> sink) { + // FIXME Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void release() { + + state.release(); + + } + + } + @Override public void outputSolutions(final IBuffer<IBindingSet> out) { try { -// if (false) { -// -// /* -// * Striterator pattern. -// */ -// -// final ICloseableIterator<IBindingSet> itr = indexScan(); -// -// try { -// -// while(itr.hasNext()) { -// -// IBindingSet bset = itr.next(); -// -// if (selectVars != null) { -// -// // Drop variables which are not projected. -// bset = bset.copy(selectVars); -// -// } -// out.add(bset); -// -// } -// -// } finally { -// -// itr.close(); -// -// } -// -// -// } else { + /* + * FIXME Set this to enable "DISTINCT" on the solutions flowing into the + * join group. + * + * Note: This should be set by the HashIndexOp (or passed in through the + * interface). + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/668" > + * JoinGroup optimizations </a> + */ + final boolean distinct = false; + + /* + * FIXME Replace with an HTreeDistinctFilter and integrate to NOT + * flow duplicate solutions into the sub-group. The HTree + * filterSolutions() method needs to be vectored to be efficient. + * Therefore, this outputSolutions() method needs to be rewritten to + * be vectored as well. It is efficient in reading the solutions + * from the HTree, and the solutions are in the "natural" order of + * the HTree for the join vars. This order SHOULD be pretty + * efficient for the DISTINCT solutions set as well, but note that + * joinVars:=projectedInVars. To maximize the corrleation, both the + * joinVars[] and the projectedInVars[] should be sorted so the + * variables in the solutions will be correllated and any variables + * that are NOT in the projectedInVars should appear towards the end + * of the joinVars where they will cause the least perturbation in + * this scan + filter. + */ + final IDistinctFilter distinctFilter; + + if (distinct && projectedInVars != null && projectedInVars.length > 0) { /* - * Simple iterator pattern. + * Note: We are single threaded here so we can use a lower + * concurrencyLevel value. + * + * Note: If necessary, this could be replaced with JVMHashIndex so + * we get the #of occurrences of each distinct combination of + * bindings that is projected into the sub-group/-query. */ + final int concurrencyLevel = 1;//ConcurrentHashMapAnnotations.DEFAULT_CONCURRENCY_LEVEL; + + distinctFilter = new JVMDistinctFilter(projectedInVars, // + op.getProperty(HashMapAnnotations.INITIAL_CAPACITY, + HashMapAnnotations.DEFAULT_INITIAL_CAPACITY),// + op.getProperty(HashMapAnnotations.LOAD_FACTOR, + HashMapAnnotations.DEFAULT_LOAD_FACTOR),// + concurrencyLevel + ); - final HTree rightSolutions = getRightSolutions(); + } else { + + distinctFilter = null; + + } + + final HTree rightSolutions = getRightSolutions(); - if (log.isInfoEnabled()) { - log.info("rightSolutions: #nnodes=" - + rightSolutions.getNodeCount() + ",#leaves=" - + rightSolutions.getLeafCount() + ",#entries=" - + rightSolutions.getEntryCount()); - } + if (log.isInfoEnabled()) { + log.info("rightSolutions: #nnodes=" + + rightSolutions.getNodeCount() + ",#leaves=" + + rightSolutions.getLeafCount() + ",#entries=" + + rightSolutions.getEntryCount()); + } - // source. - final ITupleIterator<?> solutionsIterator = rightSolutions - .rangeIterator(); + // source. + final ITupleIterator<?> solutionsIterator = rightSolutions + .rangeIterator(); - while (solutionsIterator.hasNext()) { + while (solutionsIterator.hasNext()) { - final ITuple<?> t = solutionsIterator.next(); + final ITuple<?> t = solutionsIterator.next(); - IBindingSet bset = decodeSolution(t); + IBindingSet bset = decodeSolution(t); - if (selectVars != null) { + if (distinctFilter != null) { - // Drop variables which are not projected. - bset = bset.copy(selectVars); + /* + * Note: The DISTINCT filter is based on the variables + * that are projected INTO the child join group. + * However, those are NOT always the same as the + * variables that are projected OUT of the child join + * group, so we need to + */ + if ((bset = distinctFilter.accept(bset)) == null) { + + // Drop duplicate solutions. + continue; + } - encoder.resolveCachedValues(bset); + } else if (selectVars != null) { - out.add(bset); + /* + * FIXME We should be using projectedInVars here since + * outputSolutions() is used to stream solutions into + * the child join group (at least for some kinds of + * joins, but there might be exceptions for joining with + * a named solution set). + */ + // Drop variables which are not projected. + bset = bset.copy(selectVars); + } -// } + encoder.resolveCachedValues(bset); + out.add(bset); + + } + } catch (Throwable t) { throw launderThrowable(t); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java 2013-05-16 20:16:19 UTC (rev 7138) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java 2013-05-16 20:24:56 UTC (rev 7139) @@ -114,8 +114,7 @@ * @param args * @param annotations */ - public HashIndexOp(final BOp[] args, - final Map<String, Object> annotations) { + public HashIndexOp(final BOp[] args, final Map<String, Object> annotations) { super(args, annotations); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashJoinAnnotations.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashJoinAnnotations.java 2013-05-16 20:16:19 UTC (rev 7138) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/HashJoinAnnotations.java 2013-05-16 20:24:56 UTC (rev 7139) @@ -84,4 +84,13 @@ */ long DEFAULT_NO_JOIN_VARS_LIMIT = Long.MAX_VALUE; + + /** + * The {@link IVariable[]} specifying what variables need to flow into + * the right operator of the hash join (i.e. what visible variables inside + * the right operator have appeared previously in the query and may be + * bound). + */ + String PROJECT_IN_VARS = HashJoinAnnotations.class.getName() + ".projectInVars"; + } Copied: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/IDistinctFilter.java (from rev 7138, branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/IDistinctFilter.java) =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/IDistinctFilter.java (rev 0) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/IDistinctFilter.java 2013-05-16 20:24:56 UTC (rev 7139) @@ -0,0 +1,81 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Apr 29, 2013 + */ +package com.bigdata.bop.join; + +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.engine.BOpStats; +import com.bigdata.relation.accesspath.IBuffer; +import com.bigdata.striterator.ICloseableIterator; + +/** + * A "DISTINCT" filter for {@link IBindingSet}s. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public interface IDistinctFilter { + + /** + * The variables that are being projected out of the DISTINCT filter. The + * solutions will be DISTINCT on this combination of variables. Bindings on + * other variables will be dropped. + */ + IVariable<?>[] getProjectedVars(); + + /** + * If the bindings are distinct for the configured variables then return a + * new {@link IBindingSet} consisting of only the selected variables. + * + * @param bset + * The binding set to be filtered. + * + * @return A new {@link IBindingSet} containing only the distinct as bound + * values -or- <code>null</code> if the binding set duplicates a + * solution which was already accepted. + */ + IBindingSet accept(final IBindingSet bset); + + /** + * Vectored DISTINCT. + * + * @param itr + * The source solutions. + * @param stats + * Statistics object to be updated. + * @param sink + * The sink onto which the DISTINCT solutions will be written. + * @return The #of DISTINCT solutions. + */ + long filterSolutions(final ICloseableIterator<IBindingSet[]> itr, + final BOpStats stats, final IBuffer<IBindingSet> sink); + + /** + * Discard the map backing this filter. + */ + void release(); + +} \ No newline at end of file Copied: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMDistinctFilter.java (from rev 7138, branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMDistinctFilter.java) =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMDistinctFilter.java (rev 0) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMDistinctFilter.java 2013-05-16 20:24:56 UTC (rev 7139) @@ -0,0 +1,269 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Apr 26, 2013 + */ +package com.bigdata.bop.join; + +import java.util.Arrays; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.log4j.Logger; + +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IConstant; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.bindingSet.ListBindingSet; +import com.bigdata.bop.engine.BOpStats; +import com.bigdata.relation.accesspath.IBuffer; +import com.bigdata.striterator.ICloseableIterator; + +/** + * Utility class for imposing a DISTINCT filter on {@link IBindingSet}. This + * class is thread-safe. It is based on a {@link ConcurrentHashMap}. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class JVMDistinctFilter implements IDistinctFilter { + + private static final Logger log = Logger.getLogger(JVMDistinctFilter.class); + + /** + * Wrapper used for the as bound solutions in the {@link ConcurrentHashMap}. + */ + private static class Solution { + + private final int hash; + + private final IConstant<?>[] vals; + + public Solution(final IConstant<?>[] vals) { + this.vals = vals; + this.hash = java.util.Arrays.hashCode(vals); + } + + public int hashCode() { + return hash; + } + + public boolean equals(final Object o) { + if (this == o) + return true; + if (!(o instanceof Solution)) { + return false; + } + final Solution t = (Solution) o; + if (vals.length != t.vals.length) + return false; + for (int i = 0; i < vals.length; i++) { + // @todo verify that this allows for nulls with a unit test. + if (vals[i] == t.vals[i]) + continue; + if (vals[i] == null) + return false; + if (!vals[i].equals(t.vals[i])) + return false; + } + return true; + } + } + + /** + * The variables used to impose a distinct constraint. + */ + private final IVariable<?>[] vars; + + /** + * A concurrent map whose keys are the bindings on the specified variables + * (the keys and the values are the same since the map implementation does + * not allow <code>null</code> values). + * <p> + * Note: The map is shared state and can not be discarded or cleared until + * the last invocation!!! + */ + private final ConcurrentHashMap<Solution, Solution> map; + + /** + * + * @param vars + * The set of variables on which the DISTINCT filter will be + * imposed. Only these variables will be present in the + * "accepted" solutions. Any variable bindings not specified in + * this array will be dropped. + * @param initialCapacity + * @param loadFactor + * @param concurrencyLevel + */ + public JVMDistinctFilter(final IVariable<?>[] vars, + final int initialCapacity, final float loadFactor, + final int concurrencyLevel) { + + if (vars == null) + throw new IllegalArgumentException(); + + if (vars.length == 0) + throw new IllegalArgumentException(); + + this.vars = vars; + + this.map = new ConcurrentHashMap<Solution, Solution>(initialCapacity, + loadFactor, concurrencyLevel); + + } + + /* (non-Javadoc) + * @see com.bigdata.bop.join.IDistinctFilter#clear() + */ + @Override + public void release() { + + map.clear(); + + } + + @Override + public IVariable<?>[] getProjectedVars() { + + return vars; + + } + + /** + * If the bindings are distinct for the configured variables then return + * those bindings. + * + * @param bset + * The binding set to be filtered. + * + * @return The distinct as bound values -or- <code>null</code> if the + * binding set duplicates a solution which was already accepted. + */ + private IConstant<?>[] _accept(final IBindingSet bset) { + + final IConstant<?>[] r = new IConstant<?>[vars.length]; + + for (int i = 0; i < vars.length; i++) { + + /* + * Note: This allows null's. + * + * @todo write a unit test when some variables are not bound. + */ + r[i] = bset.get(vars[i]); + + } + + final Solution s = new Solution(r); + + if (log.isTraceEnabled()) + log.trace("considering: " + Arrays.toString(r)); + + final boolean distinct = map.putIfAbsent(s, s) == null; + + if (distinct && log.isDebugEnabled()) + log.debug("accepted: " + Arrays.toString(r)); + + return distinct ? r : null; + + } + + /* (non-Javadoc) + * @see com.bigdata.bop.join.IDistinctFilter#accept(com.bigdata.bop.IBindingSet) + */ + @Override + public IBindingSet accept(final IBindingSet bset) { + + final IConstant<?>[] vals = _accept(bset); + + if (vals == null) { + + /* + * This is a duplicate solution. + */ + + return null; + + } + + /* + * This is a distinct solution. Copy only the variables used to select + * distinct solutions into a new binding set and add that to the set of + * [accepted] binding sets which will be emitted by this operator. + */ + + final ListBindingSet tmp = new ListBindingSet(); + + for (int i = 0; i < vars.length; i++) { + + if (vals[i] != null) + tmp.set(vars[i], vals[i]); + + } + + return tmp; + + } + + @Override + public long filterSolutions(final ICloseableIterator<IBindingSet[]> itr, + final BOpStats stats, final IBuffer<IBindingSet> sink) { + + long n = 0L; + + while (itr.hasNext()) { + + final IBindingSet[] a = itr.next(); + + stats.chunksIn.increment(); + stats.unitsIn.add(a.length); + + for (IBindingSet bset : a) { + + /* + * Test to see if this solution is distinct from those already + * seen. + */ + if ((bset = accept(bset)) == null) { + + // Drop duplicate solution. + continue; + } + + /* + * This is a distinct solution. + */ + + sink.add(bset); + + n++; + + } + + } // next chunk. + + return n; + + } + +} Copied: branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashIndex.java (from rev 7138, branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashIndex.java) =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashIndex.java (rev 0) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/bop/join/JVMHashIndex.java 2013-05-16 20:24:56 UTC (rev 7139) @@ -0,0 +1,694 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Apr 29, 2013 + */ +package com.bigdata.bop.join; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IConstant; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.solutions.JVMDistinctBindingSetsOp; +import com.bigdata.counters.CAT; + +/** + * A hash index for {@link IBindingSet}s that supports duplicate solutions and + * hit counts. The hit counts are used to detect {@link IBindingSet}s that do + * not join for OPTIONAL, MINUS, and related kinds of "negation" joins. + * <p> + * Note: The {@link JVMDistinctBindingSetsOp} does not use this class right now + * because it enjoys better concurrency than the {@link JVMHashIndex}. Also see + * {@link JVMDistinctFilter}, which is the backing implementation for the + * {@link JVMDistinctBindingSetsOp}. + * + * @see JVMDistinctFilter + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class JVMHashIndex { + + private static final Logger log = Logger.getLogger(JVMHashIndex.class); + + /** + * Note: If joinVars is an empty array, then the solutions will all hash to + * ONE (1). + */ + private static final int ONE = 1; + +// /** +// * Return the hash code which will be used as the key given the ordered +// * as-bound values for the join variables. +// * +// * @param joinVars +// * The join variables. +// * @param bset +// * The bindings whose as-bound hash code for the join variables +// * will be computed. +// * @param ignoreUnboundVariables +// * If a variable without a binding should be silently ignored. +// * +// * @return The hash code. +// * +// * @throws JoinVariableNotBoundException +// * if there is no binding for a join variable. +// */ +// private static int hashCode(final IVariable<?>[] joinVars, +// final IBindingSet bset, final boolean ignoreUnboundVariables) +// throws JoinVariableNotBoundException { +// +// int h = ONE; +// +// for (IVariable<?> v : joinVars) { +// +// final IConstant<?> c = bset.get(v); +// +// if (c == null) { +// +// if (ignoreUnboundVariables) +// continue; +// +// // Reject any solution which does not have a binding for a join +// // variable. +// +// throw new JoinVariableNotBoundException(v.getName()); +// +// } +// +// h = 31 * h + c.hashCode(); +// +// } +// +// if (log.isTraceEnabled()) +// log.trace("hashCode=" + h + ", joinVars=" +// + Arrays.toString(joinVars) + " : " + bset); +// +// return h; +// +// } + + /** + * Return an array of constants corresponding to the as-bound values of the + * join variables for the given solution. + * + * @param bset + * The solution. + * + * @return The as-bound values for the {@link #keyVars} for that solution + * -or- <code>null</code> if one or more join variables is not bound + * by the solution and {@link #indexSolutionsHavingUnboundJoinVars} + * is <code>false</code>. + * + * @see #keyVars + * @see #indexSolutionsHavingUnboundJoinVars + */ + private Key makeKey(//final IVariable<?>[] keyVars, + final IBindingSet bset +// final boolean indexSolutionsHavingUnboundJoinVars + ) { + + final IConstant<?>[] vals = new IConstant<?>[keyVars.length]; + + for (int i = 0; i < keyVars.length; i++) { + + final IVariable<?> v = keyVars[i]; + + vals[i] = bset.get(v); + + } + + int h = ONE; + + for (IVariable<?> v : keyVars) { + + final IConstant<?> c = bset.get(v); + + if (c == null) { + + if (!indexSolutionsHavingUnboundJoinVars) { + + /* + * Drop solution having an unbound join variable. + */ + + if (log.isDebugEnabled()) + log.debug("Join variable is not bound: var=" + v + + ", solution=" + bset); + + return null; + + } + + continue; + + } + + h = 31 * h + c.hashCode(); + + } + + if (log.isTraceEnabled()) + log.trace("hashCode=" + h + ", joinVars=" + + Arrays.toString(keyVars) + " : " + bset); + + return new Key(h, vals); + + } + + /** + * Wrapper for the keys in the hash table. This is necessary for the hash + * table to compare the keys as equal and also provides efficiencies in the + * hash code and equals() methods. + */ + public static class Key { + + private final int hash; + + private final IConstant<?>[] vals; + + private Key(final int hashCode, final IConstant<?>[] vals) { + this.vals = vals; + this.hash = hashCode; + } + + public int hashCode() { + return hash; + } + + public boolean equals(final Object o) { + if (this == o) + return true; + if (!(o instanceof Key)) { + return false; + } + final Key t = (Key) o; + if (vals.length != t.vals.length) + return false; + for (int i = 0; i < vals.length; i++) { + if (vals[i] == t.vals[i]) + continue; + if (vals[i] == null) + return false; + if (!vals[i].equals(t.vals[i])) + return false; + } + return true; + } + } + + /** + * An solution and a hit counter as stored in the {@link JVMHashIndex}. + */ + public static class SolutionHit { + + /** + * The input solution. + */ + final public IBindingSet solution; + + /** + * The #of hits on that solution. This may be used to detect solutions + * that did not join. E.g., by scanning and reporting out all solutions + * where {@link #nhits} is ZERO (0L). + */ + public final CAT nhits = new CAT(); + + private SolutionHit(final IBindingSet solution) { + + if (solution == null) + throw new IllegalArgumentException(); + + this.solution = solution; + + } + + public String toString() { + + return getClass().getName() + "{nhits=" + nhits + ",solution=" + + solution + "}"; + + } + + } // class SolutionHit + + /** + * A group of solutions having the same as-bound values for the join vars. + * Each solution is paired with a hit counter so we can support OPTIONAL + * semantics for the join. + */ + public static class Bucket implements Iterable<SolutionHit>, + Comparable<Bucket> { + + /** The hash code for this collision bucket. */ + private final int hashCode; + + /** + * A set of solutions (and their hit counters) which have the same + * as-bound values for the join variables. + */ + private final List<SolutionHit> solutions = new LinkedList<SolutionHit>(); + + public String toString() { + return super.toString() + + // + "{hashCode=" + hashCode + ",#solutions=" + solutions.size() + + "}"; + } + + public Bucket(final int hashCode, final IBindingSet solution) { + + this.hashCode = hashCode; + + add(solution); + + } + + public void add(final IBindingSet solution) { + + if (solution == null) + throw new IllegalArgumentException(); + + solutions.add(new SolutionHit(solution)); + + } + + /** + * Add the solution to the bucket iff the solutions is not already + * present in the bucket. + * <p> + * Note: There is already a hash index in place on the join variables + * when we are doing a DISTINCT filter. Further, only the "join" + * variables are "selected" and participate in a DISTINCT filter. + * Therefore, if we have a hash collision such that two solutions would + * be directed into the same {@link Bucket} then we can not improve + * matters but must simply scan the solutions in the bucket to decide + * whether the new solution duplicates a solution which is already + * present. + * + * @param solution + * The solution. + * + * @return <code>true</code> iff the bucket was modified by this + * operation. + */ + public boolean addDistinct(final IBindingSet solution) { + + if (solutions.isEmpty()) { + + // First solution. + solutions.add(new SolutionHit(solution)); + + return true; + + } + + final Iterator<SolutionHit> itr = solutions.iterator(); + + while (itr.hasNext()) { + + ... [truncated message content] |
From: <tho...@us...> - 2013-05-16 20:16:25
|
Revision: 7138 http://bigdata.svn.sourceforge.net/bigdata/?rev=7138&view=rev Author: thompsonbry Date: 2013-05-16 20:16:19 +0000 (Thu, 16 May 2013) Log Message: ----------- Missed the .classpath file when I changed the nxparser dependency. This commit updates the classpath for the eclipse IDE development environment. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/.classpath Modified: branches/BIGDATA_RELEASE_1_2_0/.classpath =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/.classpath 2013-05-16 19:43:43 UTC (rev 7137) +++ branches/BIGDATA_RELEASE_1_2_0/.classpath 2013-05-16 20:16:19 UTC (rev 7138) @@ -32,7 +32,6 @@ <classpathentry exported="true" kind="lib" path="bigdata/lib/dsi-utils-1.0.6-020610.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/lgpl-utils-1.0.6-020610.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-jini/lib/apache/zookeeper-3.3.3.jar"/> - <classpathentry exported="true" kind="lib" path="bigdata-rdf/lib/nxparser-1.2.2.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-continuation-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-http-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-io-7.2.2.v20101205.jar"/> @@ -84,5 +83,6 @@ <classpathentry kind="lib" path="bigdata-rdf/lib/sesame-rio-testsuite-2.6.10.jar"/> <classpathentry kind="lib" path="bigdata-sails/lib/sesame-sparql-testsuite-2.6.10.jar"/> <classpathentry kind="lib" path="bigdata-sails/lib/sesame-store-testsuite-2.6.10.jar"/> + <classpathentry kind="lib" path="bigdata-rdf/lib/nxparser-1.2.3.jar"/> <classpathentry kind="output" path="bin"/> </classpath> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mrp...@us...> - 2013-05-16 19:44:07
|
Revision: 7137 http://bigdata.svn.sourceforge.net/bigdata/?rev=7137&view=rev Author: mrpersonick Date: 2013-05-16 19:43:43 +0000 (Thu, 16 May 2013) Log Message: ----------- committing some new SPARQL services - sample and slice Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/search/FullTextIndex.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractQueryHint.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/CutoffLimitHint.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTCardinalityOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTRangeOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/AbstractJoinGroupOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/service/ServiceRegistry.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/BD.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/remote/BigdataSailRemoteRepositoryConnection.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AbstractServiceFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SampleServiceFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SliceServiceFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractStringQueryHint.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicBooleanQueryHint.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicDoubleQueryHint.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicIntQueryHint.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicLongQueryHint.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicStringQueryHint.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/search/FullTextIndex.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/search/FullTextIndex.java 2013-05-16 18:11:37 UTC (rev 7136) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/search/FullTextIndex.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -1235,10 +1235,18 @@ */ if (regex != null) { - final Pattern pattern = Pattern.compile(regex); + final Pattern pattern = Pattern.compile(regex);//, Pattern.CASE_INSENSITIVE); + if (log.isDebugEnabled()) { + log.debug("hits before regex: " + a.length); + } + a = applyRegex(a, pattern); + if (log.isDebugEnabled()) { + log.debug("hits after regex: " + a.length); + } + } if (a.length == 0) { @@ -1283,11 +1291,11 @@ } - if (log.isDebugEnabled()) { - log.debug("before min/max cosine/rank pruning:"); - for (Hit<V> h : a) - log.debug(h); - } +// if (log.isDebugEnabled()) { +// log.debug("before min/max cosine/rank pruning:"); +// for (Hit<V> h : a) +// log.debug(h); +// } /* * If maxCosine is specified, prune the hits that are above the max Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java 2013-05-16 18:11:37 UTC (rev 7136) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -18,9 +18,7 @@ import com.bigdata.rdf.sparql.ast.eval.AST2BOpJoins; import com.bigdata.rdf.sparql.ast.eval.AST2BOpUtility; import com.bigdata.rdf.sparql.ast.optimizers.ASTGraphGroupOptimizer; -import com.bigdata.rdf.sparql.ast.optimizers.ASTRangeConstraintOptimizer; import com.bigdata.rdf.sparql.ast.optimizers.ASTSimpleOptionalOptimizer; -import com.bigdata.rdf.sparql.ast.optimizers.ASTStaticJoinOptimizer.Annotations; import com.bigdata.rdf.spo.DistinctTermAdvancer; import com.bigdata.rdf.spo.ISPO; import com.bigdata.rdf.spo.SPOAccessPath; @@ -314,6 +312,16 @@ return (TermNode) get(3); } + + /** + * Strengthen return type. + */ + @Override + public TermNode get(final int i) { + + return (TermNode) super.get(i); + + } final public void setC(final TermNode c) { Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AbstractServiceFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AbstractServiceFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AbstractServiceFactory.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -0,0 +1,537 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Sep 9, 2011 + */ + +package com.bigdata.rdf.sparql.ast.eval; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.openrdf.model.Literal; +import org.openrdf.model.URI; +import org.openrdf.model.Value; + +import com.bigdata.bop.IVariable; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.sparql.ast.GraphPatternGroup; +import com.bigdata.rdf.sparql.ast.IGroupMemberNode; +import com.bigdata.rdf.sparql.ast.StatementPatternNode; +import com.bigdata.rdf.sparql.ast.TermNode; +import com.bigdata.rdf.sparql.ast.service.BigdataServiceCall; +import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams; +import com.bigdata.rdf.sparql.ast.service.ServiceFactory; +import com.bigdata.rdf.sparql.ast.service.ServiceNode; +import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.store.BD; + +/** + * An abstract ServiceFactory that deals with service parameters (magic + * predicates that connfigure the service). + */ +public abstract class AbstractServiceFactory implements ServiceFactory { + + private static final Logger log = Logger + .getLogger(AbstractServiceFactory.class); + + /** + * The service parameters. Can be multi-valued. Map from predicate to + * one or more TermNode values. + */ + public static class ServiceParams { + + /** + * The map of service params. + */ + final Map<URI, List<TermNode>> params; + + public ServiceParams() { + + this.params = new LinkedHashMap<URI, List<TermNode>>(); + + } + + /** + * Add. + */ + public void add(final URI param, final TermNode value) { + + if (!params.containsKey(param)) { + + params.put(param, new LinkedList<TermNode>()); + + } + + params.get(param).add(value); + + } + + /** + * Set (clear and add). + */ + public void set(final URI param, final TermNode value) { + + clear(param); + + add(param, value); + + } + + /** + * Clear. + */ + public void clear(final URI param) { + + params.remove(param); + + } + + /** + * Check for existence. + */ + public boolean contains(final URI param) { + + return params.containsKey(param); + + } + + /** + * Get a singleton value for the specified param. + */ + public TermNode get(final URI param, final TermNode defaultValue) { + + if (params.containsKey(param)) { + + final List<TermNode> values = params.get(param); + + if (values.size() > 1) { + + throw new RuntimeException("not a singleton param"); + + } + + return values.get(0); + + } + + return defaultValue; + + } + + /** + * Helper. + */ + public Boolean getAsBoolean(final URI param) { + + return getAsBoolean(param, null); + + } + + /** + * Helper. + */ + public Boolean getAsBoolean(final URI param, final Boolean defaultValue) { + + final Literal term = getAsLiteral(param, null); + + if (term != null) { + + return term.booleanValue(); + + } + + return defaultValue; + + } + + /** + * Helper. + */ + public Integer getAsInt(final URI param) { + + return getAsInt(param, null); + + } + + /** + * Helper. + */ + public Integer getAsInt(final URI param, final Integer defaultValue) { + + final Literal term = getAsLiteral(param, null); + + if (term != null) { + + return term.intValue(); + + } + + return defaultValue; + + } + + /** + * Helper. + */ + public Long getAsLong(final URI param) { + + return getAsLong(param, null); + + } + + /** + * Helper. + */ + public Long getAsLong(final URI param, final Long defaultValue) { + + final Literal term = getAsLiteral(param, null); + + if (term != null) { + + return term.longValue(); + + } + + return defaultValue; + + } + + /** + * Helper. + */ + public String getAsString(final URI param) { + + return getAsString(param, null); + + } + + /** + * Helper. + */ + public String getAsString(final URI param, final String defaultValue) { + + final Literal term = getAsLiteral(param, null); + + if (term != null) { + + return term.stringValue(); + + } + + return defaultValue; + + } + + /** + * Helper. + */ + public Literal getAsLiteral(final URI param) { + + return getAsLiteral(param, null); + + } + + /** + * Helper. + */ + public Literal getAsLiteral(final URI param, final Literal defaultValue) { + + final TermNode term = get(param, null); + + if (term != null) { + + if (term.isVariable()) { + + throw new IllegalArgumentException("not a constant"); + + } + + final Value v = term.getValue(); + + if (!(v instanceof Literal)) { + + throw new IllegalArgumentException("not a literal"); + + } + + return ((Literal) v); + + } + + return defaultValue; + + } + + /** + * Helper. + */ + public URI getAsURI(final URI param) { + + return getAsURI(param, null); + + } + + /** + * Helper. + */ + public URI getAsURI(final URI param, final URI defaultValue) { + + final TermNode term = get(param, null); + + if (term != null) { + + if (term.isVariable()) { + + throw new IllegalArgumentException("not a constant"); + + } + + final Value v = term.getValue(); + + if (!(v instanceof URI)) { + + throw new IllegalArgumentException("not a uri"); + + } + + return ((URI) v); + + } + + return defaultValue; + + } + + /** + * Helper. + */ + public IVariable<IV> getAsVar(final URI param) { + + return getAsVar(param, null); + + } + + /** + * Helper. + */ + public IVariable<IV> getAsVar(final URI param, final IVariable<IV> defaultValue) { + + final TermNode term = get(param, null); + + if (term != null) { + + if (!term.isVariable()) { + + throw new IllegalArgumentException("not a var"); + + } + + return (IVariable<IV>) term.getValueExpression(); + + } + + return defaultValue; + + } + + /** + * Helper. + */ + public List<TermNode> get(final URI param) { + + if (params.containsKey(param)) { + + return params.get(param); + + } + + return Collections.EMPTY_LIST; + + } + + /** + * Iterator. + */ + public Iterator<Map.Entry<URI, List<TermNode>>> iterator() { + + return params.entrySet().iterator(); + + } + + public String toString() { + + final StringBuilder sb = new StringBuilder(); + + sb.append("["); + + for (Map.Entry<URI, List<TermNode>> e : params.entrySet()) { + + final URI param = e.getKey(); + + final List<TermNode> terms = e.getValue(); + + sb.append(param).append(": "); + + if (terms.size() == 1) { + + sb.append(terms.get(0)); + + } else { + + sb.append("["); + for (TermNode t : terms) { + + sb.append(t).append(", "); + + } + sb.setLength(sb.length()-2); + sb.append("]"); + + } + + sb.append(", "); + + } + + if (sb.length() > 1) + sb.setLength(sb.length()-2); + sb.append("]"); + + return sb.toString(); + + } + + } + + public AbstractServiceFactory() { + } + + /** + * Create a {@link BigdataServiceCall}. Does the work of collecting + * the service parameter triples and then delegates to + * {@link #create(ServiceCallCreateParams, ServiceParams)}. + */ + public BigdataServiceCall create(final ServiceCallCreateParams params) { + + if (params == null) + throw new IllegalArgumentException(); + + final AbstractTripleStore store = params.getTripleStore(); + + if (store == null) + throw new IllegalArgumentException(); + + final ServiceNode serviceNode = params.getServiceNode(); + + if (serviceNode == null) + throw new IllegalArgumentException(); + + final ServiceParams serviceParams = gatherServiceParams(params); + + if (log.isDebugEnabled()) { + log.debug(serviceParams); + } + + return create(params, serviceParams); + + } + + /** + * Implemented by subclasses - verify the group and create the service call. + */ + public abstract BigdataServiceCall create( + final ServiceCallCreateParams params, + final ServiceParams serviceParams); + + /** + * Gather the service params (any statement patterns with the subject + * of {@link BD#SERVICE_PARAM}. + */ + protected ServiceParams gatherServiceParams( + final ServiceCallCreateParams createParams) { + + if (createParams == null) + throw new IllegalArgumentException(); + + final AbstractTripleStore store = createParams.getTripleStore(); + + if (store == null) + throw new IllegalArgumentException(); + + final ServiceNode serviceNode = createParams.getServiceNode(); + + if (serviceNode == null) + throw new IllegalArgumentException(); + + final GraphPatternGroup<IGroupMemberNode> group = + serviceNode.getGraphPattern(); + + if (group == null) + throw new IllegalArgumentException(); + + final ServiceParams serviceParams = new ServiceParams(); + + final Iterator<IGroupMemberNode> it = group.iterator(); + + while (it.hasNext()) { + + final IGroupMemberNode node = it.next(); + + if (node instanceof StatementPatternNode) { + + final StatementPatternNode sp = (StatementPatternNode) node; + + final TermNode s = sp.s(); + + if (s.isConstant() && BD.SERVICE_PARAM.equals(s.getValue())) { + + if (sp.p().isVariable()) { + + throw new RuntimeException( + "not a valid service param triple pattern, " + + "predicate must be constant: " + sp); + + } + + final URI param = (URI) sp.p().getValue(); + + serviceParams.add(param, sp.o()); + + } + + } + + } + + return serviceParams; + + } + +} Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AbstractServiceFactory.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SampleServiceFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SampleServiceFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SampleServiceFactory.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -0,0 +1,389 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Sep 9, 2011 + */ + +package com.bigdata.rdf.sparql.ast.eval; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.openrdf.model.Resource; +import org.openrdf.model.URI; +import org.openrdf.model.Value; +import org.openrdf.model.impl.URIImpl; + +import com.bigdata.bop.BOp; +import com.bigdata.bop.BOpContextBase; +import com.bigdata.bop.Constant; +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IPredicate; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.NV; +import com.bigdata.bop.ap.SampleIndex; +import com.bigdata.bop.bindingSet.EmptyBindingSet; +import com.bigdata.bop.bindingSet.ListBindingSet; +import com.bigdata.bop.fed.QueryEngineFactory; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.sparql.ast.GroupNodeBase; +import com.bigdata.rdf.sparql.ast.IGroupMemberNode; +import com.bigdata.rdf.sparql.ast.StatementPatternNode; +import com.bigdata.rdf.sparql.ast.TermNode; +import com.bigdata.rdf.sparql.ast.service.BigdataNativeServiceOptions; +import com.bigdata.rdf.sparql.ast.service.BigdataServiceCall; +import com.bigdata.rdf.sparql.ast.service.IServiceOptions; +import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams; +import com.bigdata.rdf.sparql.ast.service.ServiceFactory; +import com.bigdata.rdf.sparql.ast.service.ServiceNode; +import com.bigdata.rdf.spo.ISPO; +import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.store.BD; +import com.bigdata.relation.accesspath.EmptyCloseableIterator; +import com.bigdata.relation.accesspath.ThickCloseableIterator; +import com.bigdata.striterator.ICloseableIterator; + +/** + * A factory for a statement pattern sampling service. + * It accepts a group with a single triple pattern in it: + * + * service bd:sample { + * ?s rdf:type ex:Foo . + * + * # optional service params for the sample + * bd:serviceParam bd:sample.limit 200 . + * bd:serviceParam bd:sample.seed 0 . + * bd:serviceParam bd:sample.sampleType \"RANDOM\" . + * } + * + * The service params are optional and let you set parameters on the sample. + * + * This service will use the SampleIndex operator to take a random sample + * of tuples from an access path. + * + * @see {@link SampleIndex} + */ +public class SampleServiceFactory extends AbstractServiceFactory + implements ServiceFactory { + + private static final Logger log = Logger + .getLogger(SampleServiceFactory.class); + + /** + * The URI service key. + */ + public static final URI SERVICE_KEY = new URIImpl(BD.NAMESPACE+"sample"); + + /** + * The service params for this service. + */ + public static interface SampleParams { + + /** + * The limit on the sample. + */ + URI LIMIT = new URIImpl(SERVICE_KEY.stringValue() + ".limit"); + + /** + * Default = 100. + */ + int DEFAULT_LIMIT = SampleIndex.Annotations.DEFAULT_LIMIT; + + /** + * The seed on the sample. + */ + URI SEED = new URIImpl(SERVICE_KEY.stringValue() + ".seed"); + + /** + * Default = 0. + */ + long DEFAULT_SEED = SampleIndex.Annotations.DEFAULT_SEED; + + /** + * The sample type. + */ + URI SAMPLE_TYPE = new URIImpl(SERVICE_KEY.stringValue() + ".sampleType"); + + /** + * Default = "RANDOM". + */ + String DEFAULT_SAMPLE_TYPE = SampleIndex.Annotations.DEFAULT_SAMPLE_TYPE; + + } + + + /* + * Note: This could extend the base class to allow for search service + * configuration options. + */ + private final BigdataNativeServiceOptions serviceOptions; + + public SampleServiceFactory() { + + serviceOptions = new BigdataNativeServiceOptions(); + serviceOptions.setRunFirst(true); + + } + + @Override + public BigdataNativeServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + public BigdataServiceCall create( + final ServiceCallCreateParams params, + final ServiceParams serviceParams) { + + final AbstractTripleStore store = params.getTripleStore(); + + final ServiceNode serviceNode = params.getServiceNode(); + + /* + * Validate the predicates for a given service call. + */ + final StatementPatternNode sp = verifyGraphPattern( + store, serviceNode.getGraphPattern(), serviceParams); + + /* + * Create and return the ServiceCall object which will execute this + * query. + */ + return new SampleCall(store, sp, getServiceOptions(), serviceParams); + + } + + /** + * Verify that there is only a single statement pattern node and that the + * service parameters are valid. + */ + private StatementPatternNode verifyGraphPattern( + final AbstractTripleStore database, + final GroupNodeBase<IGroupMemberNode> group, + final ServiceParams serviceParams) { + + final Iterator<Map.Entry<URI, List<TermNode>>> it = serviceParams.iterator(); + + while (it.hasNext()) { + + final URI param = it.next().getKey(); + + if (SampleParams.LIMIT.equals(param)) { + + if (serviceParams.getAsInt(param, null) == null) { + throw new RuntimeException("must provide a value for: " + param); + } + + } else if (SampleParams.SEED.equals(param)) { + + if (serviceParams.getAsLong(param, null) == null) { + throw new RuntimeException("must provide a value for: " + param); + } + + } else if (SampleParams.SAMPLE_TYPE.equals(param)) { + + if (serviceParams.getAsString(param, null) == null) { + throw new RuntimeException("must provide a value for: " + param); + } + + } else { + + throw new RuntimeException("unrecognized param: " + param); + + } + + } + + StatementPatternNode sp = null; + + for (IGroupMemberNode node : group) { + + if (!(node instanceof StatementPatternNode)) { + + throw new RuntimeException("only statement patterns allowed"); + + } + + final StatementPatternNode tmp = (StatementPatternNode) node; + + if (tmp.s().isConstant() && BD.SERVICE_PARAM.equals(tmp.s().getValue())) { + + continue; + + } + + if (sp != null) { + + throw new RuntimeException("group must contain a single statement pattern"); + + } + + sp = tmp; + + } + + return sp; + + } + + /** + * + * Note: This has the {@link AbstractTripleStore} reference attached. This + * is not a {@link Serializable} object. It MUST run on the query + * controller. + */ + private static class SampleCall implements BigdataServiceCall { + + private final AbstractTripleStore db; + private final StatementPatternNode sp; + private final IServiceOptions serviceOptions; + private final ServiceParams serviceParams; + + public SampleCall( + final AbstractTripleStore db, + final StatementPatternNode sp, + final IServiceOptions serviceOptions, + final ServiceParams serviceParams) { + + if(db == null) + throw new IllegalArgumentException(); + + if(sp == null) + throw new IllegalArgumentException(); + + if(serviceOptions == null) + throw new IllegalArgumentException(); + + if(serviceParams == null) + throw new IllegalArgumentException(); + + this.db = db; + this.sp = sp; + this.serviceOptions = serviceOptions; + this.serviceParams = serviceParams; + + } + + /** + * Run a sample index op over the access path. + */ + @Override + public ICloseableIterator<IBindingSet> call( + final IBindingSet[] bc) { + + if (log.isInfoEnabled()) { + log.info(bc.length); + log.info(Arrays.toString(bc)); + log.info(serviceParams); + } + + if (bc != null && bc.length > 0 && !bc[0].equals(EmptyBindingSet.INSTANCE)) { + throw new RuntimeException("cannot run with incoming bindings"); + } + + @SuppressWarnings("unchecked") + IPredicate<ISPO> pred = (IPredicate<ISPO>) + db.getPredicate( + sp.s() != null && sp.s().isConstant() ? (Resource) sp.s().getValue() : null, + sp.p() != null && sp.p().isConstant() ? (URI) sp.p().getValue() : null, + sp.o() != null && sp.o().isConstant() ? (Value) sp.o().getValue() : null, + sp.c() != null && sp.c().isConstant() ? (Resource) sp.c().getValue() : null + ); + + if (pred == null) { + + return new EmptyCloseableIterator<IBindingSet>(); + + } + + pred = (IPredicate<ISPO>) pred.setProperty(IPredicate.Annotations.TIMESTAMP, + db.getSPORelation().getTimestamp()); + + final int limit = serviceParams.getAsInt( + SampleParams.LIMIT, SampleParams.DEFAULT_LIMIT); + + final long seed = serviceParams.getAsLong( + SampleParams.SEED, SampleParams.DEFAULT_SEED); + + final String type = serviceParams.getAsString( + SampleParams.SAMPLE_TYPE, SampleParams.DEFAULT_SAMPLE_TYPE); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + final SampleIndex<?> sampleOp = new SampleIndex(new BOp[] {}, // + NV.asMap(// + new NV(SampleIndex.Annotations.PREDICATE, pred),// + new NV(SampleIndex.Annotations.LIMIT, limit),// + new NV(SampleIndex.Annotations.SEED, seed),// + new NV(SampleIndex.Annotations.SAMPLE_TYPE, type) + )); + + final BOpContextBase context = new BOpContextBase( + QueryEngineFactory.getQueryController( + db.getIndexManager())); + + final ISPO[] elements = (ISPO[]) sampleOp.eval(context); + + final IBindingSet[] bSets = new IBindingSet[elements.length]; + + for (int i = 0; i < elements.length; i++) { + + bSets[i] = new ListBindingSet(); + + if (sp.s() != null && sp.s().isVariable()) + bSets[i].set((IVariable<IV>) sp.s().getValueExpression(), + new Constant<IV>(elements[i].s())); + + if (sp.p() != null && sp.p().isVariable()) + bSets[i].set((IVariable<IV>) sp.p().getValueExpression(), + new Constant<IV>(elements[i].p())); + + if (sp.o() != null && sp.o().isVariable()) + bSets[i].set((IVariable<IV>) sp.o().getValueExpression(), + new Constant<IV>(elements[i].o())); + + if (sp.c() != null && sp.c().isVariable()) + bSets[i].set((IVariable<IV>) sp.c().getValueExpression(), + new Constant<IV>(elements[i].c())); + + } + + return new ThickCloseableIterator<IBindingSet>(bSets, bSets.length); + + } + + @Override + public IServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + } + +} Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SampleServiceFactory.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SliceServiceFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SliceServiceFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SliceServiceFactory.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -0,0 +1,683 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Sep 9, 2011 + */ + +package com.bigdata.rdf.sparql.ast.eval; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.openrdf.model.URI; +import org.openrdf.model.impl.URIImpl; + +import com.bigdata.bop.Constant; +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IConstant; +import com.bigdata.bop.IPredicate; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.bindingSet.EmptyBindingSet; +import com.bigdata.bop.bindingSet.ListBindingSet; +import com.bigdata.btree.BTree; +import com.bigdata.btree.BytesUtil; +import com.bigdata.btree.IRangeQuery; +import com.bigdata.btree.ITupleIterator; +import com.bigdata.btree.keys.KeyBuilder; +import com.bigdata.btree.keys.SuccessorUtil; +import com.bigdata.cache.ConcurrentWeakValueCacheWithTimeout; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.internal.constraints.RangeBOp; +import com.bigdata.rdf.internal.impl.literal.XSDNumericIV; +import com.bigdata.rdf.sparql.ast.GroupNodeBase; +import com.bigdata.rdf.sparql.ast.IGroupMemberNode; +import com.bigdata.rdf.sparql.ast.StatementPatternNode; +import com.bigdata.rdf.sparql.ast.TermNode; +import com.bigdata.rdf.sparql.ast.service.BigdataNativeServiceOptions; +import com.bigdata.rdf.sparql.ast.service.BigdataServiceCall; +import com.bigdata.rdf.sparql.ast.service.IServiceOptions; +import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams; +import com.bigdata.rdf.sparql.ast.service.ServiceFactory; +import com.bigdata.rdf.sparql.ast.service.ServiceNode; +import com.bigdata.rdf.spo.DistinctMultiTermAdvancer; +import com.bigdata.rdf.spo.ISPO; +import com.bigdata.rdf.spo.SPO; +import com.bigdata.rdf.spo.SPOKeyOrder; +import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.store.BD; +import com.bigdata.relation.accesspath.EmptyCloseableIterator; +import com.bigdata.relation.accesspath.ThickCloseableIterator; +import com.bigdata.striterator.ICloseableIterator; + +/** + * A factory for a statement pattern slicing service. + * It accepts a group with a single triple pattern in it: + * + * service bd:slice { + * ?s rdf:type ex:Foo . + * + * # required service params for the sample + * # either offset+limit + * bd:serviceParam bd:slice.offset 0 . + * bd:serviceParam bd:slice.limit 2000 . + * # or range + * bd:serviceParam bd:slice.range ?range + * } + * + * The service params are required and set the slicing parameters. You can + * either request a slice or request a range count depending on the params. + * The range count is useful when dealing with a "rangeSafe" predicate with + * a range filter. + * + * @see RangeBOp + */ +public class SliceServiceFactory extends AbstractServiceFactory + implements ServiceFactory { + + private static final Logger log = Logger + .getLogger(SliceServiceFactory.class); + + /** + * The URI service key. + */ + public static final URI SERVICE_KEY = new URIImpl(BD.NAMESPACE+"slice"); + + /** + * The service params for this service. + */ + public static interface SliceParams { + + /** + * The offset into the range. + */ + URI OFFSET = new URIImpl(SERVICE_KEY.stringValue() + ".offset"); + + /** + * Default = 0. + */ + long DEFAULT_OFFSET = 0; + + /** + * The limit on the slice. + */ + URI LIMIT = new URIImpl(SERVICE_KEY.stringValue() + ".limit"); + + /** + * Default = 1000. + */ + int DEFAULT_LIMIT = 1000; + + /** + * A range request - object will be the variable to bind to the range + * count. + */ + URI RANGE = new URIImpl(SERVICE_KEY.stringValue() + ".range"); + + } + + /** + * Keep a timeout cache of start and end indices for a give predicate. + * Typically these slice calls happen multiple times in a row in a very + * short time period, so it's best to not have to go back to the index + * every time for this information. + */ + private static final ConcurrentWeakValueCacheWithTimeout<IPredicate<ISPO>, CacheHit> cache; + + private static final class CacheHit { + + final long startIndex, endIndex; + + public CacheHit(final long startIndex, final long endIndex) { + this.startIndex = startIndex; + this.endIndex = endIndex; + } + + } + + static { + + cache = new ConcurrentWeakValueCacheWithTimeout<IPredicate<ISPO>, CacheHit>( + 100, TimeUnit.MINUTES.toMillis(1)); + + } + + /* + * Note: This could extend the base class to allow for search service + * configuration options. + */ + private final BigdataNativeServiceOptions serviceOptions; + + public SliceServiceFactory() { + + serviceOptions = new BigdataNativeServiceOptions(); +// serviceOptions.setRunFirst(true); + + } + + @Override + public BigdataNativeServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + @Override + public BigdataServiceCall create(final ServiceCallCreateParams params, + final ServiceParams serviceParams) { + + final AbstractTripleStore store = params.getTripleStore(); + + final ServiceNode serviceNode = params.getServiceNode(); + + /* + * Validate the predicates for a given service call. + */ + final StatementPatternNode sp = verifyGraphPattern( + store, serviceNode.getGraphPattern(), serviceParams); + + /* + * Create and return the ServiceCall object which will execute this + * query. + */ + return new SliceCall(store, sp, serviceOptions, serviceParams); + + } + + /** + * Verify that there is only a single statement pattern node and that the + * service parameters are valid. + */ + private StatementPatternNode verifyGraphPattern( + final AbstractTripleStore database, + final GroupNodeBase<IGroupMemberNode> group, + final ServiceParams params) { + + final Iterator<Map.Entry<URI, List<TermNode>>> it = params.iterator(); + + while (it.hasNext()) { + + final URI param = it.next().getKey(); + + if (SliceParams.OFFSET.equals(param)) { + + if (params.getAsLong(param, null) == null) { + throw new RuntimeException("must provide a value for: " + param); + } + + } else if (SliceParams.LIMIT.equals(param)) { + + if (params.getAsInt(param, null) == null) { + throw new RuntimeException("must provide a value for: " + param); + } + + } else if (SliceParams.RANGE.equals(param)) { + + if (params.getAsVar(param, null) == null) { + throw new RuntimeException("must provide a variable for: " + param); + } + + } else { + + throw new RuntimeException("unrecognized param: " + param); + + } + + } + + StatementPatternNode sp = null; + + for (IGroupMemberNode node : group) { + + if (!(node instanceof StatementPatternNode)) { + + throw new RuntimeException("only statement patterns allowed"); + + } + + final StatementPatternNode tmp = (StatementPatternNode) node; + + if (tmp.s().isConstant() && BD.SERVICE_PARAM.equals(tmp.s().getValue())) { + + continue; + + } + + if (sp != null) { + + throw new RuntimeException("group must contain a single statement pattern"); + + } + + sp = tmp; + + } + + return sp; + + } + + /** + * + * Note: This has the {@link AbstractTripleStore} reference attached. This + * is not a {@link Serializable} object. It MUST run on the query + * controller. + */ + private static class SliceCall implements BigdataServiceCall { + + private final AbstractTripleStore db; + private final StatementPatternNode sp; + private final IServiceOptions serviceOptions; + private final ServiceParams serviceParams; + + public SliceCall( + final AbstractTripleStore db, + final StatementPatternNode sp, + final IServiceOptions serviceOptions, + final ServiceParams serviceParams) { + + if(db == null) + throw new IllegalArgumentException(); + + if(sp == null) + throw new IllegalArgumentException(); + + if(serviceOptions == null) + throw new IllegalArgumentException(); + + if(serviceParams == null) + throw new IllegalArgumentException(); + + this.db = db; + this.sp = sp; + this.serviceOptions = serviceOptions; + this.serviceParams = serviceParams; + + } + + /** + * Run a slice over an access path. Currently only implemented to + * work with zero or one incoming bindings, and all variables in the + * incoming binding must be in use in the statement pattern. + */ + @Override + public ICloseableIterator<IBindingSet> call( + final IBindingSet[] bc) { + + if (log.isInfoEnabled()) { + log.info(bc.length); + log.info(Arrays.toString(bc)); + } + + if (bc != null && bc.length > 1) { + throw new RuntimeException("cannot run with multiple incoming bindings"); + } + + /* + * Keep a map of variables in the statement pattern to the position + * in which they appear in the statement pattern. + */ + final Map<IVariable, Integer> vars = new LinkedHashMap<IVariable, Integer>(); + + for (int i = 0; i < sp.arity(); i++) { + + final TermNode term = sp.get(i); + + if (term == null) + continue; + + if (term.isVariable()) { + + final IVariable v = (IVariable) term.getValueExpression(); + + if (log.isTraceEnabled()) { + log.trace("variable: " + v + " at position: " + i); + } + + vars.put(v, i); + + } + + } + + final IBindingSet bs; + if (bc.length == 1 && !bc[0].equals(EmptyBindingSet.INSTANCE)) { + + bs = bc[0]; + + } else { + + bs = null; + + } + + if (bs != null) { + + @SuppressWarnings("rawtypes") + final Iterator<IVariable> it = bs.vars(); + + while (it.hasNext()) { + + @SuppressWarnings("rawtypes") + final IVariable v = it.next(); + + if (!vars.containsKey(v)) { + + throw new RuntimeException("unrecognized variable in incoming binding"); + + } + + if (bs.isBound(v)) { + + // no longer a variable + vars.remove(v); + + } + + } + + } + + // Handle a range. + final RangeBOp rangeBOp = sp.getRange() != null ? sp.getRange().getRangeBOp() : null; + + // Create the predicate. + @SuppressWarnings("unchecked") + final IPredicate<ISPO> pred = (IPredicate<ISPO>) + db.getSPORelation().getPredicate( + getTerm(sp, bs, 0), + getTerm(sp, bs, 1), + getTerm(sp, bs, 2), + getTerm(sp, bs, 3), + null, + rangeBOp + ); + + if (pred == null) { + + return new EmptyCloseableIterator<IBindingSet>(); + + } + + // Get the right key order for the predicate. + final SPOKeyOrder keyOrder = db.getSPORelation().getKeyOrder(pred); + + // Grab the corresponding index. + final BTree ndx = (BTree) db.getSPORelation().getIndex(keyOrder); + + /* + * Inspect the cache and/or the index for the starting and ending + * tuple index for this access path. + */ + final long startIndex, endIndex; + + /* + * Avoid an index read if possible. + */ + final CacheHit hit = cache.get(pred); + + if (hit == null) { + + if (log.isTraceEnabled()) { + log.trace("going to index for range"); + } + + final byte[] startKey = keyOrder.getFromKey(KeyBuilder.newInstance(), pred); + + startIndex = indexOf(ndx, startKey); + + final byte[] endKey = SuccessorUtil.successor(startKey.clone()); + + endIndex = indexOf(ndx, endKey); + + cache.put(pred, new CacheHit(startIndex, endIndex)); + + } else { + + if (log.isTraceEnabled()) { + log.trace("cache hit"); + } + + startIndex = hit.startIndex; + + endIndex = hit.endIndex; + + } + + final long range = endIndex - startIndex + 1; + + if (log.isTraceEnabled()) { + log.trace("range: " + range); + } + + /* + * Caller is asking for a range count only. + */ + if (serviceParams.contains(SliceParams.RANGE)) { + + final IVariable<IV> v = serviceParams.getAsVar(SliceParams.RANGE); + + final IBindingSet[] bSets = new IBindingSet[1]; + + bSets[0] = bs != null ? bs.clone() : new ListBindingSet(); + + bSets[0].set(v, new Constant<IV>(new XSDNumericIV(range))); + + return new ThickCloseableIterator<IBindingSet>(bSets, 1); + + } + + final long offset = serviceParams.getAsLong( + SliceParams.OFFSET, SliceParams.DEFAULT_OFFSET); + + if (offset < 0) { + + throw new RuntimeException("illegal negative offset"); + + } + + if (offset > range) { + + throw new RuntimeException("offset is out of range"); + + } + + final int limit = serviceParams.getAsInt( + SliceParams.LIMIT, SliceParams.DEFAULT_LIMIT); + + if (log.isTraceEnabled()) { + log.trace("offset: " + offset); + log.trace("limit: " + limit); + } + + /* + * Reading from the startIndex plus the offset. + */ + final long fromIndex = Math.max(startIndex, startIndex + offset); + + /* + * Reading to the offset plus the limit (minus 1), or the end + * index, whichever is smaller. + */ + final long toIndex = Math.min(startIndex + offset + limit - 1, + endIndex); + + if (fromIndex > toIndex) { + + throw new RuntimeException("fromIndex > toIndex"); + + } + + final byte[] fromKey = ndx.keyAt(fromIndex); + + final byte[] toKey = SuccessorUtil.successor(ndx.keyAt(toIndex)); + + final int arity = pred.arity(); + + final int numBoundEntries = pred.arity() - vars.size(); + + if (log.isTraceEnabled()) { + log.trace("fromIndex: " + fromIndex); + log.trace("toIndex: " + toIndex); + log.trace("fromKey: " + BytesUtil.toString(fromKey)); + log.trace("toKey: " + BytesUtil.toString(toKey)); + log.trace("arity: " + arity); + log.trace("#boundEntries: " + numBoundEntries); + log.trace(keyOrder); + } + + /* + * Use a multi-term advancer to skip the bound entries and just + * get to the variables. + */ + final DistinctMultiTermAdvancer advancer = //null; + new DistinctMultiTermAdvancer( + arity, //arity - 3 or 4 + numBoundEntries // #boundEntries - anything not a var and not bound by incoming bindings + ); + + final ITupleIterator it = ndx.rangeIterator(fromKey, toKey, + 0/* capacity */, IRangeQuery.KEYS | IRangeQuery.CURSOR, advancer); + + /* + * Max # of tuples read will be limit. + */ + final IBindingSet[] bSets = new IBindingSet[limit]; + + int i = 0; + + while (it.hasNext()) { + + final byte[] key = it.next().getKey(); + + final SPO spo = keyOrder.decodeKey(key); + + bSets[i] = bs != null ? bs.clone() : new ListBindingSet(); + + for (IVariable v : vars.keySet()) { + + final int pos = vars.get(v); + + bSets[i].set(v, new Constant<IV>(spo.get(pos))); + + } + +// if (log.isTraceEnabled()) { +// log.trace("next bs: " + bSets[i]); +// } + + i++; + + } + + if (log.isTraceEnabled()) { + log.trace("done iterating " + i + " results."); + } + + return new ThickCloseableIterator<IBindingSet>(bSets, i); + + } + + /** + * Get the IV in the statement pattern at the specified position, or + * get the value from the binding set for the variable at that position. + * Return null if not bound in either place. + */ + private IV getTerm(final StatementPatternNode sp, final IBindingSet bs, final int pos) { + + final TermNode t = sp.get(pos); + + if (t == null) + return null; + + if (t.isConstant()) { + + return ((IConstant<IV>) t.getValueExpression()).get(); + + } else { + + final IVariable<IV> v = (IVariable<IV>) t.getValueExpression(); + + if (bs != null && bs.isBound(v)) { + + return ((IConstant<IV>) bs.get(v)).get(); + + } else { + + return null; + + } + + } + + } + + /** + * Use the index to find the index of the tuple for the specified key + * (or the index of the next real tuple after the specified key). + */ + private long indexOf(final BTree ndx, final byte[] key) { + + if (log.isTraceEnabled()) { + log.trace(BytesUtil.toString(key)); + } + + final long indexOfKey = ndx.indexOf(key); + + if (log.isTraceEnabled()) { + log.trace("result of indexOf(key): " + indexOfKey); + } + + final long index; + if (indexOfKey >= 0) { + // it's a real key + index = indexOfKey; + } else { + // not a real key + index = -(indexOfKey+1); + } + + if (log.isTraceEnabled()) { + log.trace("index: " + index); + } + + return index; + + } + + @Override + public IServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + } + +} Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SliceServiceFactory.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractQueryHint.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractQueryHint.java 2013-05-16 18:11:37 UTC (rev 7136) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractQueryHint.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -36,7 +36,7 @@ /** * Base class for query hints. */ -abstract class AbstractQueryHint<T> implements IQueryHint<T> { +public abstract class AbstractQueryHint<T> implements IQueryHint<T> { private final String name; Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractStringQueryHint.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractStringQueryHint.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractStringQueryHint.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -0,0 +1,48 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Nov 27, 2011 + */ + +package com.bigdata.rdf.sparql.ast.hints; + +/** + * Base class for {@link String} query hints. + */ +public abstract class AbstractStringQueryHint extends AbstractQueryHint<String> { + + protected AbstractStringQueryHint(final String name, final String defaultValue) { + + super(name, defaultValue); + + } + + @Override + public String validate(final String value) { + + return value; + + } + +} \ No newline at end of file Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/AbstractStringQueryHint.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicBooleanQueryHint.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicBooleanQueryHint.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicBooleanQueryHint.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -0,0 +1,50 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Nov 27, 2011 + */ + +package com.bigdata.rdf.sparql.ast.hints; + +import com.bigdata.rdf.sparql.ast.ASTBase; +import com.bigdata.rdf.sparql.ast.eval.AST2BOpContext; + +/** + * Basic boolean query hint. + */ +public class BasicBooleanQueryHint extends AbstractBooleanQueryHint { + + public BasicBooleanQueryHint(final String name, final Boolean defaultValue) { + super(name, defaultValue); + } + + @Override + public void handle(final AST2BOpContext context, + final QueryHintScope scope, final ASTBase op, final Boolean value) { + + _setQueryHint(context, scope, op, getName(), value); + + } + +} \ No newline at end of file Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicBooleanQueryHint.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicDoubleQueryHint.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicDoubleQueryHint.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicDoubleQueryHint.java 2013-05-16 19:43:43 UTC (rev 7137) @@ -0,0 +1,50 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Nov 27, 2011 + */ + +package com.bigdata.rdf.sparql.ast.hints; + +import com.bigdata.rdf.sparql.ast.ASTBase; +import com.bigdata.rdf.sparql.ast.eval.AST2BOpContext; + +/** + * Basic double query hint. + */ +public class BasicDoubleQueryHint extends AbstractDoubleQueryHint { + + public BasicDoubleQueryHint(final String name, final Double defaultValue) { + super(name, defaultValue); + } + + @Override + public void handle(final AST2BOpContext context, + final QueryHintScope scope, final ASTBase op, final Double value) { + + _setQueryHint(context, scope, op, getName(), value); + + } + +} \ No newline at end of file Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicDoubleQueryHint.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/hints/BasicIntQueryHint.java =================================================================== --- bra... [truncated message content] |
From: <tho...@us...> - 2013-05-16 18:11:43
|
Revision: 7136 http://bigdata.svn.sourceforge.net/bigdata/?rev=7136&view=rev Author: thompsonbry Date: 2013-05-16 18:11:37 +0000 (Thu, 16 May 2013) Log Message: ----------- Changed nxparser dependency to 1.2.3 to close out [1]. [1] https://sourceforge.net/apps/trac/bigdata/ticket/590 (nxparser fails with uppercase language tag) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/build.properties branches/BIGDATA_RELEASE_1_2_0/pom.xml Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-1.2.3.jar Removed Paths: ------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-1.2.2.jar Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-1.2.2.jar =================================================================== (Binary files differ) Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-1.2.3.jar =================================================================== (Binary files differ) Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-1.2.3.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: branches/BIGDATA_RELEASE_1_2_0/build.properties =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/build.properties 2013-05-16 17:45:11 UTC (rev 7135) +++ branches/BIGDATA_RELEASE_1_2_0/build.properties 2013-05-16 18:11:37 UTC (rev 7136) @@ -59,7 +59,7 @@ apache.httpclient_cache.version=4.1.3 apache.httpcore.version=4.1.4 apache.httpmime.version=4.1.3 -nxparser.version=1.2.2 +nxparser.version=1.2.3 colt.version=1.2.0 highscalelib.version=1.1.2 log4j.version=1.2.17 Modified: branches/BIGDATA_RELEASE_1_2_0/pom.xml =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/pom.xml 2013-05-16 17:45:11 UTC (rev 7135) +++ branches/BIGDATA_RELEASE_1_2_0/pom.xml 2013-05-16 18:11:37 UTC (rev 7136) @@ -84,7 +84,7 @@ <apache.httpclient_cache.version>4.1.3</apache.httpclient_cache.version> <apache.httpcore.version>4.1.4</apache.httpcore.version> <apache.httpmime.version>4.1.3</apache.httpmime.version> - <nxparser.version>1.2.2</nxparser.version> + <nxparser.version>1.2.3</nxparser.version> <colt.version>1.2.0</colt.version> <highscalelib.version>1.1.2</highscalelib.version> <log4j.version>1.2.17</log4j.version> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-16 17:45:18
|
Revision: 7135 http://bigdata.svn.sourceforge.net/bigdata/?rev=7135&view=rev Author: thompsonbry Date: 2013-05-16 17:45:11 +0000 (Thu, 16 May 2013) Log Message: ----------- Fix for 2 unit tests that failed when the quorum was null. Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-16 17:09:27 UTC (rev 7134) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-16 17:45:11 UTC (rev 7135) @@ -2910,7 +2910,8 @@ .handleCommit(commitTime); // Local HA service implementation (non-Remote). - final QuorumService<HAGlue> quorumService = quorum.getClient(); + final QuorumService<HAGlue> quorumService = quorum == null ? null + : quorum.getClient(); // The services joined with the met quorum, in their join order. final UUID[] joinedServiceIds; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-16 17:09:34
|
Revision: 7134 http://bigdata.svn.sourceforge.net/bigdata/?rev=7134&view=rev Author: thompsonbry Date: 2013-05-16 17:09:27 +0000 (Thu, 16 May 2013) Log Message: ----------- Moved up the collection of the joined versus unjoined services in commitNow() to before we execute the releaseTime consensus protocol and passed the definition of the joined services into the releaseTime consensus protocol so it will have a consistent definition of the services that it is talking to and that the prepare2Phase and commit2Phase / abort2Phase will also talk to. This fixes a problem where a service joins after the releaseTime consensus protocol but before the prepare2Phase, Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractHATransactionService.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-16 14:26:59 UTC (rev 7133) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-16 17:09:27 UTC (rev 7134) @@ -2909,9 +2909,31 @@ rootAddrs[PREV_ROOTBLOCK] = this.m_rootBlockCommitter .handleCommit(commitTime); + // Local HA service implementation (non-Remote). + final QuorumService<HAGlue> quorumService = quorum.getClient(); + + // The services joined with the met quorum, in their join order. + final UUID[] joinedServiceIds; + + // The services in the write pipeline (in any order). + final Set<UUID> nonJoinedPipelineServiceIds; + if ((_bufferStrategy instanceof IHABufferStrategy) && quorum != null && quorum.isHighlyAvailable()) { + // The services joined with the met quorum, in their join order. + joinedServiceIds = quorum.getJoined(); + + // The services in the write pipeline (in any order). + nonJoinedPipelineServiceIds = new LinkedHashSet<UUID>( + Arrays.asList(getQuorum().getPipeline())); + + // Remove all services that are joined from this collection. + for(UUID joinedServiceId : joinedServiceIds) { + + nonJoinedPipelineServiceIds.remove(joinedServiceId); + + } try { /** * CRITICAL SECTION. We need obtain a distributed consensus @@ -2937,7 +2959,7 @@ ((AbstractHATransactionService) getLocalTransactionManager() .getTransactionService()) - .updateReleaseTimeConsensus( + .updateReleaseTimeConsensus(joinedServiceIds, getHAReleaseTimeConsensusTimeout(), TimeUnit.MILLISECONDS); @@ -2950,6 +2972,11 @@ } + } else { + + joinedServiceIds = null; + nonJoinedPipelineServiceIds = null; + } /* @@ -3169,23 +3196,6 @@ * to get that metadata from zookeeper out of the Quorum.. */ - // Local HA service implementation (non-Remote). - final QuorumService<HAGlue> quorumService = quorum.getClient(); - - // The services joined with the met quorum, in their join order. - final UUID[] joinedServiceIds = getQuorum().getJoined(); - - // The services in the write pipeline (in any order). - final Set<UUID> nonJoinedPipelineServiceIds = new LinkedHashSet<UUID>( - Arrays.asList(getQuorum().getPipeline())); - - // Remove all services that are joined from this collection. - for(UUID joinedServiceId : joinedServiceIds) { - - nonJoinedPipelineServiceIds.remove(joinedServiceId); - - } - boolean didVoteYes = false; try { Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-16 14:26:59 UTC (rev 7133) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-16 17:09:27 UTC (rev 7134) @@ -417,7 +417,8 @@ // // } - public BarrierState() { + /** The services joined with the met quorum, in their join order. */ + public BarrierState(final UUID[] joinedServiceIds) { token = getQuorum().token(); @@ -426,9 +427,8 @@ // Local HA service implementation (non-Remote). quorumService = getQuorum().getClient(); - // The services joined with the met quorum, in their join order. - joinedServiceIds = getQuorum().getJoined(); - + this.joinedServiceIds = joinedServiceIds; + leadersValue = ((InnerJournalTransactionService) getTransactionService()) .newHANotifyReleaseTimeRequest(quorumService.getServiceId()); @@ -1053,9 +1053,9 @@ */ // Note: Executed on the leader. @Override - public void updateReleaseTimeConsensus(final long timeout, - final TimeUnit units) throws IOException, InterruptedException, - TimeoutException, BrokenBarrierException { + public void updateReleaseTimeConsensus(final UUID[] joinedServiceIds, + final long timeout, final TimeUnit units) throws IOException, + InterruptedException, TimeoutException, BrokenBarrierException { final long begin = System.nanoTime(); final long nanos = units.toNanos(timeout); @@ -1072,7 +1072,7 @@ getQuorum().assertLeader(token); if (!barrierRef.compareAndSet(null/* expectedValue */, - barrierState = new BarrierState()/* newValue */)) { + barrierState = new BarrierState(joinedServiceIds)/* newValue */)) { throw new IllegalStateException(); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractHATransactionService.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractHATransactionService.java 2013-05-16 14:26:59 UTC (rev 7133) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractHATransactionService.java 2013-05-16 17:09:27 UTC (rev 7134) @@ -29,12 +29,14 @@ import java.io.IOException; import java.util.Properties; +import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import com.bigdata.ha.HATXSGlue; import com.bigdata.ha.msg.IHAGatherReleaseTimeRequest; +import com.bigdata.journal.AbstractJournal; import com.bigdata.journal.ITransactionService; /** @@ -69,12 +71,16 @@ * Coordinate the update of the <i>releaseTime</i> on each service that is * joined with the met quorum. * + * @param joinedServiceIds + * The services that are joined with the met quorum as of an + * atomic decision point in {@link AbstractJournal#commitNow()}. * @param timeout * The timeout for the release time consensus protocol. * @param units * The units for that timeout. */ - abstract public void updateReleaseTimeConsensus(final long timeout, + abstract public void updateReleaseTimeConsensus( + final UUID[] joinedServiceIds, final long timeout, final TimeUnit units) throws IOException, TimeoutException, InterruptedException, Exception; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-16 14:27:07
|
Revision: 7133 http://bigdata.svn.sourceforge.net/bigdata/?rev=7133&view=rev Author: thompsonbry Date: 2013-05-16 14:26:59 +0000 (Thu, 16 May 2013) Log Message: ----------- Added the ability to demand a local service REBUILD (disaster recover). This is available on HAGlue#rebuildFromLeader(). There is also an (unpublished, unsupported) ability to do this using /status?rebuild. @see https://sourceforge.net/apps/trac/bigdata/ticket/530 (Journal HA) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/HAGlue.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/HAStatusServletUtil.java Added Paths: ----------- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/HARemoteRebuildRequest.java branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/IHARemoteRebuildRequest.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/HAGlue.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/HAGlue.java 2013-05-16 12:35:45 UTC (rev 7132) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/HAGlue.java 2013-05-16 14:26:59 UTC (rev 7133) @@ -37,6 +37,7 @@ import com.bigdata.ha.msg.IHAGlobalWriteLockRequest; import com.bigdata.ha.msg.IHALogDigestRequest; import com.bigdata.ha.msg.IHALogDigestResponse; +import com.bigdata.ha.msg.IHARemoteRebuildRequest; import com.bigdata.ha.msg.IHARootBlockRequest; import com.bigdata.ha.msg.IHARootBlockResponse; import com.bigdata.ha.msg.IHASnapshotDigestRequest; @@ -45,6 +46,7 @@ import com.bigdata.ha.msg.IHASnapshotResponse; import com.bigdata.journal.AbstractJournal; import com.bigdata.journal.Journal; +import com.bigdata.journal.jini.ha.HAJournalServer; import com.bigdata.quorum.AsynchronousQuorumCloseException; import com.bigdata.quorum.QuorumException; import com.bigdata.service.IService; @@ -232,4 +234,31 @@ Future<IHASnapshotResponse> takeSnapshot(IHASnapshotRequest req) throws IOException; + /** + * Disaster recovery (REBUILD) of the local database instance from the + * leader of a met quorum. + * + * There are several preconditions: + * <ul> + * + * <li>The quorum must be met and there must be an + * {@link HAStatusEnum#Ready} leader.</li> + * + * <li>This service must be {@link HAStatusEnum#NotReady}.</li> + * + * <li>This service MUST NOT be at the same commit point as the leader (if + * it is, then the service could meet in a data race with the met quorum and + * we do not permit RESTORE if the service is joined with the met quorum).</li> + * + * <li>The {@link HAJournalServer} must not be running a RESTORE (we don't + * want it to accidentally interrupt a RESTORE that is in progress).</li> + * + * </ul> + * + * @return The (asynchronous) {@link Future} of the REBUILD operation -or- + * <code>null</code> if any of the pre-conditions were violated. + */ + Future<Void> rebuildFromLeader(IHARemoteRebuildRequest req) + throws IOException; + } Added: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/HARemoteRebuildRequest.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/HARemoteRebuildRequest.java (rev 0) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/HARemoteRebuildRequest.java 2013-05-16 14:26:59 UTC (rev 7133) @@ -0,0 +1,39 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package com.bigdata.ha.msg; + +import java.io.Serializable; + +public class HARemoteRebuildRequest implements IHARemoteRebuildRequest, + Serializable { + + private static final long serialVersionUID = 1L; + + /** + */ + public HARemoteRebuildRequest() { + + } + +} Added: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/IHARemoteRebuildRequest.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/IHARemoteRebuildRequest.java (rev 0) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/msg/IHARemoteRebuildRequest.java 2013-05-16 14:26:59 UTC (rev 7133) @@ -0,0 +1,40 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package com.bigdata.ha.msg; + +import com.bigdata.ha.HAGlue; + +/** + * Message requesting disaster recovery of the service from the quorum + * leader. This message is sent to the service that must be recovered. + * The service will then message the leader to send its backing state. + * + * @see HAGlue#rebuildFromLeader() + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public interface IHARemoteRebuildRequest extends IHAMessage { + + +} Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-16 12:35:45 UTC (rev 7132) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-16 14:26:59 UTC (rev 7133) @@ -126,6 +126,7 @@ import com.bigdata.ha.msg.IHAReadRequest; import com.bigdata.ha.msg.IHAReadResponse; import com.bigdata.ha.msg.IHARebuildRequest; +import com.bigdata.ha.msg.IHARemoteRebuildRequest; import com.bigdata.ha.msg.IHARootBlockRequest; import com.bigdata.ha.msg.IHARootBlockResponse; import com.bigdata.ha.msg.IHASendStoreResponse; @@ -5477,7 +5478,7 @@ * * @see HAGlue#getHAStatus() */ - final protected HAStatusEnum getHAStatus() { + final public HAStatusEnum getHAStatus() { if (quorum == null) { @@ -5936,6 +5937,14 @@ } + @Override + public Future<Void> rebuildFromLeader(IHARemoteRebuildRequest req) + throws IOException { + + throw new UnsupportedOperationException(); + + } + /** * Return a proxy object for a {@link Future} suitable for use in an RMI * environment (the default implementation returns its argument). Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-16 12:35:45 UTC (rev 7132) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-16 14:26:59 UTC (rev 7133) @@ -68,6 +68,7 @@ import com.bigdata.ha.msg.HADigestResponse; import com.bigdata.ha.msg.HALogDigestResponse; import com.bigdata.ha.msg.HALogRootBlocksResponse; +import com.bigdata.ha.msg.HARemoteRebuildRequest; import com.bigdata.ha.msg.HASendStoreResponse; import com.bigdata.ha.msg.HASnapshotDigestResponse; import com.bigdata.ha.msg.IHADigestRequest; @@ -79,6 +80,7 @@ import com.bigdata.ha.msg.IHALogRootBlocksRequest; import com.bigdata.ha.msg.IHALogRootBlocksResponse; import com.bigdata.ha.msg.IHARebuildRequest; +import com.bigdata.ha.msg.IHARemoteRebuildRequest; import com.bigdata.ha.msg.IHASendStoreResponse; import com.bigdata.ha.msg.IHASnapshotDigestRequest; import com.bigdata.ha.msg.IHASnapshotDigestResponse; @@ -1472,6 +1474,59 @@ } + @Override + public Future<Void> rebuildFromLeader(final IHARemoteRebuildRequest req) + throws IOException { + + final HAQuorumService<HAGlue, HAJournal> localService = getQuorumService(); + + final RunStateEnum innerRunState = (localService == null ? null + : localService.getRunStateEnum()); + + if(innerRunState == null) + return null; + + switch (innerRunState) { + case Error: + case SeekConsensus: + case Operator: { + + if (localService == null) + return null; + + final Future<Void> f = localService + .rebuildFromLeader(new HARemoteRebuildRequest()); + + if (f == null) + return null; + + haLog.warn("Started REBUILD"); + + return getProxy(f, true/* async */); + + } + case Rebuild: + // Already running rebuild. + return null; + case Restore: + // Running restore. Can not do rebuild. + return null; + case Resync: + // Running resync. Can not do rebuild. + return null; + case RunMet: + // RunMet. Can not do rebuild. + return null; + case Shutdown: + // Shutting down. Can not do rebuild. + return null; + default: + // Unknown run state. + throw new AssertionError("innerRunState=" + innerRunState); + } + + } + /** * Note: The invocation layer factory is reused for each exported proxy (but * the exporter itself is paired 1:1 with the exported proxy). Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java 2013-05-16 12:35:45 UTC (rev 7132) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java 2013-05-16 14:26:59 UTC (rev 7133) @@ -60,6 +60,7 @@ import com.bigdata.concurrent.FutureTaskMon; import com.bigdata.ha.HAGlue; import com.bigdata.ha.HAPipelineGlue; +import com.bigdata.ha.HAStatusEnum; import com.bigdata.ha.QuorumService; import com.bigdata.ha.QuorumServiceBase; import com.bigdata.ha.halog.HALogWriter; @@ -73,6 +74,7 @@ import com.bigdata.ha.msg.IHALogRequest; import com.bigdata.ha.msg.IHALogRootBlocksResponse; import com.bigdata.ha.msg.IHARebuildRequest; +import com.bigdata.ha.msg.IHARemoteRebuildRequest; import com.bigdata.ha.msg.IHASendStoreResponse; import com.bigdata.ha.msg.IHASnapshotResponse; import com.bigdata.ha.msg.IHASyncRequest; @@ -1149,12 +1151,68 @@ } /** + * Enter RESTORE. + * + * @return + * @throws IOException + * + * @see HAGlue#rebuildFromLeader(IHARemoteRebuildRequest) + */ + public Future<Void> rebuildFromLeader(final IHARemoteRebuildRequest req) + throws IOException { + + final Quorum<HAGlue, QuorumService<HAGlue>> quorum = getQuorum(); + + final QuorumService<HAGlue> localService = quorum.getClient(); + + if (localService == null) + return null; + + final long token = quorum.token(); + + if (journal.getHAStatus() != HAStatusEnum.NotReady) + return null; + + final UUID leaderId = quorum.getLeaderId(); + + if (leaderId == null) + return null; + + final HAGlue leader = localService.getService(leaderId); + + if (leader.getHAStatus() != HAStatusEnum.Leader) { + + return null; + + } + + final IRootBlockView leaderRB = leader.getRootBlock( + new HARootBlockRequest(null/* storeUUID */)).getRootBlock(); + + final IRootBlockView localRB = journal.getRootBlockView(); + + if (leaderRB.getCommitCounter() == localRB.getCommitCounter()) { + + // At the same commit point. + return null; + + } + + // Re-verify. + if (journal.getHAStatus() != HAStatusEnum.NotReady) + return null; + + return enterRunState(new RebuildTask(token)); + + } + + /** * Change the run state. * * @param runStateTask * The task for the new run state. */ - private void enterRunState(final RunStateCallable<Void> runStateTask) { + private Future<Void> enterRunState(final RunStateCallable<Void> runStateTask) { if (runStateTask == null) throw new IllegalArgumentException(); @@ -1181,6 +1239,8 @@ // haLog.info("Entering runState=" // + runStateTask.getClass().getSimpleName()); + return ft; + } finally { if (oldFuture != null) { Modified: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java 2013-05-16 12:35:45 UTC (rev 7132) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java 2013-05-16 14:26:59 UTC (rev 7133) @@ -70,6 +70,7 @@ import com.bigdata.ha.msg.IHAReadRequest; import com.bigdata.ha.msg.IHAReadResponse; import com.bigdata.ha.msg.IHARebuildRequest; +import com.bigdata.ha.msg.IHARemoteRebuildRequest; import com.bigdata.ha.msg.IHARootBlockRequest; import com.bigdata.ha.msg.IHARootBlockResponse; import com.bigdata.ha.msg.IHASendStoreResponse; @@ -673,6 +674,16 @@ } @Override + public Future<Void> rebuildFromLeader(IHARemoteRebuildRequest req) throws IOException { + + checkMethod("restoreFromLeader", + new Class[] { IHARemoteRebuildRequest.class }); + + return super.rebuildFromLeader(req); + + } + + @Override public Future<Void> globalWriteLock(IHAGlobalWriteLockRequest req) throws IOException, TimeoutException, InterruptedException { Modified: branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/HAStatusServletUtil.java =================================================================== --- branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/HAStatusServletUtil.java 2013-05-16 12:35:45 UTC (rev 7132) +++ branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/HAStatusServletUtil.java 2013-05-16 14:26:59 UTC (rev 7133) @@ -43,7 +43,9 @@ import com.bigdata.ha.HAStatusEnum; import com.bigdata.ha.QuorumService; import com.bigdata.ha.halog.IHALogReader; +import com.bigdata.ha.msg.HARemoteRebuildRequest; import com.bigdata.ha.msg.HASnapshotRequest; +import com.bigdata.ha.msg.IHARemoteRebuildRequest; import com.bigdata.journal.IIndexManager; import com.bigdata.journal.IRootBlockView; import com.bigdata.journal.RootBlockView; @@ -70,6 +72,17 @@ */ public class HAStatusServletUtil { + /** + * Disaster recover of this service from the leader (REBUILD). + * + * @see HAGlue#rebuildFromLeader(IHARemoteRebuildRequest) + * + * TODO Move this declaration to {@link StatusServlet} once we are done + * reconciling between the 1.2.x maintenance branch and the READ_CACHE + * branch. + */ + static final String REBUILD = "rebuild"; + final private IIndexManager indexManager; public HAStatusServletUtil(final IIndexManager indexManager) { @@ -117,6 +130,7 @@ final int njoined = quorum.getJoined().length; + // Note: This is the *local* HAGlueService. final QuorumService<HAGlue> quorumService = quorum.getClient(); final boolean digests = req.getParameter(StatusServlet.DIGESTS) != null; @@ -421,7 +435,7 @@ } /* - * If requested, conditional start a snapshot. + * If requested, conditionally start a snapshot. */ { final String val = req.getParameter(StatusServlet.SNAPSHOT); @@ -446,12 +460,12 @@ // ignore. } - ((HAJournal) journal).getSnapshotManager().takeSnapshot( + journal.getSnapshotManager().takeSnapshot( new HASnapshotRequest(percentLogSize)); } - } + } /* * Report if a snapshot is currently running. @@ -468,6 +482,36 @@ } + /** + * If requested, conditionally REBUILD the service from the leader + * (disaster recover). + * + * FIXME This should only be triggered by a POST (it is modestly safe + * since a REBUILD can not be triggered if the service is joined, at the + * same commit point as the leader, or already running, but it is not so + * safe that you should be able to use a GET to demand a REBUILD). + */ + { + + final String val = req.getParameter(HAStatusServletUtil.REBUILD); + + if (val != null) { + + // Local HAGlue interface for this service (not proxy). + final HAGlue haGlue = quorumService.getService(); + + // Request RESTORE. + if (haGlue.rebuildFromLeader(new HARemoteRebuildRequest()) != null) { + + current.node("h2", + "Running Disaster Recovery for this service (REBUILD)."); + + } + + } + + } + /* * Display the NSS port, host, and leader/follower/not-joined * status for each service in the quorum. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-16 12:35:52
|
Revision: 7132 http://bigdata.svn.sourceforge.net/bigdata/?rev=7132&view=rev Author: thompsonbry Date: 2013-05-16 12:35:45 +0000 (Thu, 16 May 2013) Log Message: ----------- I have fixed a problem with the CyclicBarrier. CyclicBarrier.await(timeout,unit) breaks the barrier if the timeout occurs. I was trying to use this to setup a spin wait, but that pattern does not work with that class. This cleans up the UPDATE behavior on the HA3 cluster for BSBM 100M. However, when running UPDATE (leader) + EXPLORE (follower), we see a problem where the 1st follower drops out of the quorum. It looks like the root cause is that the gather is still running on the follower when the PREPARE comes through. The follower sees the old gather Future. It is "old" since we should not be in gather any more. It then cancels that gather and votes NO on prepare and starts to ignore write messages on the pipeline since it does not go through the commit with the other services. Sounds like waiting on the old gather future at AbstractJournal is necessary. The follower messages the leader with its input for the release time protocol, but it does not message the leader to indicate that it has locally applied the leader's consensus for the release time protocol. I can add that oldFuture.get() easily enough. I have also improved the javadoc and logging. @see https://sourceforge.net/apps/trac/bigdata/ticket/673 (DGC in release time consensus protocol causes native thread leak in HAJournalServer at each commit) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractTransactionService.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-15 20:57:56 UTC (rev 7131) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-16 12:35:45 UTC (rev 7132) @@ -51,6 +51,7 @@ import java.util.UUID; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -6157,6 +6158,10 @@ * Validate the release time consensus protocol was * completed successfully on the follower. * + * Note: We need to block here (on oldFuture.get()) in case + * the follower has not finished applying the updated + * release time. + * * @see <a * href="https://sourceforge.net/apps/trac/bigdata/ticket/673" * > Native thread leak in HAJournalServer process </a> @@ -6166,26 +6171,29 @@ .getAndSet(null/* newValue */); if (oldFuture == null) { - throw new IllegalStateException( "Follower did not execute consensus protocol"); } - if (!oldFuture.isDone()) { - // Ensure cancelled. - oldFuture.cancel(true/* mayInterruptIfRunning */); - } +// if (!oldFuture.isDone()) { +// // Ensure cancelled. +// haLog.error("Gather not done on follower: serviceId=" + getServiceId()+ " : will cancel."); +// oldFuture.cancel(true/* mayInterruptIfRunning */); +// } try { oldFuture.get(); // Gather was successful - fall through. } catch (InterruptedException e) { - // Note: Future isDone(). Caller will not block. + // Note: Future isDone(). Caller should not block. throw new AssertionError(); + } catch (CancellationException e) { + // Gather cancelled on the follower (e.g., immediately above). + haLog.error("Gather cancelled on follower: serviceId=" + + getServiceId() + " : " + e, e); + return vote.get(); } catch (ExecutionException e) { - /* - * Gather failed on the follower. - */ + // Gather failed on the follower. haLog.error("Gather failed on follower: serviceId=" + getServiceId() + " : " + e, e); return vote.get(); @@ -6892,11 +6900,11 @@ public void gatherMinimumVisibleCommitTime( final IHAGatherReleaseTimeRequest req) throws IOException { - if (haLog.isInfoEnabled()) - haLog.info("req=" + req); + if (haLog.isInfoEnabled()) haLog.info("req=" + req); - // Clear the old outcome. - gatherFuture.set(null); + // Clear the old outcome. Reference SHOULD be null. Ensure not running. + final Future<Void> oldFuture = gatherFuture.getAndSet(null); + if(oldFuture!=null&&!oldFuture.isDone()) oldFuture.cancel(true/*mayInterruptIfRunning*/); final Callable<Void> task = ((AbstractHATransactionService) AbstractJournal.this .getLocalTransactionManager() Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-15 20:57:56 UTC (rev 7131) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-16 12:35:45 UTC (rev 7132) @@ -512,10 +512,14 @@ * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/673" > * Native thread leak in HAJournalServer process </a> */ - private void messageFollowers(final long token, final long timeout, - final TimeUnit units) throws IOException, InterruptedException, + private void messageFollowers(final long token, final long timeoutNanos) + throws IOException, InterruptedException, BrokenBarrierException, TimeoutException { + final long begin = System.nanoTime(); + final long nanos = timeoutNanos; + long remaining = nanos; + getQuorum().assertLeader(token); // /* @@ -689,12 +693,19 @@ } }, initialDelay, delay, TimeUnit.MILLISECONDS); + // Update time remaining. + remaining = nanos - (System.nanoTime() - begin); + try { /* - * Throws InterruptedException, BrokenBarrierException. + * Throws InterruptedException, BrokenBarrierException, + * TimeoutException. + * + * Note: If TimeoutException is thrown, then the barrier + * will be broken. */ - barrier.await(); + barrier.await(remaining, TimeUnit.NANOSECONDS); } finally { @@ -993,6 +1004,11 @@ * determined by the releaseTime on the transaction service).</li> * </ul> * Any of these actions must contend for the {@link #barrierLock}. + * + * @see #updateReleaseTimeConsensus(long, TimeUnit) + * @see GatherTask#call() + * @see #newTx(long) + * @see #runWithBarrierLock(Runnable) */ final private ReentrantLock barrierLock = new ReentrantLock(); @@ -1041,6 +1057,10 @@ final TimeUnit units) throws IOException, InterruptedException, TimeoutException, BrokenBarrierException { + final long begin = System.nanoTime(); + final long nanos = units.toNanos(timeout); + long remaining = nanos; + final long token = getQuorum().token(); final BarrierState barrierState; @@ -1063,8 +1083,12 @@ /* * Message the followers and block until the barrier breaks. */ - barrierState.messageFollowers(token, timeout, units); + // Update time remaining. + remaining = nanos - (System.nanoTime() - begin); + + barrierState.messageFollowers(token, remaining); + } finally { // Clear the barrierRef. @@ -1077,8 +1101,22 @@ } - /* - * Update the release time on the leader + /** + * Update the release time on the leader. + * + * Note: The follower has the new release time, but it is + * running asynchronously and might not have updated its release + * time locally by the time the leader leaves the consensus + * protocol. prepare2Phase() (on the follower) will check the + * Future of the GatherTask and block until it is complete. Thus + * all services will be in a state where they are known to have + * updated their release time (based on the consensus protocol) + * before we finish prepare2Phase() and hence before we run + * commit2Phase(). + * + * @see <a + * href="https://sourceforge.net/apps/trac/bigdata/ticket/673" + * > Native thread leak in HAJournalServer process </a> */ final IHANotifyReleaseTimeResponse consensus = barrierState.consensus; @@ -1312,7 +1350,7 @@ public Void call() throws Exception { if (log.isInfoEnabled()) - log.info("Running gather on follower: " + getServiceUUID()); + log.info("Running gather on follower"); HAGlue leader = null; @@ -1358,7 +1396,8 @@ * Now spot check the earliest active tx on this follower. * We want to make sure that this tx is not reading against * a commit point whose state would be released by the new - * consensus releaseTime. + * [consensusReleaseTime] that we just obtained from the + * leader. * * If everything is Ok, we update the releaseTime on the * follower. @@ -1367,7 +1406,11 @@ lock.lock(); try { - + + if (log.isInfoEnabled()) + log.info("Validating consensus releaseTime on follower: consensus=" + + consensusReleaseTime); + // the earliest active tx on this follower. final TxState txState = getEarliestActiveTx(); @@ -1683,7 +1726,10 @@ try { - return this._newTx(timestamp); + if (log.isInfoEnabled()) + log.info("NewTx with barrierLock"); + + return _newTx(timestamp); } finally { Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractTransactionService.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractTransactionService.java 2013-05-15 20:57:56 UTC (rev 7131) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractTransactionService.java 2013-05-16 12:35:45 UTC (rev 7132) @@ -668,7 +668,10 @@ /** * Private version is also used by {@link #start()}. - */ + * + * TODO Why is this synchronized(this)? The timestamp factory is + * synchronized internally and {@link #lastTimestamp} is volatile. + */ synchronized private final long _nextTimestamp() { return lastTimestamp = MillisecondTimestampFactory.nextMillis(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-15 20:58:03
|
Revision: 7131 http://bigdata.svn.sourceforge.net/bigdata/?rev=7131&view=rev Author: thompsonbry Date: 2013-05-15 20:57:56 +0000 (Wed, 15 May 2013) Log Message: ----------- Added a bit more information into getExtendedRunState() for an "at a glance" view of the services in an HA cluster. Modified Paths: -------------- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-15 20:39:30 UTC (rev 7130) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java 2013-05-15 20:57:56 UTC (rev 7131) @@ -1726,6 +1726,8 @@ } innerRunStateStr.append(" @ " + journal.getRootBlockView().getCommitCounter()); + innerRunStateStr.append(", haReady=" + getHAReady()); + innerRunStateStr.append(", haStatus=" + getHAStatus()); final String msg = server.getOperatorAlert(); if (msg != null) innerRunStateStr.append(", msg=[" + msg + "]"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-15 20:39:39
|
Revision: 7130 http://bigdata.svn.sourceforge.net/bigdata/?rev=7130&view=rev Author: thompsonbry Date: 2013-05-15 20:39:30 +0000 (Wed, 15 May 2013) Log Message: ----------- I performed a code review searching for all instances in the project of {{{ System.nanoTime() }}} Problems were identified in - QuorumCommitImpl.prepare2Phase(); - ServicesManagerStartupTask - JiniCoreServicesConfiguration - JiniServiceConfiguration - ZookeeperServerConfiguration. - ProcessHelper.exitValue() - WORMStrategy.writeOnChannel() (this is only ever invoked with Long.MAX_VALUE, but the code was still wrong). The RWStore version of writeOnChannel() is actually ignoring the timeout (I've added a TODO, but per above the timeout is Long.MAX_VALUE). - AsynchronousOverflowTask.runTasksInSingleThread() - JiniFederation.awaitJiniRegistrars() - Haltable - Latch.await() - ZLockImpl.lock() - ZLockImpl.awaitZLockNanos() - ZookeeperAccessor.awaitZookeeperConnected() - AbstractTransactionService.findUnusedTimestamp() I've added unit tests for Latch and Haltable that verify the bug and the fix. The errors in ZLockImpl could explain some odd behaviors in CI for the JiniFederation test suite. @see https://sourceforge.net/apps/trac/bigdata/ticket/676 (Bad patterns for timeout computations) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/io/writecache/WriteCache.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/WORMStrategy.java branches/READ_CACHE/bigdata/src/java/com/bigdata/resources/AsynchronousOverflowTask.java branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractTransactionService.java branches/READ_CACHE/bigdata/src/java/com/bigdata/util/concurrent/Haltable.java branches/READ_CACHE/bigdata/src/java/com/bigdata/util/concurrent/Latch.java branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestAll.java branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestHaltable.java branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestLatch.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/ServicesManagerStartupTask.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/JiniCoreServicesConfiguration.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/JiniServiceConfiguration.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/ZookeeperServerConfiguration.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/process/ProcessHelper.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/service/jini/JiniFederation.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/zookeeper/ZLockImpl.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/zookeeper/ZooKeeperAccessor.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java Added Paths: ----------- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestCyclicBarrier.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/io/writecache/WriteCache.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/io/writecache/WriteCache.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/io/writecache/WriteCache.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -1737,6 +1737,8 @@ /** * Called by WriteCacheService to process a direct write for large * blocks and also to flush data from dirty caches. + * + * TODO The [nanos] parameter is ignored. */ protected boolean writeOnChannel(final ByteBuffer data, final long firstOffsetIgnored, Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/WORMStrategy.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/WORMStrategy.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/WORMStrategy.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -1066,7 +1066,7 @@ try { - remaining -= (System.nanoTime() - begin); + remaining = nanos - (System.nanoTime() - begin); final int dpos = data.position(); final int nbytes = data.remaining(); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/resources/AsynchronousOverflowTask.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/resources/AsynchronousOverflowTask.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/resources/AsynchronousOverflowTask.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -3145,14 +3145,16 @@ final long begin = System.nanoTime(); // remaining nanoseconds in which to execute overflow tasks. - long nanos = TimeUnit.MILLISECONDS + final long nanos = TimeUnit.MILLISECONDS .toNanos(resourceManager.overflowTimeout); + long remaining = nanos; + final Iterator<AbstractTask> titr = tasks.iterator(); int ndone = 0; - while (titr.hasNext() && nanos > 0) { + while (titr.hasNext() && remaining > 0) { final boolean shouldOverflow = resourceManager .isOverflowEnabled() @@ -3182,10 +3184,10 @@ final Future<? extends Object> f = resourceManager .getConcurrencyManager().submit(task); - getFutureForTask(f, task, nanos, TimeUnit.NANOSECONDS); + getFutureForTask(f, task, remaining, TimeUnit.NANOSECONDS); - nanos -= (System.nanoTime() - begin); - + remaining = nanos - (System.nanoTime() - begin); + ndone++; } Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractTransactionService.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractTransactionService.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/service/AbstractTransactionService.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -1861,11 +1861,11 @@ final long nextCommitTime, final long timeout, final TimeUnit unit) throws InterruptedException, TimeoutException { - long nanos = unit.toNanos(timeout); - final long begin = System.nanoTime(); + final long nanos = unit.toNanos(timeout); + long remaining = nanos; - while (nanos >= 0) { + while (remaining >= 0) { for (long t = commitTime; t < nextCommitTime; t++) { @@ -1908,15 +1908,15 @@ * Note: throws InterruptedException */ - nanos -= (System.nanoTime() - begin); + remaining = nanos - (System.nanoTime() - begin); - if (!txDeactivate.await(nanos, TimeUnit.NANOSECONDS)) { + if (!txDeactivate.await(remaining, TimeUnit.NANOSECONDS)) { throw new TimeoutException(); } - nanos -= (System.nanoTime() - begin); + remaining = nanos - (System.nanoTime() - begin); } Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/util/concurrent/Haltable.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/util/concurrent/Haltable.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/util/concurrent/Haltable.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -258,14 +258,15 @@ final public V get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { final long begin = System.nanoTime(); - long nanos = unit.toNanos(timeout); - if (lock.tryLock(nanos, TimeUnit.NANOSECONDS)) { + final long nanos = unit.toNanos(timeout); + long remaining = nanos; + if (lock.tryLock(remaining, TimeUnit.NANOSECONDS)) { try { // subtract out the elapsed time - nanos -= (System.nanoTime() - begin); + remaining = nanos - (System.nanoTime() - begin); while (!halt) { - if (nanos > 0) - nanos = halted.awaitNanos(nanos); + if (remaining > 0) + remaining = halted.awaitNanos(remaining); else throw new TimeoutException(); } Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/util/concurrent/Latch.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/util/concurrent/Latch.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/util/concurrent/Latch.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -339,47 +339,29 @@ public boolean await(final long timeout, final TimeUnit unit) throws InterruptedException { - long nanos = unit.toNanos(timeout); final long start = System.nanoTime(); + final long nanos = unit.toNanos(timeout); + long remaining = nanos; - if (lock.tryLock(nanos, TimeUnit.NANOSECONDS)) { + if (lock.tryLock(remaining, TimeUnit.NANOSECONDS)) { try { // subtract out the lock waiting time. - nanos -= (System.nanoTime() - start); + remaining = nanos - (System.nanoTime() - start); long c; while ((c = counter.get()) != 0) { if (c < 0) throw new IllegalStateException(toString()); - if (nanos > 0) - nanos = cond.awaitNanos(nanos); + if (remaining > 0) + remaining = cond.awaitNanos(remaining); else return false; } return true; -// if (counter.get() == 0) { -// -// if (log.isInfoEnabled()) -// log.info("Done waiting (true)."); -// -// // don't wait. -// return true; -// -// } -// -// if (cond.await(nanos, TimeUnit.NANOSECONDS)) { -// -// if (log.isInfoEnabled()) -// log.info("Done waiting (true)"); -// -// return true; -// -// } - } finally { lock.unlock(); @@ -387,9 +369,6 @@ } } -// if (log.isInfoEnabled()) -// log.info("Timeout (false) : counter" + counter); - // Timeout. return false; Modified: branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestAll.java =================================================================== --- branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestAll.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestAll.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -27,10 +27,6 @@ package com.bigdata.util.concurrent; - -import com.bigdata.jsr166.LinkedBlockingDequeTest; -import com.bigdata.jsr166.LinkedBlockingQueueTest; - import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; Modified: branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestHaltable.java =================================================================== --- branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestHaltable.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestHaltable.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -29,6 +29,8 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import junit.framework.TestCase2; @@ -120,4 +122,45 @@ } -} + public void test_get_timeout() throws InterruptedException, ExecutionException { + + final Haltable<Long> f = new Haltable<Long>(); + + assertFalse(f.isDone()); + assertFalse(f.isCancelled()); + assertNull(f.getCause()); + + final Long result = Long.valueOf(12); + + { + final long timeout = TimeUnit.SECONDS.toNanos(1L); + final long begin = System.nanoTime(); + try { + f.get(timeout, TimeUnit.NANOSECONDS); + fail("Expecting: " + TimeoutException.class); + } catch (TimeoutException e) { + // ignore + } + final long elapsed = System.nanoTime() - begin; + if (elapsed < timeout || (elapsed > (2 * timeout))) { + fail("elapsed=" + elapsed + ", timeout=" + timeout); + } + } + + // set the result. + f.halt(result); + + assertTrue(result == f.get()); + + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + assertNull(f.getCause()); + assertNull(f.getAsThrownCause()); + + assertFalse(f.cancel(true/*mayInterruptIfRunning*/)); + + assertTrue(result == f.get()); + + } + +} \ No newline at end of file Modified: branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestLatch.java =================================================================== --- branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestLatch.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata/src/test/com/bigdata/util/concurrent/TestLatch.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -34,7 +34,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import junit.framework.TestCase2; @@ -111,8 +110,8 @@ latch.inc(); - if(!latch.await(100, TimeUnit.MILLISECONDS)) - throw new TimeoutException(); + if (!latch.await(100, TimeUnit.MILLISECONDS)) + fail("Expecting latch to decrement to zero."); return null; @@ -132,7 +131,8 @@ latch.dec(); - future.get(); + // Verify normal return. + assertNull(future.get()); } finally { @@ -213,5 +213,48 @@ assertEquals(0, latch.addAndGet(-1)); } + + /** + * Test of {@link Latch#await(long, TimeUnit)}. + * @throws InterruptedException + */ + public void test5() throws InterruptedException { + + final Latch latch = new Latch(); + + assertEquals(latch.get(), 0); + + assertEquals(latch.inc(), 1); + + assertEquals(latch.get(), 1); + + { + final long timeout = TimeUnit.SECONDS.toNanos(1L); + final long begin = System.nanoTime(); + // await latch to decrement to zero. + assertFalse(latch.await(timeout, TimeUnit.NANOSECONDS)); + final long elapsed = System.nanoTime() - begin; + if (elapsed < timeout || (elapsed > (2 * timeout))) { + fail("elapsed=" + elapsed + ", timeout=" + timeout); + } + } + + assertEquals(latch.get(), 1); + + assertEquals(latch.dec(), 0); + + assertTrue(latch.await(1, TimeUnit.SECONDS)); + + try { + latch.dec(); + fail("Expecting: " + IllegalStateException.class); + } catch (IllegalStateException ex) { + if (log.isInfoEnabled()) + log.info("Ignoring expected error: " + ex); + } + + assertEquals(latch.get(), 0); + + } } Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/ServicesManagerStartupTask.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/ServicesManagerStartupTask.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/ServicesManagerStartupTask.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -169,10 +169,11 @@ final long begin = System.nanoTime(); - long nanos = selfConfig.zookeeperDiscoveryTimeoutNanos; + final long nanos = selfConfig.zookeeperDiscoveryTimeoutNanos; + long remaining = nanos; // await zookeeper connection. - if (!fed.getZookeeperAccessor().awaitZookeeperConnected(nanos, + if (!fed.getZookeeperAccessor().awaitZookeeperConnected(remaining, TimeUnit.NANOSECONDS)) { throw new Exception( @@ -180,7 +181,7 @@ } - nanos -= (System.nanoTime() - begin); + remaining = nanos - (System.nanoTime() - begin); /* * @todo Should have its own timeout value (using zk's). Or just get @@ -188,7 +189,7 @@ * discovered and you can kill it if there is a problem. */ // await jini registrar(s) - if (!fed.awaitJiniRegistrars(nanos, TimeUnit.NANOSECONDS)) { + if (!fed.awaitJiniRegistrars(remaining, TimeUnit.NANOSECONDS)) { throw new Exception( "No jini registrars: startup sequence aborted."); Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/JiniCoreServicesConfiguration.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/JiniCoreServicesConfiguration.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/JiniCoreServicesConfiguration.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -49,7 +49,6 @@ import com.bigdata.jini.start.process.JiniCoreServicesProcessHelper; import com.bigdata.service.jini.JiniClientConfig; import com.bigdata.service.jini.util.LookupStarter; -import com.bigdata.service.jini.util.LookupStarter; import com.sun.jini.start.NonActivatableServiceDescriptor; import com.sun.jini.start.ServiceStarter; @@ -308,7 +307,7 @@ final long begin = System.nanoTime(); - long nanos = unit.toNanos(timeout); + final long nanos = unit.toNanos(timeout); /* * The #of registrars that we can locate on this host within a @@ -332,7 +331,7 @@ final LookupLocator locators[] = lst.toArray(new LookupLocator[0]); // adjust for elapsed time. - nanos -= (System.nanoTime() - begin); + final long remaining = nanos - (System.nanoTime() - begin); /* * Look for at least one registrar on the local host using the @@ -341,13 +340,10 @@ final ServiceRegistrar[] registrars = getServiceRegistrars(1/* maxCount */, clientConfig.groups, /* clientConfig. */locators, - nanos, TimeUnit.NANOSECONDS); + remaining, TimeUnit.NANOSECONDS); // elapsed time (ns). final long elapsed = (System.nanoTime() - begin); - - // adjust for elapsed time. - nanos -= elapsed; if (log.isInfoEnabled()) log @@ -389,10 +385,6 @@ long timeout, final TimeUnit unit) throws InterruptedException, IOException { - final long begin = System.nanoTime(); - - timeout = unit.toNanos(timeout); - final Object signal = new Object(); final LookupDiscoveryManager discovery = new LookupDiscoveryManager(groups, @@ -428,20 +420,29 @@ try { - long elapsed; - // demand some results. ServiceRegistrar[] registrars = new ServiceRegistrar[0]; - while ((timeout -= (elapsed = (System.nanoTime() - begin))) > 0 - && registrars.length < maxCount) { + final long begin = System.nanoTime(); + final long nanos = unit.toNanos(timeout); + + long remaining = nanos; + + while (remaining > 0 && registrars.length < maxCount) { + + remaining = nanos - (System.nanoTime() - begin); + synchronized (signal) { try { - signal.wait(TimeUnit.NANOSECONDS.toMillis(timeout)); + + signal.wait(TimeUnit.NANOSECONDS.toMillis(remaining)); + } catch(InterruptedException ex) { + // fall through + } if(log.isDebugEnabled()) @@ -453,9 +454,14 @@ } - if (log.isInfoEnabled()) + if (log.isInfoEnabled()) { + + final long elapsed = System.nanoTime() - begin; + log.info("Found " + registrars.length + " registrars in " + TimeUnit.NANOSECONDS.toMillis(elapsed) + "ms."); + + } return registrars; Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/JiniServiceConfiguration.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/JiniServiceConfiguration.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/JiniServiceConfiguration.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -763,21 +763,23 @@ final long begin = System.nanoTime(); - long nanos = unit.toNanos(timeout); + final long nanos = unit.toNanos(timeout); + + long remaining = nanos; // wait for the service to be discovered final ServiceItem serviceItem = awaitServiceDiscoveryOrDeath( - processHelper, nanos, TimeUnit.NANOSECONDS); + processHelper, remaining, TimeUnit.NANOSECONDS); // proxy will be used for destroy(). processHelper.setServiceItem(serviceItem); // subtract out the time we already waited. - nanos -= (System.nanoTime() - begin); + remaining = nanos - (System.nanoTime() - begin); // wait for the ephemeral znode for the service to be created awaitZNodeCreatedOrDeath(serviceItem, processHelper, - nanos, TimeUnit.NANOSECONDS); + remaining, TimeUnit.NANOSECONDS); } Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/ZookeeperServerConfiguration.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/ZookeeperServerConfiguration.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/config/ZookeeperServerConfiguration.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -697,7 +697,7 @@ final long begin = System.nanoTime(); - long nanos = unit.toNanos(timeout); + final long nanos = unit.toNanos(timeout); try { @@ -721,9 +721,6 @@ } - // adjust for time remaining. - nanos = (System.nanoTime() - begin); - /* * Verify that an instance is up and running by connecting to the * client port on the local host. @@ -740,12 +737,11 @@ ZooHelper.ruok(thisInetAddr, clientPort); - // adjust for time remaining. - nanos = (System.nanoTime() - begin); + final long elapsed = (System.nanoTime() - begin); log.warn("Started zookeeper: elapsed=" - + TimeUnit.NANOSECONDS.toMillis(nanos)); - + + TimeUnit.NANOSECONDS.toMillis(elapsed)); + } /** Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/process/ProcessHelper.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/process/ProcessHelper.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/jini/start/process/ProcessHelper.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -165,12 +165,12 @@ * if the caller's thread was interrupted awaiting the exit * value. */ - public int exitValue(long timeout, final TimeUnit unit) + public int exitValue(final long timeout, final TimeUnit unit) throws TimeoutException, InterruptedException { final long begin = System.nanoTime(); - timeout = unit.toNanos(timeout); + final long nanos = unit.toNanos(timeout); lock.lock(); @@ -192,14 +192,12 @@ } - final long elapsed = System.nanoTime() - begin; - - timeout -= elapsed; - - if (timeout <= 0) + final long remaining = nanos - (System.nanoTime() - begin); + + if (remaining <= 0) throw new TimeoutException(); - dead.await(timeout, TimeUnit.NANOSECONDS); + dead.await(remaining, TimeUnit.NANOSECONDS); } Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/service/jini/JiniFederation.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/service/jini/JiniFederation.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/service/jini/JiniFederation.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -468,19 +468,20 @@ final long begin = System.nanoTime(); // nanoseconds remaining. - long nanos = unit.toNanos(timeout); + final long nanos = unit.toNanos(timeout); + long remaining = nanos; ServiceRegistrar[] registrars = null; while (((registrars = lookupDiscoveryManager.getRegistrars()).length == 0) - && (nanos -= (System.nanoTime() - begin)) > 0) { + && ((remaining = nanos - (System.nanoTime() - begin)) > 0)) { discoveryEventLock.lockInterruptibly(); try { // await another discovery event, but not more than the time // remaining. - discoveryEvent.awaitNanos(nanos); + discoveryEvent.awaitNanos(remaining); } finally { @@ -488,6 +489,8 @@ } + remaining = nanos - (System.nanoTime() - begin); + } if (registrars.length == 0) { Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/zookeeper/ZLockImpl.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/zookeeper/ZLockImpl.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/zookeeper/ZLockImpl.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -567,20 +567,21 @@ * {@link ZooKeeper} client, but it can be handled at the * application layer in a number of ways. */ - protected boolean awaitZLockNanos(long nanos) + protected boolean awaitZLockNanos(final long nanos) throws InterruptedException, SessionExpiredException { final long begin = System.nanoTime(); + long remaining = nanos; lock.lockInterruptibly(); try { - while ((nanos -= (System.nanoTime() - begin)) > 0 + while ((remaining = nanos - (System.nanoTime() - begin)) > 0 && !zlockGranted && !cancelled) { if (log.isDebugEnabled()) log.debug("remaining=" - + TimeUnit.NANOSECONDS.toMillis(nanos) + "ms"); + + TimeUnit.NANOSECONDS.toMillis(remaining) + "ms"); try { @@ -634,8 +635,10 @@ * is granted to the caller. */ - zlock.awaitNanos((nanos -= (System.nanoTime() - begin))); + remaining = nanos - (System.nanoTime() - begin); + zlock.awaitNanos(remaining); + } // while if (cancelled) { @@ -645,10 +648,10 @@ } if (log.isDebugEnabled()) - log.debug("nanos remaining=" + nanos); + log.debug("nanos remaining=" + remaining); // lock granted iff nanos remaining is GT zero. - return nanos > 0; + return remaining > 0; } finally { @@ -965,7 +968,8 @@ final long begin = System.nanoTime(); - long nanos = unit.toNanos(timeout); + final long nanos = unit.toNanos(timeout); + long remaining = nanos; /* * Ensure that the lock node exists. @@ -996,14 +1000,14 @@ this.watcher = new ZLockWatcher(zchild); - nanos -= (System.nanoTime() - begin); + remaining = nanos - (System.nanoTime() - begin); try { /* Note: The state reported here is incomplete since [priorZChild] is not set until we test things in awaitZLockNanos(). */ - if(log.isInfoEnabled()) - log.info("Will await zlock: "+this); + if (log.isInfoEnabled()) + log.info("Will await zlock: " + this); - if(!watcher.awaitZLockNanos(nanos)) { + if(!watcher.awaitZLockNanos(remaining)) { // timeout (lock not granted). throw new TimeoutException(); Modified: branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/zookeeper/ZooKeeperAccessor.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/zookeeper/ZooKeeperAccessor.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/zookeeper/ZooKeeperAccessor.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -446,11 +446,12 @@ final long begin = System.nanoTime(); // nanoseconds remaining. - long nanos = unit.toNanos(timeout); + final long nanos = unit.toNanos(timeout); + long remaining = nanos; ZooKeeper.States state = null; - while ((nanos -= (System.nanoTime() - begin)) > 0) { + while ((remaining = nanos - (System.nanoTime() - begin)) > 0) { switch (state = getZookeeper().getState()) { @@ -469,7 +470,8 @@ // wait a bit, but not more than the time remaining. lock.lockInterruptibly(); try { - event.awaitNanos(nanos); + remaining = nanos - (System.nanoTime() - begin); + event.awaitNanos(remaining); } finally { lock.unlock(); } Modified: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java 2013-05-15 18:35:21 UTC (rev 7129) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -31,9 +31,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; -import java.io.RandomAccessFile; import java.io.StringWriter; -import java.nio.channels.FileLock; import java.rmi.Remote; import java.util.Arrays; import java.util.LinkedList; @@ -1731,9 +1729,9 @@ final long timeout, final TimeUnit unit) throws Exception, TimeoutException, InterruptedException { - final long begin = System.nanoTime(); +// final long begin = System.nanoTime(); - long nanos = unit.toNanos(timeout); + final long nanos = unit.toNanos(timeout); // wait for the service to be discovered serviceItem = awaitServiceDiscoveryOrDeath(processHelper, @@ -1742,9 +1740,9 @@ // // proxy will be used for destroy(). // processHelper.setServiceItem(serviceItem); - // subtract out the time we already waited. - nanos -= (System.nanoTime() - begin); - +// // subtract out the time we already waited. +// final long remaining = nanos - (System.nanoTime() - begin); +// // // TODO (restore) wait for the ephemeral znode for the service to be created // awaitZNodeCreatedOrDeath(serviceItem, processHelper, nanos, // TimeUnit.NANOSECONDS); Added: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestCyclicBarrier.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestCyclicBarrier.java (rev 0) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestCyclicBarrier.java 2013-05-15 20:39:30 UTC (rev 7130) @@ -0,0 +1,54 @@ +package com.bigdata.journal.jini.ha; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import junit.framework.TestCase; + +/** + * This test demonstrates that {@link CyclicBarrier} does not adhere to its + * documentation for {@link CyclicBarrier#await(long, TimeUnit)}. This means + * that we can not use this variant in the release time consensus protocol since + * we must also watch for service leaves, etc. + * <p> + * Note: We can still use the {@link CyclicBarrier#await()} as long as we + * <em>interrupt</em> one of the threads that is blocked in + * {@link CyclicBarrier#await()}. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class TestCyclicBarrier extends TestCase { + + public TestCyclicBarrier() { + + } + + public TestCyclicBarrier(String name) { + super(name); + } + + public void test_cyclicBarrier_awaitTimeout() throws InterruptedException, + BrokenBarrierException, TimeoutException { + + final CyclicBarrier b = new CyclicBarrier(2); + + assertFalse(b.isBroken()); + + try { + + b.await(1000, TimeUnit.MILLISECONDS); + + fail("Barrier should not be broken"); + + } catch (TimeoutException ex) { + + // The barrier should not be broken. + assertFalse("barrier broke with timeout.", b.isBroken()); + + } + + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-15 18:35:29
|
Revision: 7129 http://bigdata.svn.sourceforge.net/bigdata/?rev=7129&view=rev Author: thompsonbry Date: 2013-05-15 18:35:21 +0000 (Wed, 15 May 2013) Log Message: ----------- 1. Bug in QuorumCommitImpl.prepare2Phase(). Fixed in rXXXX. 2. Modified InnerJournalTransactionService.messageFollowers() to monitor the quorum state and break the barrier if the service is no longer the leader or if any of the joined services (as of the atomic decision made by commitNow()) are no longer joined with the met quorum. This fixes some holes that were opened by the use of CyclicBarrier.await(timeout,unit). That method (contrary to its javadoc) will break the barrier if the request times out. 3. Modified InnerJournalTransactionService to close several potential holes where a follower might not message the leader and the leader could remain blocked at the barrier. The HA CI test suite is green. See https://sourceforge.net/apps/trac/bigdata/ticket/673 (DGC in release time consensus protocol causes native thread leak in HAJournalServer at each commit) See https://sourceforge.net/apps/trac/bigdata/ticket/530 (Journal HA) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java 2013-05-15 16:20:51 UTC (rev 7128) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java 2013-05-15 18:35:21 UTC (rev 7129) @@ -291,7 +291,7 @@ throw new AssertionError("null @ index=" + i); boolean done = false; try { - remaining = nanos - (begin - System.nanoTime()); + remaining = nanos - (System.nanoTime() - begin); final boolean vote = rf .get(remaining, TimeUnit.NANOSECONDS); votes[i] = vote; Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-15 16:20:51 UTC (rev 7128) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2013-05-15 18:35:21 UTC (rev 7129) @@ -2941,6 +2941,8 @@ } catch (Exception ex) { + log.error(ex, ex); + // Wrap and rethrow. throw new RuntimeException(ex); @@ -5462,6 +5464,30 @@ return haReadyToken; } + + /** + * A simplified summary of the HA status of the service. This may be used to + * reliably decide whether the service is the {@link HAStatusEnum#Leader}, a + * {@link HAStatusEnum#Follower}, or {@link HAStatusEnum#NotReady}. This is + * exposed both here (an RMI interface) and by the REST API. + * + * @return The {@link HAStatusEnum} or <code>null</code> if the store is not + * associated with a {@link Quorum}. + * + * @see HAGlue#getHAStatus() + */ + final protected HAStatusEnum getHAStatus() { + + if (quorum == null) { + + // Not HA. + return null; + + } + + return haStatus; + + } /** * Install identical root blocks on the journal. This is used for a few @@ -5854,61 +5880,8 @@ @Override public HAStatusEnum getHAStatus() { - final Quorum<HAGlue, QuorumService<HAGlue>> quorum = getQuorum(); - - if (quorum == null) { - - // Not HA. - return null; - - } - - return haStatus; + return AbstractJournal.this.getHAStatus(); -// final QuorumService<HAGlue> quorumService = quorum.getClient(); -// -// // check, but do not wait. -// final long haReadyToken = AbstractJournal.this.getHAReady(); -// -// final HAStatusEnum status; -// -// if (haReadyToken == Quorum.NO_QUORUM) { -// -// // Quorum is not met (as percieved by the HAJournal). -// status = HAStatusEnum.NotReady; -// -// } else { -// -// if (quorumService.isLeader(haReadyToken)) { -// -// // Service is leader. -// status = HAStatusEnum.Leader; -// -// } else if (quorumService.isFollower(haReadyToken)) { -// -// // Service is follower. -// status = HAStatusEnum.Follower; -// -// } else { -// -// /* -// * awaitHAReady() should only return successfully (and hence -// * haReadyToken should only be a valid token) if the service was -// * elected as either a leader or a follower. However, it is -// * possible for the service to have concurrently left the met -// * quorum, in which case the if/then/else pattern will fall -// * through to this code path. -// */ -// -// // Quorum is not met (as percieved by the HAJournal). -// status = HAStatusEnum.NotReady; -// -// } -// -// } -// -// return status; - } @Override @@ -6919,6 +6892,9 @@ public void gatherMinimumVisibleCommitTime( final IHAGatherReleaseTimeRequest req) throws IOException { + if (haLog.isInfoEnabled()) + haLog.info("req=" + req); + // Clear the old outcome. gatherFuture.set(null); @@ -6929,7 +6905,9 @@ final FutureTask<Void> ft = new FutureTask<Void>(task); + // Save reference to the gather Future. gatherFuture.set(ft); + // Fire and forget. The Future is checked by prepare2Phase. getExecutorService().execute(ft); Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-15 16:20:51 UTC (rev 7128) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/Journal.java 2013-05-15 18:35:21 UTC (rev 7129) @@ -95,6 +95,7 @@ import com.bigdata.sparse.GlobalRowStoreHelper; import com.bigdata.sparse.SparseRowStore; import com.bigdata.util.ClocksNotSynchronizedException; +import com.bigdata.util.InnerCause; import com.bigdata.util.concurrent.DaemonThreadFactory; import com.bigdata.util.concurrent.LatchedExecutor; import com.bigdata.util.concurrent.ShutdownHelper; @@ -315,10 +316,11 @@ /** * The token that must remain valid. * - * TODO We should also verify that the responses we collect are for the - * same request. This could be done using a request UUID or one-up - * request counter. That would guard against having a service reconnect - * and respond late once the leader had gotten to another commit point. + * TODO HA TXS: We should also verify that the responses we collect are + * for the same request. This could be done using a request UUID or + * one-up request counter. That would guard against having a service + * reconnect and respond late once the leader had gotten to another + * commit point. */ final private long token; @@ -450,8 +452,8 @@ @Override public void run() { - if (log.isTraceEnabled()) - log.trace("leader: " + leadersValue); + if (log.isInfoEnabled()) + log.info("leader: " + leadersValue); // This is the timestamp from the BarrierState ctor. final long timeLeader = leadersValue.getTimestamp(); @@ -484,8 +486,8 @@ minimumResponse.getPinnedCommitTime(), minimumResponse.getPinnedCommitCounter()); - if (log.isTraceEnabled()) - log.trace("consensus: " + consensus); + if (log.isInfoEnabled()) + log.info("consensus: " + consensus); } @@ -600,16 +602,106 @@ // } // } // } + +// spinWaitBarrier(getQuorum(), barrier, token, timeout, units); - try { - barrier.await(timeout, units); - // fall through. - } catch (TimeoutException e) { - throw e; - } catch (InterruptedException e) { - throw e; - } catch (BrokenBarrierException e) { - throw e; + /* + * This sets up a task that will monitor the quorum state and + * then interrupt this Thread if it is blocked at the barrier + * [actually, it uses barrier.reset(), which appears to be a + * litle safer]. + * + * If this service is no longer the quorum leader or if any of + * the services leave that were joined with the met quorum when + * we started the release time consensus protocol, then we have + * to reset() the barrier. We achieve this by interrupting the + * Thread (actually it now uses barrier.reset()). + * + * Note: CyclicBarrier.await(timeout,unit) causes the barrier to + * break if the timeout is exceeded. Therefore is CAN NOT be + * used in preference to this pattern. + */ + { +// final Thread blockedAtBarrier = Thread.currentThread(); + + final Quorum<HAGlue, QuorumService<HAGlue>> quorum = getQuorum(); + + final long initialDelay = 100; // milliseconds. + final long delay = initialDelay; + + final ScheduledFuture<?> scheduledFuture = scheduledExecutorService + .scheduleWithFixedDelay(new Runnable() { + public void run() { + try { + + // Verify service is still leader. + quorum.assertLeader(token); + + // Verify service self-recognizes as leader. + if (getHAStatus() != HAStatusEnum.Leader) { + + throw new QuorumException(); + + } + + // Verify messaged services still + // joined. + assertServicesStillJoined(quorum); + + } catch (QuorumException ex) { + + if (!barrier.isBroken()) { + + barrier.reset(); + + } + + } catch (RuntimeException ex) { + + if (InnerCause.isInnerCause(ex, + InterruptedException.class)) { + + // Normal termination. + return; + + } + + /* + * Something went wrong in the + * monitoring code. + */ + + log.error(ex, ex); + + if (!barrier.isBroken()) { + + /* + * Force the barrier to break since + * we will no longer be monitoring + * the quorum state. + */ + barrier.reset(); + + } + + } + + } + }, initialDelay, delay, TimeUnit.MILLISECONDS); + + try { + + /* + * Throws InterruptedException, BrokenBarrierException. + */ + barrier.await(); + + } finally { + + scheduledFuture.cancel(true/* mayInterruptIfRunning */); + + } + } // /* @@ -671,7 +763,143 @@ }// finally } + +// /** +// * Wait on the {@link CyclicBarrier}, but do this in a loop so we can +// * watch for a quorum break or service leave. +// * +// * @param quorum +// * @param barrier +// * @param timeout +// * @param units +// * +// * @throws BrokenBarrierException +// * @throws InterruptedException +// * @throws TimeoutException +// */ +// private void spinWaitBarrier( +// final Quorum<HAGlue, QuorumService<HAGlue>> quorum, +// final CyclicBarrier barrier, final long token, +// final long timeout, final TimeUnit unit) +// throws BrokenBarrierException, InterruptedException, +// TimeoutException { +// +// if (log.isInfoEnabled()) +// log.info("Waiting at barrier: #parties=" + barrier.getParties() +// + ", #waiting=" + barrier.getNumberWaiting() +// + ", isBroken=" + barrier.isBroken() + ", token=" +// + token + ", timeout=" + timeout + ", unit=" + unit); +// +// // How lock to block in each iteration. +// final long blockNanos = TimeUnit.MILLISECONDS.toNanos(10000); +// +// final long begin = System.nanoTime(); +// final long nanos = unit.toNanos(timeout); +// long remaining = nanos; +// long nspin = 0L; +// +// try { +// +// while (remaining > 0) { +// +// nspin++; +// +// remaining = nanos - (System.nanoTime() - begin); +// +// try { +// +// // Verify that this service remains the leader. +// quorum.assertLeader(token); +// +// // Verify messaged services are still joined. +// assertServicesStillJoined(quorum); +// +// /* +// * If we observe a serviceLeave for any service that we +// * are awaiting, then we need to stop waiting on that +// * service. This could be achieved by running a Thread +// * that did a barrier.await() on the behalf of that +// * service, but only if that service has not yet +// * responded with its input for the consensus protocol +// * [if it has responded then it is probably already at +// * barrier.await() in a Thread on the leader for that +// * follower.] +// */ +// final long awaitNanos = Math.min(blockNanos, remaining); +// +// /* +// * Await barrier, up to the timeout. +// * +// * Note: Contrary to the javadoc, barrier.await(timeout) +// * will break the barrier if the timeout is exceeded!!! +// */ +// barrier.await(awaitNanos, TimeUnit.NANOSECONDS); +// +// // Done. +// return; +// +// } catch (TimeoutException e) { +// // Spin. +// continue; +// } catch (InterruptedException e) { +// throw e; +// } catch (BrokenBarrierException e) { +// throw e; +// } +// +// } +// +// } finally { +// +// /* +// * Note: On exit, the caller must reset() the barrier if it is +// * not yet broken. +// */ +// +// if (log.isInfoEnabled()) +// log.info("barrier: #parties=" + barrier.getParties() +// + ", #waiting=" + barrier.getNumberWaiting() +// + ", isBroken=" + barrier.isBroken() + ", #spin=" +// + nspin); +// +// } +// +// } + /** + * Verify that the services that were messaged for the release time + * consensus protocol are still joined with the met quorum. + * + * @throws QuorumException + * if one of the joined services leaves. + */ + private void assertServicesStillJoined( + final Quorum<HAGlue, QuorumService<HAGlue>> quorum) + throws QuorumException { + + final UUID[] tmp = quorum.getJoined(); + + for (UUID serviceId : joinedServiceIds) { + + boolean found = false; + for (UUID t : tmp) { + if (serviceId.equals(t)) { + found = true; + break; + } + } + if (!found) { + + throw new QuorumException( + "Service leave during consensus protocol: " + + serviceId); + + } + + } + + } + } // /** @@ -835,7 +1063,7 @@ /* * Message the followers and block until the barrier breaks. */ - barrierState.messageFollowers(token,timeout,units); + barrierState.messageFollowers(token, timeout, units); } finally { @@ -852,10 +1080,17 @@ /* * Update the release time on the leader */ + + final IHANotifyReleaseTimeResponse consensus = barrierState.consensus; - final long consensusValue = barrierState.consensus - .getCommitTime(); + if (consensus == null) { + throw new RuntimeException("No consensus"); + + } + + final long consensusValue = consensus.getCommitTime(); + final long newReleaseTime = Math.max(0L, consensusValue - 1); if (log.isInfoEnabled()) @@ -1075,18 +1310,26 @@ } public Void call() throws Exception { - - final long now = nextTimestamp(); - // Verify event on leader occurs before event on follower. - assertBefore(req.getTimestampOnLeader(), now); + if (log.isInfoEnabled()) + log.info("Running gather on follower: " + getServiceUUID()); - final long token = req.token(); - + HAGlue leader = null; + + boolean didNotifyLeader = false; + barrierLock.lock(); // take lock on follower! try { + // This timestamp is used to help detect clock skew. + final long now = nextTimestamp(); + + // Verify event on leader occurs before event on follower. + assertBefore(req.getTimestampOnLeader(), now); + + final long token = req.token(); + getQuorum().assertQuorum(token); final QuorumService<HAGlue> quorumService = getQuorum() @@ -1095,7 +1338,7 @@ if (!quorumService.isFollower(token)) throw new QuorumException(); - final HAGlue leader = quorumService.getLeader(token); + leader = quorumService.getLeader(token); final IHANotifyReleaseTimeRequest req2 = newHANotifyReleaseTimeRequest(quorumService .getServiceId()); @@ -1105,6 +1348,9 @@ * * Note: Will block until barrier breaks on the leader. */ + + didNotifyLeader = true; + final IHANotifyReleaseTimeResponse consensusReleaseTime = leader .notifyEarliestCommitTime(req2); @@ -1142,7 +1388,7 @@ */ throw new AssertionError( - "The releaseTime consensus would release an in use commit point" + "The releaseTime consensus would release a commit point with active readers" + ": consensus=" + consensusReleaseTime + ", earliestActiveTx=" + txState); @@ -1166,7 +1412,28 @@ // Done. return null; + + } catch (Throwable t) { + log.error(t, t); + + if (!didNotifyLeader && leader != null) { + + /* + * Send a [null] to the leader so it does not block + * forever waiting for our response. + */ + + try { + leader.notifyEarliestCommitTime(null/* resp */); + } catch (Throwable t2) { + log.error(t2, t2); + } + + } + + throw new Exception(t); + } finally { barrierLock.unlock(); @@ -1180,7 +1447,7 @@ /** * {@inheritDoc} * <p> - * Note: Message sent by follower. Method executes on leader. + * Note: Message sent by follower (RMI). Method executes on leader. * <p> * We pass the message through to the {@link BarrierState} object. * <p> @@ -1188,10 +1455,12 @@ * lock is held by the Thread that invoked * {@link #updateReleaseTimeConsensus()}. * - * TODO We should ensure that the [req] is for the same gather() request - * as this barrier instance. That will let us detect a service that - * responds late (after a transient disconnect) when the leader has + * TODO HA TXS: We should ensure that the [req] is for the same gather() + * request as this barrier instance. That will let us detect a service + * that responds late (after a transient disconnect) when the leader has * moved on to another commit. See BarrierState#token for more on this. + * [Note that [req] can be [null if the follower was unable to produce a + * valid response.] */ @Override public IHANotifyReleaseTimeResponse notifyEarliestCommitTime( @@ -1203,23 +1472,40 @@ if (barrierState == null) throw new IllegalStateException(); - getQuorum().assertLeader(barrierState.token); + try { - // ServiceId of the follower. - final UUID followerId = req.getServiceUUID(); - - // Make a note of the message from this follower. - barrierState.responses.put(followerId, req); - - // Block until barrier breaks. - barrierState.barrier.await(); + getQuorum().assertLeader(barrierState.token); + // ServiceId of the follower (NPE if req is null). + final UUID followerId = req.getServiceUUID(); + + // Make a note of the message from this follower. + barrierState.responses.put(followerId, req); + + } finally { + + /* + * Block until barrier breaks. + * + * Note: We want to await() on the barrier even if there is an + * error in the try{} block. This is necessary to decrement the + * barrier count down to zero. + */ + + // follower blocks on Thread on the leader here. + barrierState.barrier.await(); + + } + // Return the consensus. final IHANotifyReleaseTimeResponse resp = barrierState.consensus; - if (resp == null) - throw new AssertionError(); + if (resp == null) { + throw new RuntimeException("No consensus"); + + } + return resp; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-15 16:20:58
|
Revision: 7128 http://bigdata.svn.sourceforge.net/bigdata/?rev=7128&view=rev Author: thompsonbry Date: 2013-05-15 16:20:51 +0000 (Wed, 15 May 2013) Log Message: ----------- Bug fix for broken commit. This included a fileLock.close() invocation that is apparently not available in JDK 1.6. I've commented out the code since it was conditionally disabled (by if(false)). Modified Paths: -------------- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java Modified: branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java =================================================================== --- branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java 2013-05-15 14:32:20 UTC (rev 7127) +++ branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java 2013-05-15 16:20:51 UTC (rev 7128) @@ -966,80 +966,80 @@ * at com.bigdata.journal.jini.ha.HAJournalServer.main(HAJournalServer.java:3602) * </pre> */ - if(false) - assertCondition(new Runnable() { - public void run() { - try { - - final File lockFile = new File(serviceDir, ".lock"); - - if (!lockFile.exists()) { - - // Lock file is gone. - return; - - } +// if(false) +// assertCondition(new Runnable() { +// public void run() { +// try { +// +// final File lockFile = new File(serviceDir, ".lock"); +// +// if (!lockFile.exists()) { +// +// // Lock file is gone. +// return; +// +// } +// +// RandomAccessFile lockFileRAF = new RandomAccessFile( +// lockFile, "rw"); +// FileLock fileLock = null; +// try { +// +// fileLock = lockFileRAF.getChannel().tryLock(); +// +// if (fileLock == null) { +// +// /* +// * Note: A null return indicates that someone else +// * holds the lock. +// */ +// +// try { +// lockFileRAF.close(); +// } catch (Throwable t) { +// // ignore. +// } finally { +// lockFileRAF = null; +// } +// +// throw new RuntimeException( +// "Service still running: file=" + lockFile); +// +// } +// +// } catch (IOException ex) { +// +// /* +// * Note: This is true of NFS volumes. +// */ +// +// log.warn("FileLock not supported: file=" + lockFile, ex); +// +// } finally { +// if (fileLock != null) { +// try { +// fileLock.close(); +// } finally { +// fileLock = null; +// } +// } +// if (lockFileRAF != null) { +// try { +// lockFileRAF.close(); +// } finally { +// lockFileRAF = null; +// } +// } +// } +// +// fail();// lock file still exists or is still locked. +// } catch (IOException e) { +// // Service is down. +// return; +// } +// } +// }); - RandomAccessFile lockFileRAF = new RandomAccessFile( - lockFile, "rw"); - FileLock fileLock = null; - try { - - fileLock = lockFileRAF.getChannel().tryLock(); - - if (fileLock == null) { - - /* - * Note: A null return indicates that someone else - * holds the lock. - */ - - try { - lockFileRAF.close(); - } catch (Throwable t) { - // ignore. - } finally { - lockFileRAF = null; - } - - throw new RuntimeException( - "Service still running: file=" + lockFile); - - } - - } catch (IOException ex) { - - /* - * Note: This is true of NFS volumes. - */ - - log.warn("FileLock not supported: file=" + lockFile, ex); - - } finally { - if (fileLock != null) { - try { - fileLock.close(); - } finally { - fileLock = null; - } - } - if (lockFileRAF != null) { - try { - lockFileRAF.close(); - } finally { - lockFileRAF = null; - } - } - } - - fail();// lock file still exists or is still locked. - } catch (IOException e) { - // Service is down. - return; - } - } - }); - } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2013-05-15 14:32:32
|
Revision: 7127 http://bigdata.svn.sourceforge.net/bigdata/?rev=7127&view=rev Author: thompsonbry Date: 2013-05-15 14:32:20 +0000 (Wed, 15 May 2013) Log Message: ----------- {{{ 1. Added a unit test for the 2-phase commit where the 1st follower votes "NO". To do this I subclassed HAJournal and HAGlueService. We plan to add more such tests to investigate different failure modes and how the HA cluster performs under those failure modes. 2. Refactored QuorumCommit and QuorumCommitImpl. These are the local implementation that the leader uses to coordinate a distributed 2-phase commit. The arguments were encapsulated in helper objects. This refactoring also includes a semantics change. The QuorumCommitImpl now reports for each service whether it voted YES or NO for the prepare. The commit2Phase() method now only messages the services that voted YES. (I am looking at how to do the same thing for abort2Phase(), but that method is also invoked from abort() and not just in commitNow() so we do not always have the necessary joined[] available, though one could be created for this purpose). 3. Modified the default timeouts for PREPARE and the release time consensus protocol to Long.MAX_VALUE. This is being done in an attempt to track down some odd behaviors on the HA3 cluster for BSBM UPDATE (on leader) + EXPLORE (on follower). If an RMI can not succeed then it will eventually fail anyway. 4. ClientFuture was modified to cache locally when it knows that the remote Future is done. This helps to reduce RMI calls during code snips such as if(!ft.isDone()) ft.cancel(true); 5. Added the current root block to the data reported by /status for HA. This makes it possible to inspect the root blocks on each service to verify that they are consistent. 6. Refactored how AbstractHA3JournalServerTestCase discloses the serviceDir for each HAJournalServer process. I have also stubbed in some code that we might use to verify that the .lock file has been released in awaitServiceGone(). }}} HA CI is green locally with this change set. See https://sourceforge.net/apps/trac/bigdata/ticket/530 (Journal HA) Modified Paths: -------------- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommit.java branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumPipelineImpl.java branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumServiceBase.java branches/READ_CACHE/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/READ_CACHE/bigdata/src/java/com/bigdata/service/proxy/ClientFuture.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournal.java branches/READ_CACHE/bigdata-jini/src/java/com/bigdata/journal/jini/ha/HAJournalServer.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/AbstractHA3JournalServerTestCase.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/HAJournalTest.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestAll.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHA3JournalServer.java branches/READ_CACHE/bigdata-jini/src/test/com/bigdata/journal/jini/ha/TestHAJournalServerOverride.java branches/READ_CACHE/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/HAStatusServletUtil.java Added Paths: ----------- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/CommitRequest.java branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/PrepareRequest.java branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/PrepareResponse.java Added: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/CommitRequest.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/CommitRequest.java (rev 0) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/CommitRequest.java 2013-05-15 14:32:20 UTC (rev 7127) @@ -0,0 +1,84 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Jun 13, 2010 + */ +package com.bigdata.ha; + +/** + * Commit request for a 2-phase commit as coodinated by the leader (local + * object). + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class CommitRequest { + + private final PrepareRequest prepareRequest; + private final PrepareResponse prepareResponse; + + /** + * The request used for the PREPARE. + */ + public PrepareRequest getPrepareRequest() { + return prepareRequest; + } + + /** + * The response for the PREPARE. This indicates which services voted to + * commit and which did not. + */ + public PrepareResponse getPrepareResponse() { + return prepareResponse; + } + + /** + * + * @param prepareRequest + * The request used for the PREPARE. + * @param prepareResponse + * The response for the PREPARE. This indicates which services + * voted to commit and which did not. + */ + public CommitRequest(final PrepareRequest prepareRequest, + final PrepareResponse prepareResponse) { + + if (prepareRequest == null) + throw new IllegalArgumentException(); + + if (prepareResponse == null) + throw new IllegalArgumentException(); + + this.prepareRequest = prepareRequest; + this.prepareResponse = prepareResponse; + } + + @Override + public String toString() { + + return super.toString() + "{req=" + prepareRequest + ", resp=" + + prepareResponse + "}"; + + } + +} Added: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/PrepareRequest.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/PrepareRequest.java (rev 0) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/PrepareRequest.java 2013-05-15 14:32:20 UTC (rev 7127) @@ -0,0 +1,114 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Jun 13, 2010 + */ +package com.bigdata.ha; + +import java.util.Arrays; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import com.bigdata.journal.IRootBlockView; + +/** + * A 2-phase request as coordinated by the leader (local object). + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class PrepareRequest { + + private final UUID[] joinedServiceIds; + private final Set<UUID> nonJoinedPipelineServiceIds; + private final IRootBlockView rootBlock; + private final long timeout; + private final TimeUnit unit; + + public UUID[] getJoinedServiceIds() { + return joinedServiceIds; + } + + public Set<UUID> getNonJoinedPipelineServiceIds() { + return nonJoinedPipelineServiceIds; + } + + public IRootBlockView getRootBlock() { + return rootBlock; + } + + public long getTimeout() { + return timeout; + } + + public TimeUnit getUnit() { + return unit; + } + + /** + * + * @param joinedServiceIds + * The services joined with the met quorum, in their join order. + * @param nonJoinedPipelineServiceIds + * The non-joined services in the write pipeline (in any order). + * @param isRootBlock0 + * if this is rootBlock0. + * @param rootBlock + * The new root block. + * @param timeout + * How long to wait for the other services to prepare. + * @param unit + * The unit for the timeout. + */ + public PrepareRequest( + final UUID[] joinedServiceIds, // + final Set<UUID> nonJoinedPipelineServiceIds,// + final IRootBlockView rootBlock, final long timeout, + final TimeUnit unit) { + + if (rootBlock == null) + throw new IllegalArgumentException(); + + if (unit == null) + throw new IllegalArgumentException(); + + this.joinedServiceIds = joinedServiceIds; + this.nonJoinedPipelineServiceIds = nonJoinedPipelineServiceIds; + this.rootBlock = rootBlock; + this.timeout = timeout; + this.unit = unit; + } + + @Override + public String toString() { + return super.toString() + "{isRootBlock0=" + rootBlock.isRootBlock0() + + ", rootBlock=" + rootBlock + ", #joined=" + + joinedServiceIds.length + ", #nonJoined=" + + nonJoinedPipelineServiceIds.size() + ", joinedServices=" + + Arrays.toString(joinedServiceIds) + ", nonJoined=" + + nonJoinedPipelineServiceIds + ", timeout=" + timeout + + ", unit=" + unit + "}"; + } + +} Added: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/PrepareResponse.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/PrepareResponse.java (rev 0) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/PrepareResponse.java 2013-05-15 14:32:20 UTC (rev 7127) @@ -0,0 +1,107 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Jun 13, 2010 + */ +package com.bigdata.ha; + +import cern.colt.Arrays; + + +/** + * The 2-phase prepare outcome as coordinated by the leader. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class PrepareResponse { + + private final int k; + private final int nyes; + private final boolean willCommit; + private final boolean[] votes; + + /** + * The replication factor for the quorum. + */ + public int replicationFactor() { + return k; + } + + /** + * Return the #of services that voted "YES". + */ + public int getYesCount() { + return nyes; + } + + /** + * Return <code>true</code> iff the transaction will commit based on the + * responses to the prepare requests. + */ + public boolean willCommit() { + return willCommit; + } + + public boolean getVote(final int index) { + + return votes[index]; + + } + + /** + * + * @param k + * The replication factor for the quorum. + * @param nyes + * The #of YES votes. + * @param willCommit + * <code>true</code> iff the transaction will commit based on the + * responses to the prepare requests. + */ + public PrepareResponse(final int k, final int nyes, + final boolean willCommit, final boolean[] votes) { + + if (k < 1) + throw new IllegalArgumentException(); + + if (nyes > k) + throw new IllegalArgumentException(); + + this.k = k; + this.nyes = nyes; + this.willCommit = willCommit; + this.votes = votes; + + } + + @Override + public String toString() { + + return super.toString() + "{k=" + k + ", nyes=" + nyes + + ", willCommit=" + willCommit + ", votes=" + + Arrays.toString(votes) + "}"; + + } + +} Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommit.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommit.java 2013-05-15 11:55:06 UTC (rev 7126) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommit.java 2013-05-15 14:32:20 UTC (rev 7127) @@ -28,9 +28,6 @@ package com.bigdata.ha; import java.io.IOException; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -58,27 +55,11 @@ * root block for use with the next {@link #commit2Phase(long, long) commit} * message. * - * @param joinedServiceIds - * The services joined with the met quorum, in their join order. - * @param nonJoinedPipelineServiceIds - * The non-joined services in the write pipeline (in any order). - * @param isRootBlock0 - * if this is rootBlock0. - * @param rootBlock - * The new root block. - * @param timeout - * How long to wait for the other services to prepare. - * @param unit - * The unit for the timeout. - * - * @return A {@link Future} which evaluates to a yes/no vote on whether the - * service is prepared to commit. + * @return The outcome of the distributed PREPARE request, indicating + * whether each service is prepared to commit. */ - int prepare2Phase(final UUID[] joinedServiceIds, // - final Set<UUID> nonJoinedPipelineServiceIds,// - final IRootBlockView rootBlock, final long timeout, - final TimeUnit unit) throws InterruptedException, TimeoutException, - IOException; + PrepareResponse prepare2Phase(PrepareRequest req) + throws InterruptedException, TimeoutException, IOException; /** * Used by the leader to send a message to each joined service in the quorum @@ -87,20 +68,8 @@ * The commit MAY NOT go forward unless both the current quorum token and * the lastCommitTime on this message agree with the quorum token and * lastCommitTime in the root block from the last "prepare" message. - * - * @param joinedServiceIds - * The services joined with the met quorum, in their join order. - * @param nonJoinedPipelineServiceIds - * The non-joined services in the write pipeline (in any order). - * @param token - * The quorum token used in the prepare message. - * @param commitTime - * The commit time that assigned to the new commit point. */ - void commit2Phase( - final UUID[] joinedServiceIds, // - final Set<UUID> nonJoinedPipelineServiceIds, long token, - long commitTime) throws IOException, InterruptedException; + void commit2Phase(CommitRequest req) throws IOException, InterruptedException; /** * Used by the leader to send a message to each service joined with the Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java 2013-05-15 11:55:06 UTC (rev 7126) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumCommitImpl.java 2013-05-15 14:32:20 UTC (rev 7127) @@ -25,11 +25,10 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.LinkedList; import java.util.List; -import java.util.Set; import java.util.UUID; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -139,30 +138,23 @@ * from the prepare message. This metadata is used to decide how the service * will handle the prepare, commit, and abort messages. */ - public int prepare2Phase(// - final UUID[] joinedServiceIds, // - final Set<UUID> nonJoinedPipelineServiceIds,// - final IRootBlockView rootBlock,// - final long timeout, final TimeUnit unit// - ) - throws InterruptedException, TimeoutException, IOException { + public PrepareResponse prepare2Phase(final PrepareRequest req) + throws InterruptedException, IOException { - if (rootBlock == null) - throw new IllegalArgumentException(); + if (log.isInfoEnabled()) + log.info("req=" + req); - if (unit == null) - throw new IllegalArgumentException(); + final IRootBlockView rootBlock = req.getRootBlock(); + + final UUID[] joinedServiceIds = req.getJoinedServiceIds(); - final boolean isRootBlock0 = rootBlock.isRootBlock0(); - - if (log.isInfoEnabled()) - log.info("isRootBlock0=" + isRootBlock0 + ", rootBlock=" - + rootBlock + ", #joined=" + joinedServiceIds.length - + ", #nonJoined=" + nonJoinedPipelineServiceIds.size() - + ", joinedServices=" + Arrays.toString(joinedServiceIds) - + ", nonJoined=" + nonJoinedPipelineServiceIds - + ", timeout=" + timeout + ", unit=" + unit); - +// final Set<UUID> nonJoinedPipelineServiceIds = req +// .getNonJoinedPipelineServiceIds(); + + final long timeout = req.getTimeout(); + + final TimeUnit unit = req.getUnit(); + /* * The token of the quorum for which the leader issued this prepare * message. @@ -187,12 +179,12 @@ // #of remote followers (joined services, excluding the leader). final int nfollowers = (joinedServiceIds.length - 1); - // #of non-joined services in the pipeline. - final int nNonJoinedPipelineServices = nonJoinedPipelineServiceIds - .size(); +// // #of non-joined services in the pipeline. +// final int nNonJoinedPipelineServices = nonJoinedPipelineServiceIds +// .size(); // #of remote services (followers plus others in the pipeline). - final int remoteServiceCount = nfollowers + nNonJoinedPipelineServices; + final int remoteServiceCount = nfollowers;// + nNonJoinedPipelineServices; // Random access list of futures. final ArrayList<Future<Boolean>> remoteFutures = new ArrayList<Future<Boolean>>( @@ -238,30 +230,30 @@ } - // Next, message the pipeline services NOT met with the quorum. - { +// // Next, message the pipeline services NOT met with the quorum. +// { +// +// // message for non-joined services. +// final IHA2PhasePrepareMessage msg = new HA2PhasePrepareMessage( +// false/* isJoinedService */, rootBlock, timeout, unit); +// +// for (UUID serviceId : nonJoinedPipelineServiceIds) { +// +// /* +// * Runnable which will execute this message on the +// * remote service. +// */ +// final Future<Boolean> rf = getService(serviceId) +// .prepare2Phase(msg); +// +// // add to list of futures we will check. +// remoteFutures.set(i, rf); +// +// i++; +// +// } +// } - // message for non-joined services. - final IHA2PhasePrepareMessage msg = new HA2PhasePrepareMessage( - false/* isJoinedService */, rootBlock, timeout, unit); - - for (UUID serviceId : nonJoinedPipelineServiceIds) { - - /* - * Runnable which will execute this message on the - * remote service. - */ - final Future<Boolean> rf = getService(serviceId) - .prepare2Phase(msg); - - // add to list of futures we will check. - remoteFutures.set(i, rf); - - i++; - - } - } - /* * Finally, run the operation on the leader using local method * call (non-RMI) in the caller's thread to avoid deadlock. @@ -292,6 +284,7 @@ */ int nyes = 0; assert remoteFutures.size() == remoteServiceCount + 1; + final boolean[] votes = new boolean[remoteServiceCount + 1]; for (int i = 0; i <= remoteServiceCount; i++) { final Future<Boolean> rf = remoteFutures.get(i); if (rf == null) @@ -301,6 +294,7 @@ remaining = nanos - (begin - System.nanoTime()); final boolean vote = rf .get(remaining, TimeUnit.NANOSECONDS); + votes[i] = vote; if (i < joinedServiceIds.length) { // Only the leader and the followers get a vote. nyes += vote ? 1 : 0; @@ -311,21 +305,27 @@ } } done = true; + } catch (CancellationException ex) { + // This Future was cancelled. + log.error(ex, ex); + done = true; // CancellationException indicates isDone(). + } catch (TimeoutException ex) { + // Timeout on this Future. + log.error(ex, ex); + done = false; } catch (ExecutionException ex) { /* - * TODO prepare2Phase() is throwing exceptions if - * preconditions are violated. Unless if is a joined - * service, it probably should just vote "no" instead. We do - * not need to log @ ERROR when a precondition for a - * non-joined service has been violated. + * Note: prepare2Phase() is throwing exceptions if + * preconditions are violated. These thrown exceptions are + * interpreted as a "NO" vote. */ log.error(ex, ex); - done = true; // Note: ExecutionException indicates isDone(). + done = true; // ExecutionException indicates isDone(). } catch (RuntimeException ex) { /* - * Note: ClientFuture.get() can throw a RuntimeException - * if there is a problem with the RMI call. In this case - * we do not know whether the Future is done. + * Note: ClientFuture.get() can throw a RuntimeException if + * there is a problem with the RMI call. In this case we do + * not know whether the Future is done. */ log.error(ex, ex); } finally { @@ -340,15 +340,26 @@ } } + // The quorum replication factor. final int k = getQuorum().replicationFactor(); - if (!getQuorum().isQuorum(nyes)) { + /* + * Note: The leader MUST vote YES in order for the commit to + * continue. In addition, we need a majority of the joined services. + * In practice, for an HA3 configuration, this means that up to one + * follower could fail and the commit would still go through. + * However, if the leader fails then the commit will fail as well. + */ + final boolean willCommit = votes[0] && getQuorum().isQuorum(nyes); - log.error("prepare rejected: nyes=" + nyes + " out of " + k); + if (!willCommit) { + log.error("prepare rejected: leader=" + votes[0] + ", nyes=" + + nyes + " out of " + k); + } - return nyes; + return new PrepareResponse(k, nyes, willCommit, votes); } finally { /* @@ -370,24 +381,45 @@ } - public void commit2Phase(final UUID[] joinedServiceIds, // - final Set<UUID> nonJoinedPipelineServiceIds,// - final long token, final long commitTime) throws IOException, + public void commit2Phase(final CommitRequest req) throws IOException, InterruptedException { if (log.isInfoEnabled()) - log.info("token=" + token + ", commitTime=" + commitTime - + ", #joined=" + joinedServiceIds.length + ", #nonJoined=" - + nonJoinedPipelineServiceIds.size() + ", joinedServices=" - + Arrays.toString(joinedServiceIds) + ", nonJoined=" - + nonJoinedPipelineServiceIds); + log.info("req=" + req); /* * To minimize latency, we first submit the futures for the other * services and then do f.run() on the leader. This will allow the other * services to commit concurrently with the leader's IO. + * + * Note: Only services that voted "YES" will get a commit2Phase message. + * + * Note: Do NOT message the services that voted NO. [At one point the + * code was modified to message each joined and non-joined service. That + * change was introduced to support services that join during the + * 2-phase commit. However, we have since resolved the service join by + * relying on the service blocking the pipeline writes in + * handleReplicatedWrite(). Since we can reliably know that there will + * not be a concurrent commit, we can atomically join an existing quorum + * and we do not need to make the 2-phase commit protocol visible to the + * non-joined services. Thus we do not need to push the 2-phase commit + * protocol to a service that is not joined with the met quorum at the + * atomic decision point concerning such things in commitNow().] */ + + final PrepareRequest preq = req.getPrepareRequest(); + final UUID[] joinedServiceIds = preq.getJoinedServiceIds(); + +// final Set<UUID> nonJoinedPipelineServiceIds = preq +// .getNonJoinedPipelineServiceIds(); + + final long token = preq.getRootBlock().getQuorumToken(); + + final long commitTime = preq.getRootBlock().getLastCommitTime(); + + final PrepareResponse presp = req.getPrepareResponse(); + member.assertLeader(token); final List<Future<Void>> remoteFutures = new LinkedList<Future<Void>>(); @@ -401,6 +433,13 @@ final UUID serviceId = joinedServiceIds[i]; + if (!presp.getVote(i)) { + + // Skip services that did not vote YES in PREPARE. + continue; + + } + /* * Runnable which will execute this message on the remote * service. @@ -413,27 +452,27 @@ } - if (!nonJoinedPipelineServiceIds.isEmpty()) { +// if (!nonJoinedPipelineServiceIds.isEmpty()) { +// +// final IHA2PhaseCommitMessage msgNonJoinedService = new HA2PhaseCommitMessage( +// false/* isJoinedService */, commitTime); +// +// for (UUID serviceId : nonJoinedPipelineServiceIds) { +// +// /* +// * Runnable which will execute this message on the remote +// * service. +// */ +// final Future<Void> rf = getService(serviceId).commit2Phase( +// msgNonJoinedService); +// +// // add to list of futures we will check. +// remoteFutures.add(rf); +// +// } +// +// } - final IHA2PhaseCommitMessage msgNonJoinedService = new HA2PhaseCommitMessage( - false/* isJoinedService */, commitTime); - - for (UUID serviceId : nonJoinedPipelineServiceIds) { - - /* - * Runnable which will execute this message on the remote - * service. - */ - final Future<Void> rf = getService(serviceId).commit2Phase( - msgNonJoinedService); - - // add to list of futures we will check. - remoteFutures.add(rf); - - } - - } - { /* * Run the operation on the leader using local method call in @@ -455,11 +494,18 @@ for (Future<Void> rf : remoteFutures) { boolean done = false; try { - rf.get(); + rf.get(); // TODO Timeout to await followers in commit2Phase(). done = true; - } catch (InterruptedException ex) { +// } catch (TimeoutException ex) { +// // Timeout on this Future. +// log.error(ex, ex); +// causes.add(ex); +// done = false; + } catch (CancellationException ex) { + // Future was cancelled. log.error(ex, ex); causes.add(ex); + done = true; // Future is done since cancelled. } catch (ExecutionException ex) { log.error(ex, ex); causes.add(ex); @@ -486,9 +532,6 @@ /* * If there were any errors, then throw an exception listing them. - * - * FIXME But only throw the exception if the errors were for a joined - * service. Otherwise just log. */ if (!causes.isEmpty()) { // Cancel remote futures. @@ -518,6 +561,11 @@ } + /** + * FIXME Only issue abort to services that voted YES in prepare? [We have + * that information in commitNow(), but we do not have the atomic set of + * joined services in AbstractJournal.abort())]. + */ public void abort2Phase(final long token) throws IOException, InterruptedException { Modified: branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumPipelineImpl.java =================================================================== --- branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumPipelineImpl.java 2013-05-15 11:55:06 UTC (rev 7126) +++ branches/READ_CACHE/bigdata/src/java/com/bigdata/ha/QuorumPipelineImpl.java 2013-05-15 14:32:20 UTC (rev 7127) @@ -1,1442 +1,1557 @@ -/** - -Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. - -Contact: - SYSTAP, LLC - 4501 Tower Road - Greensboro, NC 27410 - lic...@bi... - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -package com.bigdata.ha; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; -import java.util.concurrent.RunnableFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.apache.log4j.Logger; - -import com.bigdata.ha.msg.HAWriteMessageBase; -import com.bigdata.ha.msg.IHALogRequest; -import com.bigdata.ha.msg.IHAMessage; -import com.bigdata.ha.msg.IHASyncRequest; -import com.bigdata.ha.msg.IHAWriteMessage; -import com.bigdata.ha.pipeline.HAReceiveService; -import com.bigdata.ha.pipeline.HAReceiveService.IHAReceiveCallback; -import com.bigdata.ha.pipeline.HASendService; -import com.bigdata.io.DirectBufferPool; -import com.bigdata.io.IBufferAccess; -import com.bigdata.io.writecache.WriteCache; -import com.bigdata.quorum.Quorum; -import com.bigdata.quorum.QuorumException; -import com.bigdata.quorum.QuorumMember; -import com.bigdata.quorum.QuorumStateChangeListener; -import com.bigdata.quorum.QuorumStateChangeListenerBase; -import com.bigdata.util.InnerCause; - -/** - * {@link QuorumPipeline} implementation. - * <p> - * The {@link QuorumMember} must pass along the "pipeline" messages, including: - * <ul> - * <li>{@link QuorumMember#pipelineAdd()}</li> - * <li>{@link QuorumMember#pipelineRemove()}</li> - * <li>{@link QuorumMember#pipelineChange(UUID, UUID)}</li> - * </ul> - * When a quorum is met, the <i>leader</i> is always first in the write pipeline - * since it is the node which receives writes from clients. When a service joins - * the write pipeline, it always does so at the end of the chain. Services may - * enter the write pipeline before joining a quorum in order to synchronize with - * the quorum. If a service in the middle of the chain leaves the pipeline, then - * the upstream node will reconfigure and retransmit the current cache block to - * its new downstream node. This prevent nodes which are "bouncing" during - * synchronization from causing write sets to be discarded. However, if the - * leader leaves the write pipeline, then the quorum is broken and the write set - * will be discarded. - * <p> - * Since the write pipeline is used to synchronize services trying to join the - * quorum as well as the replicate writes for services joined with the quorum, - * {@link HAReceiveService} may be live for a met quorum even though the - * {@link QuorumMember} on whose behalf this class is acting is not joined with - * the met quorum. - * - * <h3>Pipeline maintenance</h3> - * - * There are three broad categories which have to be handled: (1) leader leaves; - * (2) pipeline leader election; and (3) follower leaves. A leader leave causes - * the quorum to break, which will cause service leaves and pipeline leaves for - * all joined services. However, services must add themselves to the pipeline - * before they join the quorum and the pipeline will be reorganized if necessary - * when the quorum leader is elected. This will result in a - * {@link #pipelineElectedLeader()} event. A follower leave only causes the - * follower to leave the pipeline and results in a - * {@link #pipelineChange(UUID, UUID)} event. - * <p> - * There are two cases for a follower leave: (A) when the follower did not did - * not have a downstream node; and (B) when there is downstream node. For (B), - * the upstream node from the left follower should reconfigure for the new - * downstream node and retransmit the current cache block and the event should - * be otherwise unnoticed. - * <p> - * Handling a follower join requires us to synchronize the follower first which - * requires some more infrastructure and should be done as part of the HA - * synchronization test suite. - * <p> - * What follows is an example of how events will arrive for a quorum of three - * services: A, B, and C. - * - * <pre> - * A.getActor().pipelineAdd() => A.pipelineAdd() - * B.getActor().pipelineAdd() => B.pipelineAdd(); A.pipelineChange(null,B); - * C.getActor().pipelineAdd() => C.pipelineAdd(); B.pipelineChange(null,C); - * </pre> - * - * At this point the pipeline order is <code>[A,B,C]</code>. Notice that the - * {@link HASendService} for A is not established until the - * <code>A.pipelineChange(null,B)</code> sets B as the new downstream service - * for A. Likewise, B will not relay to C until it handles the - * <code>B.pipelineChange(null,C)</code> event. - * - * <p> - * - * Given the pipeline order <code>[A,B,C]</code>, if B were to leave, then the - * events would be: - * - * <pre> - * B.getActor().pipelineRemove() => B.pipelineRemove(); A.pipelineChange(B,C); - * </pre> - * - * and when this class handles the <code>A.pipelineChange(B,C)</code> event, it - * must update the {@link HAReceiveService} such that it now relays data to C. - * - * <p> - * - * On the other hand, given the pipeline order <code>[A,B,C]</code>, if C were - * to leave the events would be: - * - * <pre> - * C.getActor().pipelineRemove() => C.pipelineRemove(); B.pipelineChange(C,null); - * </pre> - * - * and when this class handles the <code>B.pipelineChange(C,null)</code> event, - * it must update the C's {@link HAReceiveService} such that it continues to - * receive data, but no longer relays data to a downstream service. - * - * @author <a href="mailto:tho...@us...">Bryan Thompson</a> - * @version $Id$ - * @param <S> - */ -abstract public class QuorumPipelineImpl<S extends HAPipelineGlue> extends - QuorumStateChangeListenerBase implements QuorumPipeline<S>, - QuorumStateChangeListener { - - static private transient final Logger log = Logger - .getLogger(QuorumPipelineImpl.class); - - /** - * The timeouts for a sleep before the next retry. These timeouts are - * designed to allow some asynchronous processes to reconnect the - * {@link HASendService} and the {@link HAReceiveService}s in write pipeline - * such that a retransmit can succeed after a service has left the pipeline. - * Depending on the nature of the error (i.e., a transient network problem - * versus a pipeline reorganization), this can involve a number of zookeeper - * events. Hence the sleep latency is backed off through this array of - * values. - * - * TODO We do not want to induce too much latency here. It would be nice if - * we automatically retried after each relevant quorum event that might cure - * the problem as well as after a timeout. This would require a Condition - * that we await with a timeout and signaling the Condition if there are any - * relevant events (probably once we handle them locally). - */ - static protected final int RETRY_SLEEP[] = new int[] { 100, 200, 200, 500, 500, 1000 }; - - /** - * The {@link QuorumMember}. - */ - protected final QuorumMember<S> member; - - /** - * The service {@link UUID} for the {@link QuorumMember}. - */ - protected final UUID serviceId; - - /** - * Lock managing the various mutable aspects of the pipeline state. - */ - private final ReentrantLock lock = new ReentrantLock(); - - /** send service (iff this is the leader). */ - private HASendService sendService; - - /** - * The receive service (iff this is a follower in a met quorum). - */ - private HAReceiveService<HAMessageWrapper> receiveService; - - /** - * The buffer used to relay the data. This is only allocated for a - * follower. - */ - private IBufferAccess receiveBuffer; - - /** - * Cached metadata about the downstream service. - */ - private final AtomicReference<PipelineState<S>> pipelineStateRef = new AtomicReference<PipelineState<S>>(); - - public QuorumPipelineImpl(final QuorumMember<S> member) { - - if (member == null) - throw new IllegalArgumentException(); - - this.member = member; - - this.serviceId = member.getServiceId(); - - } - - /** - * Extended to invoke {@link #tearDown()} in order to guarantee the eventual - * release of the {@link #receiveBuffer} and the shutdown of the - * {@link #sendService} or {@link #receiveService}. - */ - @Override - protected void finalize() throws Throwable { - - tearDown(); - - super.finalize(); - - } - - /** - * Return the index at which the given serviceId appears in the array of - * serviceIds. - * - * @param serviceId - * The {@link UUID} of some quorum member. - * @param a - * An array of service {@link UUID}s. - * - * @return The index of the service in the array -or- <code>-1</code> if the - * service does not appear in the array. - */ - private int getIndex(final UUID serviceId, final UUID[] a) { - - if (serviceId == null) - throw new IllegalArgumentException(); - - for (int i = 0; i < a.length; i++) { - - if (serviceId.equals(a[i])) { - - return i; - - } - } - - return -1; - - } - - /** - * Return the NIO buffer used to receive payloads written on the HA write - * pipeline. - * - * @return The buffer -or- <code>null</code> if the pipeline has been torn - * down or if this is the leader. - */ - private ByteBuffer getReceiveBuffer() { - - if (!lock.isHeldByCurrentThread()) { - - // The caller MUST be holding the lock. - throw new IllegalMonitorStateException(); - - } - - // trinary pattern is safe while thread has lock. - return receiveBuffer == null ? null : receiveBuffer.buffer(); - - } - - /** - * Return the {@link HAReceiveService} used to receive payloads written on - * the HA write pipeline. - * - * @return The buffer -or- <code>null</code> if the pipeline has been torn - * down or if this is the leader. - */ - private HAReceiveService<HAMessageWrapper> getHAReceiveService() { - - if (!lock.isHeldByCurrentThread()) { - - // The caller MUST be holding the lock. - throw new IllegalMonitorStateException(); - - } - - return receiveService; - - } - - /** - * Return the {@link HASendService} used to write payloads on the HA write - * pipeline. - * - * @return The {@link HASendService} -or- <code>null</code> if the pipeline - * has been torn down. - */ - private HASendService getHASendService() { - - if (!lock.isHeldByCurrentThread()) { - - // The caller MUST be holding the lock. - throw new IllegalMonitorStateException(); - - } - - return sendService; - - } - - /* - * QuorumStateChangeListener - */ - -// /** -// * Extended to setup this service as a leader ({@link #setUpLeader()}), -// * or a relay ({@link #setUpReceiveAndRelay()}. -// */ -// @Override -// public void quorumMeet(final long token, final UUID leaderId) { -// super.quorumMeet(token, leaderId); -// lock.lock(); -// try { -// this.token = token; -// if(leaderId.equals(serviceId)) { -// setUpLeader(); -// } else if(member.isPipelineMember()) { -// setUpReceiveAndRelay(); -// } -// } finally { -// lock.unlock(); -// } -// } - -// @Override -// public void quorumBreak() { -// super.quorumBreak(); -// lock.lock(); -// try { -// tearDown(); -// } finally { -// lock.unlock(); -// } -// } - - /** - * Sets up the {@link HASendService} or the {@link HAReceiveService} as - * appropriate depending on whether or not this service is the first in the - * pipeline order. - */ - public void pipelineAdd() { - if (log.isInfoEnabled()) - log.info(""); - super.pipelineAdd(); - lock.lock(); - try { - // The current pipeline order. - final UUID[] pipelineOrder = member.getQuorum().getPipeline(); - // The index of this service in the pipeline order. - final int index = getIndex(serviceId, pipelineOrder); - if (index == 0) { - setUpSendService(); - } else - if (index > 0) { - setUpReceiveService(); - } - } finally { - lock.unlock(); - } - } - - public void pipelineElectedLeader() { - if (log.isInfoEnabled()) - log.info(""); - super.pipelineElectedLeader(); - lock.lock(); - try { - tearDown(); - setUpSendService(); - } finally { - lock.unlock(); - } - } - - /** - * Tears down the {@link HASendService} or {@link HAReceiveService} - * associated with this service. - */ - @Override - public void pipelineRemove() { - if (log.isInfoEnabled()) - log.info(""); - super.pipelineRemove(); - lock.lock(); - try { - tearDown(); - } finally { - lock.unlock(); - } - } - - /** - * Changes the target of the {@link HASendService} for the leader (or the - * {@link HAReceiveService} for a follower) to send (or relay) write cache - * blocks to the specified service. - */ - public void pipelineChange(final UUID oldDownStreamId, - final UUID newDownStreamId) { - super.pipelineChange(oldDownStreamId, newDownStreamId); - lock.lock(); - try { - // The address of the next service in the pipeline. - final InetSocketAddress addrNext = newDownStreamId == null ? null - : getAddrNext(newDownStreamId); - if (log.isInfoEnabled()) - log.info("oldDownStreamId=" + oldDownStreamId - + ",newDownStreamId=" + newDownStreamId + ", addrNext=" - + addrNext + ", sendService=" + sendService - + ", receiveService=" + receiveService); - if (sendService != null) { - /* - * Terminate the existing connection (we were the first service - * in the pipeline). - */ - sendService.terminate(); - if (addrNext != null) { - if (log.isDebugEnabled()) - log.debug("sendService.start(): addrNext=" + addrNext); - sendService.start(addrNext); - } - } else if (receiveService != null) { - /* - * Reconfigure the receive service to change how it is relaying - * (we were relaying, so the receiveService was running but not - * the sendService). - */ - if (log.isDebugEnabled()) - log.debug("receiveService.changeDownStream(): addrNext=" - + addrNext); - receiveService.changeDownStream(addrNext); - } - // populate and/or clear the cache. - cachePipelineState(newDownStreamId); - if (log.isDebugEnabled()) - log.debug("pipelineChange - done."); - } finally { - lock.unlock(); - } - } - - @Override - public void pipelineUpstreamChange() { - super.pipelineUpstreamChange(); - lock.lock(); - try { - if (receiveService != null) { - /* - * Make sure that the receiveService closes out its client - * connection with the old upstream service. - */ - if (log.isInfoEnabled()) - log.info("receiveService=" + receiveService); - receiveService.changeUpStream(); - } - } finally { - lock.unlock(); - } - } - - /** - * Request the {@link InetSocketAddress} of the write pipeline for a service - * (RMI). - * - * @param downStreamId - * The service. - * - * @return It's {@link InetSocketAddress} - */ - private InetSocketAddress getAddrNext(final UUID downStreamId) { - - if (downStreamId == null) - return null; - - final S service = member.getService(downStreamId); - - try { - - final InetSocketAddress addrNext = service.getWritePipelineAddr(); - - return addrNext; - - } catch (IOException e) { - - throw new RuntimeException(e); - - } - - } - - /** - * Tear down any state associated with the {@link QuorumPipelineImpl}. This - * implementation tears down the send/receive service and releases the - * receive buffer. - */ - private void tearDown() { - if (log.isInfoEnabled()) - log.info(""); - lock.lock(); - try { - /* - * Leader tear down. - */ - { - if (sendService != null) { - sendService.terminate(); - sendService = null; - } - } - /* - * Follower tear down. - */ - { - if (receiveService != null) { - receiveService.terminate(); - try { - receiveService.awaitShutdown(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } finally { - receiveService = null; - } - } - if (receiveBuffer != null) { - try { - /* - * Release the buffer back to the pool. - */ - receiveBuffer.release(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } finally { - receiveBuffer = null; - } - } - } - // clear cache. - pipelineStateRef.set(null); - } finally { - lock.unlock(); - } - } - - /** - * Populate or clear the {@link #pipelineState} cache. - * <p> - * Note: The only times we need to populate the {@link #pipelineState} are - * in response to a {@link #pipelineChange(UUID, UUID)} event or in response - * to message a {@link #pipelineElectedLeader()} event. - * - * @param downStreamId - * The downstream service {@link UUID}. - */ - private void cachePipelineState(final UUID downStreamId) { - - if (downStreamId == null) { - - pipelineStateRef.set(null); - - return; - - } - - final S nextService = member.getService(downStreamId); - - final PipelineState<S> pipelineState = new PipelineState<S>(); - - try { - - pipelineState.addr = nextService.getWritePipelineAddr(); - - } catch (IOException e) { - - throw new RuntimeException(e); - - } - - pipelineState.service = nextService; - - this.pipelineStateRef.set(pipelineState); - - } - - /** - * Setup the send service. - */ - private void setUpSendService() { - if (log.isInfoEnabled()) - log.info(""); - lock.lock(); - try { - // Allocate the send service. - sendService = new HASendService(); - /* - * The service downstream from this service. - * - * Note: The downstream service in the pipeline is not available - * when the first service adds itself to the pipeline. In those - * cases the pipelineChange() event is used to update the - * HASendService to send to the downstream service. - * - * Note: When we handle a pipelineLeaderElected() message the - * downstream service MAY already be available, which is why we - * handle downstreamId != null conditionally. - */ - final UUID downstreamId = member.getDownstreamServiceId(); - if (downstreamId != null) { - // The address of the next service in the pipeline. - final InetSocketAddress addrNext = member.getService( - downstreamId).getWritePipelineAddr(); - // Start the send service. - sendService.start(addrNext); - } - // populate and/or clear the cache. - cachePipelineState(downstreamId); - } catch (Throwable t) { - try { - tearDown(); - } catch (Throwable t2) { - log.error(t2, t2); - } - throw new RuntimeException(t); - } finally { - lock.unlock(); - } - } - - /** - * Glue class wraps the {@link IHAWriteMessage} and the - * {@link IHALogRequest} message and exposes the requires {@link IHAMessage} - * interface to the {@link HAReceiveService}. This class is never persisted. - * It just let's us handshake with the {@link HAReceiveService} and get back - * out the original {@link IHAWriteMessage} as well as the optional - * {@link IHALogRequest} message. - * - * @author <a href="mailto:tho...@us...">Bryan - * Thompson</a> - */ - private static class HAMessageWrapper extends HAWriteMessageBase { - - private static final long serialVersionUID = 1L; - - final IHASyncRequest req; - final IHAWriteMessage msg; - - public HAMessageWrapper(final IHASyncRequest req, - final IHAWriteMessage msg) { - - // Use size and checksum from real IHAWriteMessage. - super(msg.getSize(),msg.getChk()); - - this.req = req; // MAY be null; - this.msg = msg; - - } - - } - - /** - * Setup the service to receive pipeline writes and to relay them (if there - * is a downstream service). - */ - private void setUpReceiveService() { - lock.lock(); - try { - // The downstream service UUID. - final UUID downstreamId = member.getDownstreamServiceId(); - // Acquire buffer from the pool to receive data. - try { - receiveBuffer = DirectBufferPool.INSTANCE.acquire(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - // The address of this service. - final InetSocketAddress addrSelf = member.getService() - .getWritePipelineAddr(); - // Address of the downstream service (if any). - final InetSocketAddress addrNext = downstreamId == null ? null - : member.getService(downstreamId).getWritePipelineAddr(); - // Setup the receive service. - receiveService = new HAReceiveService<HAMessageWrapper>(addrSelf, - addrNext, new IHAReceiveCallback<HAMessageWrapper>() { - public void callback(final HAMessageWrapper msg, - final ByteBuffer data) throws Exception { - // delegate handling of write cache blocks. - handleReplicatedWrite(msg.req, msg.msg, data); - } - }); - // Start the receive service - will not return until service is - // running - receiveService.start(); - } catch (Throwable t) { - /* - * Always tear down if there was a setup problem to avoid leaking - * threads or a native ByteBuffer. - */ - try { - tearDown(); - } catch (Throwable t2) { - log.error(t2, t2); - } finally { - log.error(t, t); - } - throw new RuntimeException(t); - } finally { - lock.unlock(); - } - } - - /* - * This is the leader, so send() the buffer. - */ - @Override - public Future<Void> replicate(final IHASyncRequest req, - final IHAWriteMessage msg, final ByteBuffer b) throws IOException { - - final RunnableFuture<Void> ft; - - lock.lock(); - try { - - ft = new FutureTask<Void>(new RobustReplicateTask(req, msg, b)); - - } finally { - - lock.unlock(); - - } - - // Submit Future for execution (outside of the lock). - member.getExecutor().execute(ft); - - // Return Future. Caller must wait on the Future. - return ft; - - } - - /** - * Task robustly replicates an {@link IHAWriteMessage} and the associated - * payload. - */ - private class RobustReplicateTask implements Callable<Void> { - - /** - * An historical message is indicated when the {@link IHASyncRequest} is - * non-<code>null</code>. - */ - private final IHASyncRequest req; - - /** - * The {@link IHAWriteMessage}. - */ - private final IHAWriteMessage msg; - - /** - * The associated payload. - */ - private final ByteBuffer b; - - /** - * The token for the leader. The service that initiates the replication - * of a message MUST be the leader for this token. - * <p> - * The token is either taken from the {@link IHAWriteMessage} (if this - * is a live write) or from the current {@link Quorum#token()}. - * <p> - * Either way, we verify that this service is (and remains) the leader - * for that token throughout the {@link Robus... [truncated message content] |