hollow/src/main/java/com/netflix/hollow/api/client/HollowClientUpdater.java
public synchronized boolean updateTo(long requestedVersion) throws Throwable {
        if (requestedVersion == getCurrentVersionId()) {
            if (requestedVersion == HollowConstants.VERSION_NONE && hollowDataHolderVolatile == null) {
                LOG.warning("No versions to update to, initializing to empty state");
                // attempting to refresh, but no available versions - initialize to empty state
                hollowDataHolderVolatile = newHollowDataHolder();
                forceDoubleSnapshotNextUpdate(); // intentionally ignore doubleSnapshotConfig
            }
            return true;
        }

        // Take a snapshot of the listeners to ensure additions or removals may occur concurrently
        // but will not take effect until a subsequent refresh
        final HollowConsumer.RefreshListener[] localListeners =
                refreshListeners.toArray(new HollowConsumer.RefreshListener[0]);

        long beforeVersion = getCurrentVersionId();

        for (HollowConsumer.RefreshListener listener : localListeners)
            listener.refreshStarted(beforeVersion, requestedVersion);

        try {
            HollowUpdatePlan updatePlan = shouldCreateSnapshotPlan()
                ? planner.planInitializingUpdate(requestedVersion)
                : planner.planUpdate(hollowDataHolderVolatile.getCurrentVersion(), requestedVersion,
                        doubleSnapshotConfig.allowDoubleSnapshot());

            for (HollowConsumer.RefreshListener listener : localListeners)
                if (listener instanceof HollowConsumer.TransitionAwareRefreshListener)
                    ((HollowConsumer.TransitionAwareRefreshListener)listener).transitionsPlanned(beforeVersion, requestedVersion, updatePlan.isSnapshotPlan(), updatePlan.getTransitionSequence());

            if (updatePlan.destinationVersion() == HollowConstants.VERSION_NONE
                    && requestedVersion != HollowConstants.VERSION_LATEST)
                throw new IllegalArgumentException(String.format("Could not create an update plan for version %s, because that version or any previous versions could not be retrieved.", requestedVersion));

            if (updatePlan.equals(HollowUpdatePlan.DO_NOTHING)
                    && requestedVersion == HollowConstants.VERSION_LATEST)
                throw new IllegalArgumentException("Could not create an update plan, because no existing versions could be retrieved.");

            if (updatePlan.destinationVersion(requestedVersion) == getCurrentVersionId())
                return true;

            if (updatePlan.isSnapshotPlan()) {
                if (hollowDataHolderVolatile == null || doubleSnapshotConfig.allowDoubleSnapshot()) {
                    hollowDataHolderVolatile = newHollowDataHolder();
                    hollowDataHolderVolatile.update(updatePlan, localListeners);
                    forceDoubleSnapshot = false;
                }
            } else {
                hollowDataHolderVolatile.update(updatePlan, localListeners);
            }

            for(HollowConsumer.RefreshListener refreshListener : localListeners)
                refreshListener.refreshSuccessful(beforeVersion, getCurrentVersionId(), requestedVersion);

            metrics.updateTypeStateMetrics(getStateEngine(), requestedVersion);
            if(metricsCollector != null)
                metricsCollector.collect(metrics);

            initialLoad.complete(getCurrentVersionId()); // only set the first time
            return getCurrentVersionId() == requestedVersion;
        } catch(Throwable th) {
            forceDoubleSnapshotNextUpdate();
            metrics.updateRefreshFailed();
            if(metricsCollector != null)
                metricsCollector.collect(metrics);
            for(HollowConsumer.RefreshListener refreshListener : localListeners)
                refreshListener.refreshFailed(beforeVersion, getCurrentVersionId(), requestedVersion, th);

            // intentionally omitting a call to initialLoad.completeExceptionally(th), for producers
            // that write often a consumer has a chance to try another snapshot that might succeed

            throw th;
        }
    }
public synchronized boolean updateTo(long requestedVersion) throws Throwable {
        if (requestedVersion == getCurrentVersionId()) {
            if (requestedVersion == HollowConstants.VERSION_NONE && hollowDataHolderVolatile == null) {
                LOG.warning("No versions to update to, initializing to empty state");
                // attempting to refresh, but no available versions - initialize to empty state
                hollowDataHolderVolatile = newHollowDataHolder();
                forceDoubleSnapshotNextUpdate(); // intentionally ignore doubleSnapshotConfig
            }
            return true;
        }

        // Take a snapshot of the listeners to ensure additions or removals may occur concurrently
        // but will not take effect until a subsequent refresh
        final HollowConsumer.RefreshListener[] localListeners =
                refreshListeners.toArray(new HollowConsumer.RefreshListener[0]);

        long beforeVersion = getCurrentVersionId();

        for (HollowConsumer.RefreshListener listener : localListeners)
            listener.refreshStarted(beforeVersion, requestedVersion);

        try {
            HollowUpdatePlan updatePlan = shouldCreateSnapshotPlan()
                ? planner.planInitializingUpdate(requestedVersion)
                : planner.planUpdate(hollowDataHolderVolatile.getCurrentVersion(), requestedVersion,
                        doubleSnapshotConfig.allowDoubleSnapshot());

            for (HollowConsumer.RefreshListener listener : localListeners)
                if (listener instanceof HollowConsumer.TransitionAwareRefreshListener)
                    ((HollowConsumer.TransitionAwareRefreshListener)listener).transitionsPlanned(beforeVersion, requestedVersion, updatePlan.isSnapshotPlan(), updatePlan.getTransitionSequence());

            if (updatePlan.destinationVersion() == HollowConstants.VERSION_NONE
                    && requestedVersion != HollowConstants.VERSION_LATEST)
                throw new IllegalArgumentException(String.format("Could not create an update plan for version %s, because that version or any previous versions could not be retrieved.", requestedVersion));

            if (updatePlan.equals(HollowUpdatePlan.DO_NOTHING)
                    && requestedVersion == HollowConstants.VERSION_LATEST)
                throw new IllegalArgumentException("Could not create an update plan, because no existing versions could be retrieved.");

            if (updatePlan.destinationVersion(requestedVersion) == getCurrentVersionId())
                return true;

            if (updatePlan.isSnapshotPlan()) {
                if (hollowDataHolderVolatile == null || doubleSnapshotConfig.allowDoubleSnapshot()) {
                    hollowDataHolderVolatile = newHollowDataHolder();
                    hollowDataHolderVolatile.update(updatePlan, localListeners);
                    forceDoubleSnapshot = false;
                }
            } else {
                hollowDataHolderVolatile.update(updatePlan, localListeners);
            }

            for(HollowConsumer.RefreshListener refreshListener : localListeners)
                refreshListener.refreshSuccessful(beforeVersion, getCurrentVersionId(), requestedVersion);

            metrics.updateTypeStateMetrics(getStateEngine(), requestedVersion);
            if(metricsCollector != null)
                metricsCollector.collect(metrics);

            initialLoad.complete(getCurrentVersionId()); // only set the first time
            return getCurrentVersionId() == requestedVersion;
        } catch(Throwable th) {
            forceDoubleSnapshotNextUpdate();
            metrics.updateRefreshFailed();
            if(metricsCollector != null)
                metricsCollector.collect(metrics);
            for(HollowConsumer.RefreshListener refreshListener : localListeners)
                refreshListener.refreshFailed(beforeVersion, getCurrentVersionId(), requestedVersion, th);

            // intentionally omitting a call to initialLoad.completeExceptionally(th), for producers
            // that write often a consumer has a chance to try another snapshot that might succeed

            throw th;
        }
    }
public synchronized boolean updateTo ( long requestedVersion ) throws Throwable { if ( requestedVersion == getCurrentVersionId ( ) ) { if ( requestedVersion == HollowConstants . VERSION_NONE && hollowDataHolderVolatile == null ) { LOG . warning ( "No versions to update to, initializing to empty state" ) ; // attempting to refresh, but no available versions - initialize to empty state hollowDataHolderVolatile = newHollowDataHolder ( ) ; forceDoubleSnapshotNextUpdate ( ) ; // intentionally ignore doubleSnapshotConfig } return true ; } // Take a snapshot of the listeners to ensure additions or removals may occur concurrently // but will not take effect until a subsequent refresh final HollowConsumer . RefreshListener [ ] localListeners = refreshListeners . toArray ( new HollowConsumer . RefreshListener [ 0 ] ) ; long beforeVersion = getCurrentVersionId ( ) ; for ( HollowConsumer . RefreshListener listener : localListeners ) listener . refreshStarted ( beforeVersion , requestedVersion ) ; try { HollowUpdatePlan updatePlan = shouldCreateSnapshotPlan ( ) ? planner . planInitializingUpdate ( requestedVersion ) : planner . planUpdate ( hollowDataHolderVolatile . getCurrentVersion ( ) , requestedVersion , doubleSnapshotConfig . allowDoubleSnapshot ( ) ) ; for ( HollowConsumer . RefreshListener listener : localListeners ) if ( listener instanceof HollowConsumer . TransitionAwareRefreshListener ) ( ( HollowConsumer . TransitionAwareRefreshListener ) listener ) . transitionsPlanned ( beforeVersion , requestedVersion , updatePlan . isSnapshotPlan ( ) , updatePlan . getTransitionSequence ( ) ) ; if ( updatePlan . destinationVersion ( ) == HollowConstants . VERSION_NONE && requestedVersion != HollowConstants . VERSION_LATEST ) throw new IllegalArgumentException ( String . format ( "Could not create an update plan for version %s, because that version or any previous versions could not be retrieved." , requestedVersion ) ) ; if ( updatePlan . equals ( HollowUpdatePlan . DO_NOTHING ) && requestedVersion == HollowConstants . VERSION_LATEST ) throw new IllegalArgumentException ( "Could not create an update plan, because no existing versions could be retrieved." ) ; if ( updatePlan . destinationVersion ( requestedVersion ) == getCurrentVersionId ( ) ) return true ; if ( updatePlan . isSnapshotPlan ( ) ) { if ( hollowDataHolderVolatile == null || doubleSnapshotConfig . allowDoubleSnapshot ( ) ) { hollowDataHolderVolatile = newHollowDataHolder ( ) ; hollowDataHolderVolatile . update ( updatePlan , localListeners ) ; forceDoubleSnapshot = false ; } } else { hollowDataHolderVolatile . update ( updatePlan , localListeners ) ; } for ( HollowConsumer . RefreshListener refreshListener : localListeners ) refreshListener . refreshSuccessful ( beforeVersion , getCurrentVersionId ( ) , requestedVersion ) ; metrics . updateTypeStateMetrics ( getStateEngine ( ) , requestedVersion ) ; if ( metricsCollector != null ) metricsCollector . collect ( metrics ) ; initialLoad . complete ( getCurrentVersionId ( ) ) ; // only set the first time return getCurrentVersionId ( ) == requestedVersion ; } catch ( Throwable th ) { forceDoubleSnapshotNextUpdate ( ) ; metrics . updateRefreshFailed ( ) ; if ( metricsCollector != null ) metricsCollector . collect ( metrics ) ; for ( HollowConsumer . RefreshListener refreshListener : localListeners ) refreshListener . refreshFailed ( beforeVersion , getCurrentVersionId ( ) , requestedVersion , th ) ; // intentionally omitting a call to initialLoad.completeExceptionally(th), for producers // that write often a consumer has a chance to try another snapshot that might succeed throw th ; } }
/*
Note that this method is synchronized and it is the only method that modifies the
{@code hollowDataHolderVolatile}, so we don't need to worry about it changing out from
under us.
/ * Note that this method is synchronized and it is the only method that modifies the {