package com.constellio.data.dao.services.factories; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.UUID; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.params.ModifiableSolrParams; import com.constellio.data.conf.ConfigManagerType; import com.constellio.data.conf.ContentDaoType; import com.constellio.data.conf.DataLayerConfiguration; import com.constellio.data.conf.IdGeneratorType; import com.constellio.data.conf.SolrServerType; import com.constellio.data.dao.dto.records.RecordDTO; import com.constellio.data.dao.dto.records.RecordDeltaDTO; import com.constellio.data.dao.dto.records.RecordsFlushing; import com.constellio.data.dao.dto.records.TransactionDTO; import com.constellio.data.dao.managers.StatefullServiceDecorator; import com.constellio.data.dao.managers.config.ConfigManager; import com.constellio.data.dao.managers.config.FileSystemConfigManager; import com.constellio.data.dao.managers.config.ZooKeeperConfigManager; import com.constellio.data.dao.services.DataLayerLogger; import com.constellio.data.dao.services.DataStoreTypesFactory; import com.constellio.data.dao.services.bigVault.BigVaultRecordDao; import com.constellio.data.dao.services.bigVault.RecordDaoException; import com.constellio.data.dao.services.bigVault.solr.BigVaultException; import com.constellio.data.dao.services.bigVault.solr.BigVaultLogger; import com.constellio.data.dao.services.bigVault.solr.BigVaultServer; import com.constellio.data.dao.services.contents.ContentDao; import com.constellio.data.dao.services.contents.FileSystemContentDao; import com.constellio.data.dao.services.contents.HadoopContentDao; import com.constellio.data.dao.services.idGenerator.UUIDV1Generator; import com.constellio.data.dao.services.idGenerator.UniqueIdGenerator; import com.constellio.data.dao.services.idGenerator.ZeroPaddedSequentialUniqueIdGenerator; import com.constellio.data.dao.services.records.RecordDao; import com.constellio.data.dao.services.recovery.TransactionLogRecoveryManager; import com.constellio.data.dao.services.sequence.SequencesManager; import com.constellio.data.dao.services.sequence.SolrSequencesManager; import com.constellio.data.dao.services.solr.SolrDataStoreTypesFactory; import com.constellio.data.dao.services.solr.SolrServerFactory; import com.constellio.data.dao.services.solr.SolrServers; import com.constellio.data.dao.services.solr.serverFactories.CloudSolrServerFactory; import com.constellio.data.dao.services.solr.serverFactories.HttpSolrServerFactory; import com.constellio.data.dao.services.transactionLog.SecondTransactionLogManager; import com.constellio.data.dao.services.transactionLog.XMLSecondTransactionLogManager; import com.constellio.data.extensions.DataLayerExtensions; import com.constellio.data.io.IOServicesFactory; import com.constellio.data.test.FaultInjectorSolrServerFactory; import com.constellio.data.threads.BackgroundThreadsManager; import com.constellio.data.threads.ConstellioJobManager; import com.constellio.data.utils.ImpossibleRuntimeException; public class DataLayerFactory extends LayerFactory { private static final String RECORDS_SEQUENCE_TABLE_CONFIG_PATH = "/sequence.properties"; private static final String SECONDARY_SEQUENCE_TABLE_CONFIG_PATH = "/secondarySequence.properties"; static final String RECORDS_COLLECTION = "records"; static final String EVENTS_COLLECTION = "events"; static final String CONTENTS_COLLECTION = "contents"; static final String NOTIFICATIONS_COLLECTION = "notifications"; private final IOServicesFactory ioServicesFactory; private final SolrServers solrServers; private final ConfigManager configManager; private final UniqueIdGenerator idGenerator; private final UniqueIdGenerator secondaryIdGenerator; private final DataLayerConfiguration dataLayerConfiguration; private final ContentDao contentDao; private final BigVaultLogger bigVaultLogger; private final SecondTransactionLogManager secondTransactionLogManager; private final BackgroundThreadsManager backgroundThreadsManager; private final ConstellioJobManager constellioJobManager; private final DataLayerLogger dataLayerLogger; private final DataLayerExtensions dataLayerExtensions; final TransactionLogRecoveryManager transactionLogRecoveryManager; public DataLayerFactory(IOServicesFactory ioServicesFactory, DataLayerConfiguration dataLayerConfiguration, StatefullServiceDecorator statefullServiceDecorator, String instanceName) { super(statefullServiceDecorator, instanceName); this.dataLayerExtensions = new DataLayerExtensions(); this.dataLayerConfiguration = dataLayerConfiguration; // TODO Possibility to configure the logger this.bigVaultLogger = BigVaultLogger.disabled(); this.ioServicesFactory = ioServicesFactory; this.solrServers = new SolrServers(newSolrServerFactory(), bigVaultLogger, dataLayerExtensions); this.dataLayerLogger = new DataLayerLogger(); this.backgroundThreadsManager = add(new BackgroundThreadsManager(dataLayerConfiguration, this)); constellioJobManager = add(new ConstellioJobManager(dataLayerConfiguration)); if (dataLayerConfiguration.getSettingsConfigType() == ConfigManagerType.ZOOKEEPER) { this.configManager = add(new ZooKeeperConfigManager(dataLayerConfiguration.getSettingsZookeeperAddress(), ioServicesFactory.newIOServices())); } else if (dataLayerConfiguration.getSettingsConfigType() == ConfigManagerType.FILESYSTEM) { this.configManager = add(new FileSystemConfigManager(dataLayerConfiguration.getSettingsFileSystemBaseFolder(), ioServicesFactory.newIOServices(), ioServicesFactory.newHashingService(dataLayerConfiguration.getHashingEncoding()))); } else { throw new ImpossibleRuntimeException("Unsupported ConfigManagerType"); } if (dataLayerConfiguration.getIdGeneratorType() == IdGeneratorType.UUID_V1) { this.idGenerator = new UUIDV1Generator(); } else if (dataLayerConfiguration.getIdGeneratorType() == IdGeneratorType.SEQUENTIAL) { this.idGenerator = add(new ZeroPaddedSequentialUniqueIdGenerator(configManager, RECORDS_SEQUENCE_TABLE_CONFIG_PATH)); } else { throw new ImpossibleRuntimeException("Unsupported UniqueIdGenerator"); } if (dataLayerConfiguration.getSecondaryIdGeneratorType() == IdGeneratorType.UUID_V1) { this.secondaryIdGenerator = new UUIDV1Generator(); } else if (dataLayerConfiguration.getSecondaryIdGeneratorType() == IdGeneratorType.SEQUENTIAL) { this.secondaryIdGenerator = add(new ZeroPaddedSequentialUniqueIdGenerator(configManager, SECONDARY_SEQUENCE_TABLE_CONFIG_PATH)); } else { throw new ImpossibleRuntimeException("Unsupported UniqueIdGenerator"); } if (ContentDaoType.FILESYSTEM == dataLayerConfiguration.getContentDaoType()) { File rootFolder = dataLayerConfiguration.getContentDaoFileSystemFolder(); contentDao = add(new FileSystemContentDao(rootFolder, ioServicesFactory.newIOServices(), dataLayerConfiguration)); } else if (ContentDaoType.HADOOP == dataLayerConfiguration.getContentDaoType()) { String hadoopUrl = dataLayerConfiguration.getContentDaoHadoopUrl(); String hadoopUser = dataLayerConfiguration.getContentDaoHadoopUser(); contentDao = new HadoopContentDao(hadoopUrl, hadoopUser); } else { throw new ImpossibleRuntimeException("Unsupported ContentDaoType"); } transactionLogRecoveryManager = new TransactionLogRecoveryManager(this); if (dataLayerConfiguration.isSecondTransactionLogEnabled()) { secondTransactionLogManager = add(new XMLSecondTransactionLogManager(dataLayerConfiguration, ioServicesFactory.newIOServices(), newRecordDao(), contentDao, backgroundThreadsManager, dataLayerLogger, dataLayerExtensions.getSystemWideExtensions(), transactionLogRecoveryManager)); } else { secondTransactionLogManager = null; } } public DataLayerExtensions getExtensions() { return dataLayerExtensions; } public RecordDao newRecordDao() { return new BigVaultRecordDao(getRecordsVaultServer(), newTypesFactory(), secondTransactionLogManager, dataLayerLogger); } public RecordDao newEventsDao() { return new BigVaultRecordDao(getEventsVaultServer(), newTypesFactory(), null, dataLayerLogger); } public RecordDao newNotificationsDao() { return new BigVaultRecordDao(getNotificationsVaultServer(), newTypesFactory(), null, dataLayerLogger); } public ConfigManager getConfigManager() { return configManager; } public ContentDao getContentsDao() { return contentDao; } public BigVaultServer getRecordsVaultServer() { return solrServers.getSolrServer(RECORDS_COLLECTION); } public BigVaultServer getEventsVaultServer() { return solrServers.getSolrServer(EVENTS_COLLECTION); } public BigVaultServer getContentsVaultServer() { return solrServers.getSolrServer(CONTENTS_COLLECTION); } public BigVaultServer getNotificationsVaultServer() { return solrServers.getSolrServer(NOTIFICATIONS_COLLECTION); } public DataStoreTypesFactory newTypesFactory() { return new SolrDataStoreTypesFactory(); } public UniqueIdGenerator getUniqueIdGenerator() { return idGenerator; } public UniqueIdGenerator getSecondaryUniqueIdGenerator() { return secondaryIdGenerator; } public DataLayerLogger getDataLayerLogger() { return dataLayerLogger; } public IOServicesFactory getIOServicesFactory() { return ioServicesFactory; } @Override public void initialize() { super.initialize(); newRecordDao().removeOldLocks(); } @Override public void close() { super.close(); solrServers.close(); } @Override public void close(boolean closeBottomLayers) { super.close(closeBottomLayers); solrServers.close(); } public SolrServers getSolrServers() { return solrServers; } private SolrServerFactory newSolrServerFactory() { SolrServerType solrServerType = dataLayerConfiguration.getRecordsDaoSolrServerType(); if (SolrServerType.HTTP == solrServerType) { return newHttpSolrServerFactory(); } else if (SolrServerType.CLOUD == solrServerType) { return newSolrCloudServerFactory(); } else { throw new ImpossibleRuntimeException("Unsupported solr server type"); } } private SolrServerFactory newHttpSolrServerFactory() { String httpSolrUrl = dataLayerConfiguration.getRecordsDaoHttpSolrServerUrl(); SolrServerFactory solrServerFactory = new HttpSolrServerFactory(httpSolrUrl, ioServicesFactory); if (dataLayerConfiguration.isRecordsDaoHttpSolrServerFaultInjectionEnabled()) { solrServerFactory = new FaultInjectorSolrServerFactory(solrServerFactory); } return solrServerFactory; } private SolrServerFactory newSolrCloudServerFactory() { String zkHost = dataLayerConfiguration.getRecordsDaoCloudSolrServerZKHost(); return new CloudSolrServerFactory(zkHost); } public BackgroundThreadsManager getBackgroundThreadsManager() { return backgroundThreadsManager; } public ConstellioJobManager getConstellioJobManager() { return constellioJobManager; } public SecondTransactionLogManager getSecondTransactionLogManager() { return secondTransactionLogManager; } public DataLayerConfiguration getDataLayerConfiguration() { return dataLayerConfiguration; } public String readEncryptionKey() throws BigVaultException { ModifiableSolrParams params = new ModifiableSolrParams(); params.set("q", "id:the_private_key"); SolrDocument solrDocument = getRecordsVaultServer().querySingleResult(params); return (String) solrDocument.getFieldValue("value_s"); } public void saveEncryptionKey() { String solrKeyPart = dataLayerConfiguration.createRandomUniqueKey(); RecordDao recordDao = newRecordDao(); Map<String, Object> fields = new HashMap<>(); fields.put("value_s", solrKeyPart); RecordDTO record = new RecordDTO("the_private_key", -1L, null, fields); try { recordDao.execute(new TransactionDTO(UUID.randomUUID().toString(), RecordsFlushing.NOW, Arrays.asList(record), new ArrayList<RecordDeltaDTO>())); } catch (RecordDaoException.OptimisticLocking e) { throw new RuntimeException(e); } } public TransactionLogRecoveryManager getTransactionLogRecoveryManager() { return this.transactionLogRecoveryManager; } public SequencesManager getSequencesManager() { return new SolrSequencesManager(newRecordDao(), secondTransactionLogManager); } }