pl.edu.icm.unity.engine.server.ServerManagementImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2013 ICM Uniwersytet Warszawski All rights reserved.
* See LICENCE.txt file for licensing information.
*/
package pl.edu.icm.unity.engine.server;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.JsonGenerationException;
import eu.unicore.util.configuration.ConfigurationException;
import pl.edu.icm.unity.base.exceptions.EngineException;
import pl.edu.icm.unity.base.exceptions.InternalException;
import pl.edu.icm.unity.base.json.dump.DBDumpContentElements;
import pl.edu.icm.unity.base.utils.Log;
import pl.edu.icm.unity.engine.api.ServerManagement;
import pl.edu.icm.unity.engine.api.config.UnityServerConfiguration;
import pl.edu.icm.unity.engine.api.utils.ExecutorsService;
import pl.edu.icm.unity.engine.authz.InternalAuthorizationManager;
import pl.edu.icm.unity.engine.authz.AuthzCapability;
import pl.edu.icm.unity.engine.bulkops.BulkProcessingInternal;
import pl.edu.icm.unity.engine.endpoint.InternalEndpointManagement;
import pl.edu.icm.unity.engine.events.InvocationEventProducer;
import pl.edu.icm.unity.store.api.ImportExport;
import pl.edu.icm.unity.store.api.StorageCleaner;
import pl.edu.icm.unity.base.tx.Transactional;
import pl.edu.icm.unity.store.api.tx.TransactionalRunner;
/**
* Implementation of general maintenance.
* @author K. Benedyczak
*/
@Component
@Primary
@InvocationEventProducer
class ServerManagementImpl implements ServerManagement
{
private Logger log = Log.getLogger(Log.U_SERVER_CORE, ServerManagementImpl.class);
private ImportExport dbDump;
private StorageCleaner initDb;
private EngineInitialization engineInit;
private InternalAuthorizationManager authz;
private UnityServerConfiguration config;
private InternalEndpointManagement endpointMan;
private TransactionalRunner tx;
private BulkProcessingInternal bulkProcessing;
@Autowired
ServerManagementImpl(TransactionalRunner tx, ImportExport dbDump, StorageCleaner initDb,
EngineInitialization engineInit, InternalEndpointManagement endpointMan,
InternalAuthorizationManager authz, ExecutorsService executorsService,
UnityServerConfiguration config,
BulkProcessingInternal bulkProcessing)
{
this.tx = tx;
this.dbDump = dbDump;
this.initDb = initDb;
this.engineInit = engineInit;
this.endpointMan = endpointMan;
this.authz = authz;
this.config = config;
this.bulkProcessing = bulkProcessing;
executorsService.getScheduledService().scheduleWithFixedDelay(new ClenupDumpsTask(), 20, 60, TimeUnit.SECONDS);
}
@Override
public void resetDatabase() throws EngineException
{
authz.checkAuthorization(AuthzCapability.maintenance);
bulkProcessing.removeAllRules();
initDb.cleanOrDelete();
endpointMan.undeployAll();
engineInit.initializeDatabaseContents();
}
@Override
@Transactional
public File exportDb(DBDumpContentElements content) throws EngineException
{
authz.checkAuthorization(AuthzCapability.maintenance);
try
{
File exportFile = createExportFile();
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(exportFile));
dbDump.store(os, content);
return exportFile;
} catch (JsonGenerationException e)
{
throw new InternalException("Error creating JSON from database contents", e);
} catch (IOException e)
{
throw new InternalException("Error writing database contents to disk", e);
}
}
@Override
public void importDb(File from) throws EngineException
{
authz.checkAuthorization(AuthzCapability.maintenance);
tx.runInTransaction(() -> {
try
{
BufferedInputStream is = new BufferedInputStream(new FileInputStream(from));
List dbDumpElements = dbDump.getDBDumpElements(is);
initDb.deletePreImport(dbDumpElements);
dbDump.load(new BufferedInputStream(is));
} catch (Exception e)
{
throw new InternalException("Database import failed. " +
"Database should not be changed.", e);
}
initDb.runPostImportCleanup();
});
endpointMan.undeployAll();
engineInit.initializeDatabaseContents();
}
private class ClenupDumpsTask implements Runnable
{
private static final long DUMP_STORE_TIME = 600000;
@Override
public void run()
{
File exportsDirectory = getExportDirectory();
File[] files = exportsDirectory.listFiles();
if (files == null)
{
log.error("Can not list exports directory " + exportsDirectory + "; cleanup failed");
return;
}
long now = System.currentTimeMillis();
for (File file: files)
{
if (file.lastModified() + DUMP_STORE_TIME < now)
{
log.debug("Removing the old, temporary, database dump from the workspace: "
+ file);
file.delete();
continue;
}
}
}
}
@Override
public void reloadConfig() throws EngineException
{
authz.checkAuthorization(AuthzCapability.maintenance);
try
{
config.reload();
} catch (ConfigurationException e)
{
throw new InternalException("Error in configuration file", e);
} catch (IOException e)
{
throw new InternalException("Error reading configuration file", e);
}
}
@Override
public String loadConfigurationFile(String path) throws EngineException
{
authz.checkAuthorization(AuthzCapability.maintenance);
File f = new File(path);
try
{
return FileUtils.readFileToString(f, Charset.defaultCharset());
} catch (IOException e)
{
throw new InternalException("Error loading configuration file " + path, e);
}
}
private File getExportDirectory()
{
File workspace = config.getFileValue(UnityServerConfiguration.WORKSPACE_DIRECTORY, true);
File exportDir = new File(workspace, ServerManagement.DB_DUMP_DIRECTORY);
if (!exportDir.exists())
exportDir.mkdir();
return exportDir;
}
private String getExportFilePrefix()
{
return "export-";
}
private String getExportFileSuffix()
{
return ".json";
}
private File createExportFile() throws IOException
{
File exportDir = getExportDirectory();
String[] list = exportDir.list();
if (list == null)
throw new IOException("Can not list database dumps directory, I/O error");
if (list.length > 1)
throw new IOException("Maximum number of database dumps was reached. " +
"Subsequent dumps can be created in few minutes.");
return File.createTempFile(getExportFilePrefix(), getExportFileSuffix(), exportDir);
}
}