package org.infinispan.persistence.cli.upgrade; import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.codehaus.jackson.annotate.JsonTypeInfo; import org.codehaus.jackson.map.ObjectMapper; import org.infinispan.Cache; import org.infinispan.commons.CacheException; import org.infinispan.commons.util.Util; import org.infinispan.factories.ComponentRegistry; import org.infinispan.marshall.core.MarshalledEntry; import org.infinispan.persistence.cli.CLInterfaceLoader; import org.infinispan.persistence.manager.PersistenceManager; import org.infinispan.upgrade.TargetMigrator; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import org.kohsuke.MetaInfServices; /** * // TODO: Document this * * @author Galder ZamarreƱo * @since // TODO */ @MetaInfServices public class CLInterfaceTargetMigrator implements TargetMigrator { private static final Log log = LogFactory.getLog(CLInterfaceTargetMigrator.class); private static final String KNOWN_KEY = "___MigrationManager_CLI_KnownKeys___"; private ObjectMapper jsonMapper = new ObjectMapper().enableDefaultTyping( ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_OBJECT); @Override public String getName() { return "cli"; } @Override public long synchronizeData(final Cache<Object, Object> cache) throws CacheException { return synchronizeData(cache, 0, Runtime.getRuntime().availableProcessors()); } @Override public long synchronizeData(Cache<Object, Object> cache, int readBatch, int threads) throws CacheException { PersistenceManager loaderManager = getPersistenceManager(cache); Set<CLInterfaceLoader> loaders = loaderManager.getStores(CLInterfaceLoader.class); for (CLInterfaceLoader loader : loaders) { MarshalledEntry loadedKnownKey = loader.load(KNOWN_KEY); if (loadedKnownKey != null) { Set<Object> keys; try { keys = jsonMapper .readValue((String) loadedKnownKey.getValue(), HashSet.class); } catch (IOException e) { throw new CacheException( "Unable to read JSON value: " + loadedKnownKey.getValue(), e); } ExecutorService es = Executors.newFixedThreadPool(threads); final AtomicInteger count = new AtomicInteger(0); for (final Object key : keys) { es.submit(new Runnable() { @Override public void run() { try { cache.get(key); int i = count.getAndIncrement(); if (log.isDebugEnabled() && i % 100 == 0) log.debugf(">> Moved %s keys\n", i); } catch (Exception e) { log.keyMigrationFailed(Util.toStr(key), e); } } }); } es.shutdown(); try { while (!es.awaitTermination(500, TimeUnit.MILLISECONDS)) { } } catch (InterruptedException e) { throw new CacheException(e); } return count.longValue(); } } throw log.missingMigrationData(cache.getName()); } private PersistenceManager getPersistenceManager(Cache<Object, Object> cache) { ComponentRegistry cr = cache.getAdvancedCache().getComponentRegistry(); return cr.getComponent(PersistenceManager.class); } @Override public void disconnectSource(Cache<Object, Object> cache) throws CacheException { PersistenceManager loaderManager = getPersistenceManager(cache); loaderManager.disableStore(CLInterfaceLoader.class.getName()); } }