X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.init%2Fsrc%2Forg%2Fargeo%2Finit%2FRuntimeManagerMain.java;h=27778427c2df7638e8e91d593913a4d3be50947c;hb=58ec99a5ae0a63167bf378d98751a8066271758d;hp=5a8331dfeeeb2cf2b4b0e32f2fd6139a7d860838;hpb=4f899ffcfd5652eb13748535353d2bd09f568bbc;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.init/src/org/argeo/init/RuntimeManagerMain.java b/org.argeo.init/src/org/argeo/init/RuntimeManagerMain.java index 5a8331dfe..27778427c 100644 --- a/org.argeo.init/src/org/argeo/init/RuntimeManagerMain.java +++ b/org.argeo.init/src/org/argeo/init/RuntimeManagerMain.java @@ -1,81 +1,59 @@ package org.argeo.init; -import static org.argeo.api.init.InitConstants.SYMBOLIC_NAME_INIT; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; import java.lang.System.Logger; import java.lang.System.Logger.Level; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; import java.util.Map; -import java.util.Properties; -import java.util.TreeMap; -import java.util.function.Consumer; import org.argeo.api.init.InitConstants; -import org.argeo.api.init.RuntimeContext; import org.argeo.api.init.RuntimeManager; import org.argeo.init.logging.ThinLoggerFinder; import org.argeo.init.osgi.OsgiRuntimeContext; import org.argeo.internal.init.InternalState; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.FrameworkEvent; -import org.osgi.framework.launch.Framework; /** * Dynamically configures and launches multiple runtimes, coordinated by a main * one. */ -public class RuntimeManagerMain implements RuntimeManager { +public class RuntimeManagerMain { private final static Logger logger = System.getLogger(RuntimeManagerMain.class.getName()); private final static String ENV_STATE_DIRECTORY = "STATE_DIRECTORY"; -// private final static String ENV_CONFIGURATION_DIRECTORY = "CONFIGURATION_DIRECTORY"; -// private final static String ENV_CACHE_DIRECTORY = "CACHE_DIRECTORY"; + private final static String ENV_CONFIGURATION_DIRECTORY = "CONFIGURATION_DIRECTORY"; + private final static String ENV_CACHE_DIRECTORY = "CACHE_DIRECTORY"; private final static long RUNTIME_SHUTDOWN_TIMEOUT = 60 * 1000; - private final static String JVM_ARGS = "jvm.args"; - - private Path baseConfigArea; - private Path baseStateArea; private Map configuration = new HashMap<>(); - private Map runtimeContexts = new TreeMap<>(); + RuntimeManagerMain(Path configArea, Path stateArea, Path cacheArea) { + RuntimeManager.loadDefaults(configuration); - RuntimeManagerMain(Path configArea, Path stateArea) { - loadConfig(configArea, configuration); - configuration.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.toUri().toString()); - this.baseConfigArea = configArea.getParent(); - this.baseStateArea = stateArea.getParent(); + configuration.put(InitConstants.PROP_OSGI_USE_SYSTEM_PROPERTIES, "false"); - logger.log(Level.TRACE, () -> "Runtime manager configuration: " + configuration); + configuration.put(InitConstants.PROP_ARGEO_CONFIG_AREA, configArea.toString()); + configuration.put(InitConstants.PROP_ARGEO_STATE_AREA, stateArea.toString()); + configuration.put(InitConstants.PROP_ARGEO_CACHE_AREA, cacheArea.toString()); + + configuration.put(InitConstants.PROP_OSGI_SHARED_CONFIGURATION_AREA, configArea.toUri().toString()); + configuration.put(InitConstants.PROP_OSGI_SHARED_CONFIGURATION_AREA_RO, "true"); -// System.out.println("java.library.path=" + System.getProperty("java.library.path")); + configuration.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, + cacheArea.resolve(RuntimeManager.OSGI_STORAGE_DIRNAME).toUri().toString()); + configuration.put(InitConstants.PROP_OSGI_INSTANCE_AREA, + stateArea.resolve(RuntimeManager.DATA).toUri().toString()); + + // TODO find a cleaner way to configure Jackrabbit indexes + configuration.put("argeo.node.repo.indexesBase", cacheArea.resolve("indexes").toString()); + + logger.log(Level.TRACE, () -> "Runtime manager configuration: " + configuration); } public void run() { -// try { -// for (Path p : Files.newDirectoryStream(Paths.get("/usr/local/lib/a2"), "*.so")) { -// try { -// System.load(p.toString()); -// } catch (UnsatisfiedLinkError e) { -// e.printStackTrace(); -// } -// } -// } catch (IOException e) { -// e.printStackTrace(); -// } - - OsgiRuntimeContext managerRuntimeContext = new OsgiRuntimeContext(configuration); + OsgiRuntimeContext managerRuntimeContext = new OsgiRuntimeContext(OsgiRuntimeContext.loadFrameworkFactory(), + configuration); try { managerRuntimeContext.run(); InternalState.setMainRuntimeContext(managerRuntimeContext); @@ -83,18 +61,14 @@ public class RuntimeManagerMain implements RuntimeManager { // shutdown on exit Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(), "Runtime shutdown")); - BundleContext bc = managerRuntimeContext.getFramework().getBundleContext(); - // uninstall init as a bundle since it will be available via OSGi system - for (Bundle b : bc.getBundles()) { - if (b.getSymbolicName().equals(SYMBOLIC_NAME_INIT)) { - b.uninstall(); - } - } - bc.registerService(RuntimeManager.class, this, new Hashtable<>(configuration)); +// BundleContext bc = managerRuntimeContext.getFramework().getBundleContext(); +// // uninstall init as a bundle since it will be available via OSGi system +// OsgiBoot.uninstallBundles(bc, SYMBOLIC_NAME_INIT); +// bc.registerService(RuntimeManager.class, this, new Hashtable<>(configuration)); logger.log(Level.DEBUG, "Registered runtime manager"); managerRuntimeContext.waitForStop(0); - } catch (InterruptedException | BundleException e) { + } catch (InterruptedException e) { e.printStackTrace(); System.exit(1); } @@ -102,21 +76,6 @@ public class RuntimeManagerMain implements RuntimeManager { } protected void shutdown() { - // shutdowm runtimes - Map shutdowning = new HashMap<>(runtimeContexts); - for (String id : new HashSet<>(runtimeContexts.keySet())) { - logger.log(Logger.Level.DEBUG, "Shutting down runtime " + id + " ..."); - closeRuntime(id, true); - } - for (String id : shutdowning.keySet()) - try { - RuntimeContext runtimeContext = shutdowning.get(id); - runtimeContext.waitForStop(RUNTIME_SHUTDOWN_TIMEOUT); - } catch (InterruptedException e) { - // silent - } catch (Exception e) { - logger.log(Logger.Level.DEBUG, "Cannot wait for " + id + " to shutdown", e); - } // shutdown manager runtime try { InternalState.getMainRuntimeContext().close(); @@ -129,102 +88,28 @@ public class RuntimeManagerMain implements RuntimeManager { } } - public static void loadConfig(Path dir, Map config) { - try { -// System.out.println("Load from " + dir); - Path jvmArgsPath = dir.resolve(JVM_ARGS); - if (!Files.exists(jvmArgsPath)) { - // load from parent directory - loadConfig(dir.getParent(), config); - } - - if (Files.exists(dir)) - for (Path p : Files.newDirectoryStream(dir, "*.ini")) { - Properties props = new Properties(); - try (InputStream in = Files.newInputStream(p)) { - props.load(in); - } - for (Object key : props.keySet()) { - config.put(key.toString(), props.getProperty(key.toString())); - } - } - } catch (IOException e) { - throw new UncheckedIOException("Cannot load configuration from " + dir, e); - } - } - - OsgiRuntimeContext loadRuntime(String relPath, Consumer> configCallback) { - closeRuntime(relPath, false); - Path stateArea = baseStateArea.resolve(relPath); - Path configArea = baseConfigArea.resolve(relPath); - Map config = new HashMap<>(); - loadConfig(configArea, config); - config.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.toUri().toString()); - - if (configCallback != null) - configCallback.accept(config); - - // use config area if instance area is not set - if (!config.containsKey(InitConstants.PROP_OSGI_INSTANCE_AREA)) - config.put(InitConstants.PROP_OSGI_INSTANCE_AREA, config.get(InitConstants.PROP_OSGI_CONFIGURATION_AREA)); - - OsgiRuntimeContext runtimeContext = new OsgiRuntimeContext(config); - runtimeContexts.put(relPath, runtimeContext); - return runtimeContext; - } - - public void startRuntime(String relPath, Consumer> configCallback) { - OsgiRuntimeContext runtimeContext = loadRuntime(relPath, configCallback); - runtimeContext.run(); - Framework framework = runtimeContext.getFramework(); - if (framework != null) {// in case the framework has closed very quickly after run - framework.getBundleContext().addFrameworkListener((e) -> { - if (e.getType() >= FrameworkEvent.STOPPED) { - logger.log(Level.DEBUG, "Externally stopped runtime " + relPath + ". Unregistering...", e); - runtimeContexts.remove(relPath); - } - }); - } else { - closeRuntime(relPath, false); - } - } - - public void closeRuntime(String relPath, boolean async) { - if (!runtimeContexts.containsKey(relPath)) - return; - RuntimeContext runtimeContext = runtimeContexts.get(relPath); - try { - runtimeContext.close(); - if (!async) { - runtimeContext.waitForStop(RUNTIME_SHUTDOWN_TIMEOUT); - System.gc(); - } - } catch (Exception e) { - logger.log(Level.ERROR, "Cannot close runtime context " + relPath, e); - } finally { - runtimeContexts.remove(relPath); - } - - } - public static void main(String[] args) { ThinLoggerFinder.reloadConfiguration(); logger.log(Logger.Level.DEBUG, () -> "Argeo Init starting with PID " + ProcessHandle.current().pid()); - Map env = System.getenv(); -// for (String envName : new TreeSet<>(env.keySet())) { -// System.out.format("%s=%s%n", envName, env.get(envName)); -// } - if (args.length < 1) - throw new IllegalArgumentException("A relative configuration directory must be specified"); - Path configArea = Paths.get(System.getProperty("user.dir"), args[0]); - // System.out.println("## Start with PID " + ProcessHandle.current().pid()); - // System.out.println("user.dir=" + System.getProperty("user.dir")); - - Path stateArea = Paths.get(env.get(ENV_STATE_DIRECTORY)); - - RuntimeManagerMain runtimeManager = new RuntimeManagerMain(configArea, stateArea); + Path writableArea = getLocalPath(InitConstants.PROP_ARGEO_STATE_AREA, ENV_STATE_DIRECTORY, null); + Path configArea = getLocalPath(InitConstants.PROP_ARGEO_CONFIG_AREA, ENV_CONFIGURATION_DIRECTORY, null); + Path cacheArea = getLocalPath(InitConstants.PROP_ARGEO_CACHE_AREA, ENV_CACHE_DIRECTORY, writableArea); + RuntimeManagerMain runtimeManager = new RuntimeManagerMain(configArea, writableArea, cacheArea); runtimeManager.run(); } + private static Path getLocalPath(String systemProperty, String environmentVariable, Path defaultPath) { + String prop = System.getProperty(systemProperty); + if (prop != null) + return Paths.get(prop); + String env = System.getenv().get(environmentVariable); + if (env != null) + return Paths.get(env); + if (defaultPath != null) + return defaultPath; + throw new IllegalStateException("No local path set with system property " + systemProperty + + " or environment variable " + environmentVariable); + // TODO allocate a temporary directory? or defaults based on working directory ? + } }