@Override public DeltaStoreBasedWaveletState call() throws PersistenceException { return DeltaStoreBasedWaveletState.create(deltaStore.open(waveletName), persistExecutor); } });
/** * Creates a new delta store based state. * * The executor must ensure that only one thread executes at any time for each * state instance. * * @param deltasAccess delta store accessor * @param persistExecutor executor for making persistence calls * @return a state initialized from the deltas * @throws PersistenceException if a failure occurs while reading or * processing stored deltas */ public static DeltaStoreBasedWaveletState create(DeltaStore.DeltasAccess deltasAccess, Executor persistExecutor) throws PersistenceException { if (deltasAccess.isEmpty()) { return new DeltaStoreBasedWaveletState(deltasAccess, ImmutableList.<WaveletDeltaRecord>of(), null, persistExecutor); } else { try { ImmutableList<WaveletDeltaRecord> deltas = readAll(deltasAccess, null); WaveletData snapshot = WaveletDataUtil.buildWaveletFromDeltas(deltasAccess.getWaveletName(), Iterators.transform(deltas.iterator(), TRANSFORMED)); return new DeltaStoreBasedWaveletState(deltasAccess, deltas, snapshot, persistExecutor); } catch (IOException e) { throw new PersistenceException("Failed to read stored deltas", e); } catch (OperationException e) { throw new PersistenceException("Failed to compose stored deltas", e); } } }
private boolean isDeltaBoundary(HashedVersion version) { Preconditions.checkNotNull(version, "version is null"); return version.equals(getCurrentVersion()) || cachedDeltas.containsKey(version); } }
@Override public ByteStringMessage<ProtocolAppliedWaveletDelta> getAppliedDeltaByEndVersion( final HashedVersion endVersion) { Preconditions.checkArgument(endVersion.getVersion() > 0, "end version %s is not positive", endVersion); Entry<HashedVersion, WaveletDeltaRecord> appliedEntry = cachedDeltas.lowerEntry(endVersion); final ByteStringMessage<ProtocolAppliedWaveletDelta> cachedDelta = appliedEntry != null ? appliedEntry.getValue().getAppliedDelta() : null; WaveletDeltaRecord deltaRecord = getDeltaRecordByEndVersion(endVersion); ByteStringMessage<ProtocolAppliedWaveletDelta> appliedDelta; if (deltaRecord == null && isDeltaBoundary(endVersion)) { appliedDelta = cachedDelta; } else { appliedDelta = deltaRecord != null ? deltaRecord.getAppliedDelta() : null; } return appliedDelta; }
@Override public HashedVersion getHashedVersion(long version) { final Entry<HashedVersion, WaveletDeltaRecord> cachedEntry = lookupCached(cachedDeltas, version); if (version == 0) { return versionZero; } else if (snapshot == null) { return null; } else if (version == snapshot.getVersion()) { return snapshot.getHashedVersion(); } else { WaveletDeltaRecord delta; try { delta = lookup(version); } catch (IOException e) { throw new RuntimeIOException(new IOException(format("Version : %d", version), e)); } if (delta == null && cachedEntry != null) { return cachedEntry.getKey(); } else { return delta != null ? delta.getAppliedAtVersion() : null; } } }
@Override public void appendDelta(WaveletDeltaRecord deltaRecord) throws OperationException { HashedVersion currentVersion = getCurrentVersion(); Preconditions.checkArgument(currentVersion.equals(deltaRecord.getAppliedAtVersion()), "Applied version %s doesn't match current version %s", deltaRecord.getAppliedAtVersion(), currentVersion); if (deltaRecord.getAppliedAtVersion().getVersion() == 0) { Preconditions.checkState(lastPersistedVersion.get() == null); snapshot = WaveletDataUtil.buildWaveletFromFirstDelta(getWaveletName(), deltaRecord.getTransformedDelta()); } else { WaveletDataUtil.applyWaveletDelta(deltaRecord.getTransformedDelta(), snapshot); } // Now that we built the snapshot without any exceptions, we record the delta. cachedDeltas.put(deltaRecord.getAppliedAtVersion(), deltaRecord); }
@Override public ByteStringMessage<ProtocolAppliedWaveletDelta> getAppliedDelta( HashedVersion beginVersion) { WaveletDeltaRecord delta = cachedDeltas.get(beginVersion); if (delta != null) { return delta.getAppliedDelta(); } else { WaveletDeltaRecord record = null; try { record = lookup(beginVersion.getVersion()); } catch (IOException e) { throw new RuntimeIOException(new IOException(format("Begin version : %s", beginVersion.toString()), e)); } return record != null ? record.getAppliedDelta() : null; } }
private static void readDeltasInRange(WaveletDeltaRecordReader reader, ConcurrentNavigableMap<HashedVersion, WaveletDeltaRecord> cachedDeltas, HashedVersion startVersion, HashedVersion endVersion, Receiver<WaveletDeltaRecord> receiver) throws IOException { WaveletDeltaRecord delta = getDelta(reader, cachedDeltas, startVersion); Preconditions.checkArgument(delta != null && delta.getAppliedAtVersion().equals(startVersion), "invalid start version"); for (;;) { if (!receiver.put(delta)) { return; } if (delta.getResultingVersion().getVersion() >= endVersion.getVersion()) { break; } delta = getDelta(reader, cachedDeltas, delta.getResultingVersion()); if (delta == null) { break; } } Preconditions.checkArgument(delta != null && delta.getResultingVersion().equals(endVersion), "invalid end version"); }
@Override public ListenableFuture<Void> persist(final HashedVersion version) { Preconditions.checkArgument(version.getVersion() > 0, "Cannot persist non-positive version %s", version); Preconditions.checkArgument(isDeltaBoundary(version), "Version to persist %s matches no delta", version); synchronized (persistLock) { if (latestVersionToPersist != null) { // There's a persist task in flight. if (version.getVersion() <= latestVersionToPersist.getVersion()) { LOG.info("Attempt to persist version " + version + " smaller than last version requested " + latestVersionToPersist); } else { latestVersionToPersist = version; } if (nextPersistTask == null) { nextPersistTask = ListenableFutureTask.<Void>create(persisterTask); } return nextPersistTask; } else { latestVersionToPersist = version; ListenableFutureTask<Void> resultTask = ListenableFutureTask.<Void>create(persisterTask); persistExecutor.execute(resultTask); return resultTask; } } }
@Override public TransformedWaveletDelta getTransformedDeltaByEndVersion(final HashedVersion endVersion) { Preconditions.checkArgument(endVersion.getVersion() > 0, "end version %s is not positive", endVersion); Entry<HashedVersion, WaveletDeltaRecord> transformedEntry = cachedDeltas.lowerEntry(endVersion); final WaveletDeltaRecord cachedDelta = transformedEntry != null ? transformedEntry.getValue() : null; if (snapshot == null) { return null; } else { WaveletDeltaRecord deltaRecord = getDeltaRecordByEndVersion(endVersion); TransformedWaveletDelta delta; if (deltaRecord == null && cachedDelta != null && cachedDelta.getResultingVersion().equals(endVersion)) { delta = cachedDelta.getTransformedDelta(); } else { delta = deltaRecord != null ? deltaRecord.getTransformedDelta() : null; } return delta; } }
@Override public TransformedWaveletDelta getTransformedDelta( final HashedVersion beginVersion) { WaveletDeltaRecord delta = cachedDeltas.get(beginVersion); if (delta != null) { return delta.getTransformedDelta(); } else { WaveletDeltaRecord nowDelta; try { nowDelta = lookup(beginVersion.getVersion()); } catch (IOException e) { throw new RuntimeIOException(new IOException(format("Begin version : %s", beginVersion.toString()), e)); } return nowDelta != null ? nowDelta.getTransformedDelta() : null; } }
@Override protected WaveletState createEmptyState(WaveletName name) throws Exception { return DeltaStoreBasedWaveletState.create(store.open(name), PERSIST_EXECUTOR); }
@Override protected WaveletState createEmptyState(WaveletName name) throws Exception { return DeltaStoreBasedWaveletState.create(store.open(name), PERSIST_EXECUTOR); }
@Override public LocalWaveletContainer create(WaveletNotificationSubscriber notifiee, WaveletName waveletName, String domain) { WaveletState waveletState; try { waveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(waveletName), persistExecutor); } catch (PersistenceException e) { throw new RuntimeException(e); } return new LocalWaveletContainerImpl(waveletName, notifiee, Futures.immediateFuture(waveletState), DOMAIN, storageContinuationExecutor); } };
@Override public LocalWaveletContainer create(WaveletNotificationSubscriber notifiee, WaveletName waveletName, String domain) { WaveletState waveletState; try { waveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(waveletName), persistExecutor); } catch (PersistenceException e) { throw new RuntimeException(e); } return new LocalWaveletContainerImpl(waveletName, notifiee, Futures.immediateFuture(waveletState), DOMAIN, storageContinuationExecutor); } };
@Override public LocalWaveletContainer create(WaveletNotificationSubscriber notifiee, WaveletName waveletName, String domain) { WaveletState waveletState; try { waveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(waveletName), persistExecutor); } catch (PersistenceException e) { throw new RuntimeException(e); } return new LocalWaveletContainerImpl(waveletName, notifiee, Futures.immediateFuture(waveletState), DOMAIN, storageContinuationExecutor, accessController); } };
@Override public LocalWaveletContainer create(WaveletNotificationSubscriber notifiee, WaveletName waveletName, String domain) { WaveletState waveletState; try { waveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(waveletName), persistExecutor); } catch (PersistenceException e) { throw new RuntimeException(e); } return new LocalWaveletContainerImpl(waveletName, notifiee, Futures.immediateFuture(waveletState), DOMAIN, storageContinuationExecutor, accessController); } };
@Override public void setUp() throws Exception { super.setUp(); WaveletNotificationSubscriber notifiee = mock(WaveletNotificationSubscriber.class); DeltaStore deltaStore = new MemoryDeltaStore(); WaveletState localWaveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(localWaveletName), PERSIST_EXECUTOR); localWavelet = new LocalWaveletContainerImpl(localWaveletName, notifiee, Futures.immediateFuture(localWaveletState), localDomain, STORAGE_CONTINUATION_EXECUTOR); localWavelet.awaitLoad(); WaveletState remoteWaveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(remoteWaveletName), PERSIST_EXECUTOR); remoteWavelet = new RemoteWaveletContainerImpl(remoteWaveletName, notifiee, Futures.immediateFuture(remoteWaveletState), STORAGE_CONTINUATION_EXECUTOR); remoteWavelet.awaitLoad(); }
@Override public void setUp() throws Exception { super.setUp(); WaveletNotificationSubscriber notifiee = mock(WaveletNotificationSubscriber.class); DeltaStore deltaStore = new MemoryDeltaStore(); AccessController localAccessController = mock(AccessController.class); AccessController remoteAccessController = mock(AccessController.class); WaveletState localWaveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(localWaveletName), PERSIST_EXECUTOR); localWavelet = new LocalWaveletContainerImpl(localWaveletName, notifiee, Futures.immediateFuture(localWaveletState), localDomain, STORAGE_CONTINUATION_EXECUTOR, localAccessController); localWavelet.awaitLoad(); WaveletState remoteWaveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(remoteWaveletName), PERSIST_EXECUTOR); remoteWavelet = new RemoteWaveletContainerImpl(remoteWaveletName, notifiee, Futures.immediateFuture(remoteWaveletState), STORAGE_CONTINUATION_EXECUTOR, remoteAccessController); remoteWavelet.awaitLoad(); }
@Override protected void setUp() throws Exception { super.setUp(); addParticipantOp = ProtocolWaveletOperation.newBuilder() .setAddParticipant(AUTHOR) .build(); // An empty blip operation - creates a new document. addBlipOp = ProtocolWaveletOperation.newBuilder().setMutateDocument( MutateDocument.newBuilder().setDocumentId(BLIP_ID).setDocumentOperation( ProtocolDocumentOperation.newBuilder().build())).build(); WaveletNotificationSubscriber notifiee = mock(WaveletNotificationSubscriber.class); DeltaStore deltaStore = new MemoryDeltaStore(); WaveletState waveletState = DeltaStoreBasedWaveletState.create(deltaStore.open(WAVELET_NAME), PERSIST_EXECUTOR); AccessController accessController = mock(AccessController.class); wavelet = new LocalWaveletContainerImpl(WAVELET_NAME, notifiee, Futures.immediateFuture(waveletState), null, STORAGE_CONTINUATION_EXECUTOR, accessController); wavelet.awaitLoad(); }