package org.infinispan.tools.jdbc.migrator;
import static org.infinispan.tools.jdbc.migrator.Element.BATCH;
import static org.infinispan.tools.jdbc.migrator.Element.SIZE;
import java.io.FileReader;
import java.util.Properties;
import javax.transaction.Status;
import javax.transaction.TransactionManager;
import org.infinispan.AdvancedCache;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.context.Flag;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.marshall.core.MarshalledEntry;
import org.infinispan.tools.jdbc.migrator.marshaller.LegacyVersionAwareMarshaller;
/**
* @author Ryan Emerson
* @since 9.0
*/
public class JDBCMigrator {
private static final int DEFAULT_BATCH_SIZE = 1000;
private final String defaultCacheName = this.getClass().getName();
private final Properties properties;
private JDBCMigrator(Properties properties) {
this.properties = properties;
}
private void run() throws Exception {
String batchSizeProp = properties.getProperty(BATCH + "." + SIZE);
int batchLimit = batchSizeProp != null ? new Integer(batchSizeProp) : DEFAULT_BATCH_SIZE;
try (JdbcStoreReader sourceReader = initAndGetSourceReader()) {
AdvancedCache targetCache = initAndGetTargetCache();
// Txs used so that writes to the DB are batched. Migrator will always operate locally Tx overhead should be negligible
TransactionManager tm = targetCache.getTransactionManager();
int txBatchSize = 0;
for (MarshalledEntry entry : sourceReader) {
if (txBatchSize == 0) tm.begin();
targetCache.put(entry.getKey(), entry.getValue());
txBatchSize++;
if (txBatchSize == batchLimit) {
txBatchSize = 0;
tm.commit();
}
}
if (tm.getStatus() == Status.STATUS_ACTIVE) tm.commit();
}
}
private JdbcStoreReader initAndGetSourceReader() {
MigratorConfiguration config = new MigratorConfiguration(true, properties);
return new JdbcStoreReader(config);
}
private AdvancedCache initAndGetTargetCache() {
MigratorConfiguration config = new MigratorConfiguration(false, properties);
GlobalConfiguration globalConfig = new GlobalConfigurationBuilder()
.defaultCacheName(defaultCacheName)
.globalJmxStatistics()
.allowDuplicateDomains(true)
.build();
if (config.hasCustomMarshaller()) {
globalConfig = new GlobalConfigurationBuilder()
.globalJmxStatistics().allowDuplicateDomains(true)
.serialization().marshaller(config.getMarshaller())
.build();
}
Configuration cacheConfig = new ConfigurationBuilder().persistence().addStore(config.getJdbcConfigBuilder()).build();
DefaultCacheManager targetCacheManager = new DefaultCacheManager(globalConfig, new ConfigurationBuilder().build());
targetCacheManager.defineConfiguration(config.cacheName, cacheConfig);
return targetCacheManager.getCache(config.cacheName).getAdvancedCache().withFlags(Flag.SKIP_CACHE_LOAD);
}
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Usage: JDBCMigrator migrator.properties");
System.exit(1);
}
Properties properties = new Properties();
properties.load(new FileReader(args[0]));
new JDBCMigrator(properties).run();
}
}