diff --git a/conf/core/cache.ccf b/conf/core/cache.ccf index 672c798d126e9c759e0c7a59a81702733aa4e7b3..821e5d7862efb21e0aa13f8410886c6c14b10a7c 100644 --- a/conf/core/cache.ccf +++ b/conf/core/cache.ccf @@ -4,30 +4,46 @@ jcs.default.cacheattributes.MaxObjects=1000 jcs.default.elementattributes=org.apache.commons.jcs.engine.ElementAttributes # Caching of the backend transactions -jcs.region.BACKEND_UserRoles.cacheattributes.MaxObjects=100 -jcs.region.BACKEND_Users.cacheattributes.MaxObjects=100 -jcs.region.BACKEND_PermissionRules.cacheattributes.MaxObjects=1000 +jcs.region.BACKEND_UserRoles +jcs.region.BACKEND_UserRoles.cacheattributes.MaxObjects=101 -jcs.region.BACKEND_SparseEntities.cacheattributes.MaxObjects=1000 -jcs.region.BACKEND_EntityProperties.cacheattributes.MaxObjects=1000 -jcs.region.BACKEND_EntityParents.cacheattributes.MaxObjects=1000 -jcs.region.BACKEND_SparseFileRecordsByPath.cacheattributes.MaxObjects=1000 +jcs.region.BACKEND_Users +jcs.region.BACKEND_Users.cacheattributes.MaxObjects=102 -jcs.region.BACKEND_JobRules.cacheattributes.MaxObjects=100 +jcs.region.BACKEND_PermissionRules +jcs.region.BACKEND_PermissionRules.cacheattributes.MaxObjects=1001 + +jcs.region.BACKEND_EntityProperties +jcs.region.BACKEND_EntityProperties.cacheattributes.MaxObjects=1003 + +jcs.region.BACKEND_EntityParents +jcs.region.BACKEND_EntityParents.cacheattributes.MaxObjects=1004 + +jcs.region.BACKEND_SparseFileRecordsByPath +jcs.region.BACKEND_SparseFileRecordsByPath.cacheattributes.MaxObjects=1005 + +jcs.region.BACKEND_JobRules +jcs.region.BACKEND_JobRules.cacheattributes.MaxObjects=103 + +jcs.region.BACKEND_SparseEntities +jcs.region.BACKEND_SparseEntities.cacheattributes.MaxObjects=1002 # PAM UserSource Caching: Cached Items expire after 60 seconds if they are not requested (idle) and after 600 seconds max. # PAM_UnixUserGroups +jcs.region.PAM_UnixUserGroups jcs.region.PAM_UnixUserGroups.elementattributes.IsEternal=false -jcs.region.PAM_UnixUserGroups.elementattributes.MaxLife=600 -jcs.region.PAM_UnixUserGroups.elementattributes.IdleTime=60 +jcs.region.PAM_UnixUserGroups.elementattributes.MaxLife=601 +jcs.region.PAM_UnixUserGroups.elementattributes.IdleTime=61 # PAM_UnixUserExists +jcs.region.PAM_UnixUserExists jcs.region.PAM_UnixUserExists.elementattributes.IsEternal=false -jcs.region.PAM_UnixUserExists.elementattributes.MaxLife=600 -jcs.region.PAM_UnixUserExists.elementattributes.IdleTime=60 +jcs.region.PAM_UnixUserExists.elementattributes.MaxLife=599 +jcs.region.PAM_UnixUserExists.elementattributes.IdleTime=59 # PAM_Authentication +jcs.region.PAM_Authentication jcs.region.PAM_Authentication.elementattributes.IsEternal=false jcs.region.PAM_Authentication.elementattributes.MaxLife=600 jcs.region.PAM_Authentication.elementattributes.IdleTime=60 diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java index c68ae31c1fbfe8487bce082e545222ec9647b188..19560aacd50ede38471c0fb02e31fd4560e9d8bb 100644 --- a/src/main/java/caosdb/server/CaosDBServer.java +++ b/src/main/java/caosdb/server/CaosDBServer.java @@ -27,7 +27,7 @@ import caosdb.server.accessControl.OneTimeTokenRealm; import caosdb.server.accessControl.Principal; import caosdb.server.accessControl.SessionToken; import caosdb.server.accessControl.SessionTokenRealm; -import caosdb.server.database.Database; +import caosdb.server.database.BackendTransaction; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.RetrieveDatatypes; import caosdb.server.database.misc.TransactionBenchmark; @@ -58,7 +58,7 @@ import caosdb.server.resource.transaction.EntityResource; import caosdb.server.terminal.CaosDBTerminal; import caosdb.server.terminal.StatsPanel; import caosdb.server.terminal.SystemErrPanel; -import caosdb.server.utils.ChecksumUpdater; +import caosdb.server.transaction.ChecksumUpdater; import caosdb.server.utils.FileUtils; import caosdb.server.utils.Initialization; import caosdb.server.utils.NullPrintStream; @@ -279,8 +279,10 @@ public class CaosDBServer extends Application { try { // init backend if (START_BACKEND) { + BackendTransaction.init(); + // init benchmark - TransactionBenchmark.getInstance(); + TransactionBenchmark.getRootInstance(); // Role Role.init(init.getAccess()); @@ -316,7 +318,7 @@ public class CaosDBServer extends Application { Thread.sleep(1000); // add Benchmark - StatsPanel.addStat("TransactionBenchmark", TransactionBenchmark.getInstance()); + StatsPanel.addStat("TransactionBenchmark", TransactionBenchmark.getRootInstance()); } else { logger.info("NO GUI"); System.setOut(new NullPrintStream()); @@ -357,7 +359,9 @@ public class CaosDBServer extends Application { private static void initDatatypes(final Access access) throws Exception { final RetrieveDatatypes t = new RetrieveDatatypes(); - final Container<? extends EntityInterface> dts = Database.execute(t, access).getDatatypes(); + t.setAccess(access); + t.executeTransaction(); + final Container<? extends EntityInterface> dts = t.getDatatypes(); AbstractDatatype.initializeDatatypes(dts); } diff --git a/src/main/java/caosdb/server/FileSystem.java b/src/main/java/caosdb/server/FileSystem.java index 44b663e958841ac92a24f44244096034eb9154c3..c46f0f644442a5df6c2363dedfacb38025cacde4 100644 --- a/src/main/java/caosdb/server/FileSystem.java +++ b/src/main/java/caosdb/server/FileSystem.java @@ -24,9 +24,9 @@ package caosdb.server; -import caosdb.server.database.Database; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.GetFileRecordByPath; +import caosdb.server.database.misc.TransactionBenchmark; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.FileProperties; import caosdb.server.entity.Message; @@ -300,8 +300,8 @@ public class FileSystem { * @return * @throws Message */ - public static boolean checkTarget(final EntityInterface entity, final Access access) - throws Message { + public static boolean checkTarget( + final EntityInterface entity, final Access access, TransactionBenchmark b) throws Message { final FileProperties file = entity.getFileProperties(); // target file name = where the file is to be stored. @@ -321,8 +321,10 @@ public class FileSystem { if (file.getFile() != null && file.getFile().equals(target)) { return true; } else { - final GetFileRecordByPath t = - Database.execute(new GetFileRecordByPath(file.getPath()), access); + final GetFileRecordByPath t = new GetFileRecordByPath(file.getPath()); + t.setAccess(access); + t.setTransactionBenchmark(b); + t.executeTransaction(); if (t.getEntity() != null) { final Integer foreign = t.getId(); if (foreign != null && foreign.equals(entity.getId())) { diff --git a/src/main/java/caosdb/server/accessControl/Pam.java b/src/main/java/caosdb/server/accessControl/Pam.java index 99f68faadc15c15d9404a504d15669f0c2604ea3..d640a66f4fffdb6254c7d11d696a1f2a1bf5ebf6 100644 --- a/src/main/java/caosdb/server/accessControl/Pam.java +++ b/src/main/java/caosdb/server/accessControl/Pam.java @@ -108,6 +108,10 @@ public class Pam implements UserSource { public static final String KEY_EMAIL = "email"; public static final String REGEX_SPLIT_CSV = "\\s*,\\s*"; + public static final String CACHE_REGION_GROUPS = "PAM_UnixUserGroups"; + public static final String CACHE_REGION_USER_EXIST = "PAM_UnixUserExists"; + public static final String CACHE_REGION_AUTH = "PAM_Authentication"; + private String[] EXCLUDE_USERS = null; private String[] INCLUDE_USERS = null; private String[] EXCLUDE_GROUPS = null; @@ -117,9 +121,9 @@ public class Pam implements UserSource { /* Caches for groups, user-existence and password validation */ - private ICacheAccess<String, HashSet<String>> groupsCache = Cache.getCache("PAM_UnixUserGroups"); - private ICacheAccess<String, Boolean> userExistsCache = Cache.getCache("PAM_UnixUserExists"); - private ICacheAccess<String, Boolean> passwordValidCache = Cache.getCache("PAM_Authentication"); + private ICacheAccess<String, HashSet<String>> groupsCache = Cache.getCache(CACHE_REGION_GROUPS); + private ICacheAccess<String, Boolean> userExistsCache = Cache.getCache(CACHE_REGION_USER_EXIST); + private ICacheAccess<String, Boolean> passwordValidCache = Cache.getCache(CACHE_REGION_AUTH); @Override public void setMap(final Map<String, String> map) { diff --git a/src/main/java/caosdb/server/caching/JCSCacheHelper.java b/src/main/java/caosdb/server/caching/JCSCacheHelper.java index dab2b77ceaab3d0caaf49d798a4819ca890b5e82..55efaa191bcb777bd63881dfbd72cd292808064c 100644 --- a/src/main/java/caosdb/server/caching/JCSCacheHelper.java +++ b/src/main/java/caosdb/server/caching/JCSCacheHelper.java @@ -58,11 +58,18 @@ public class JCSCacheHelper implements CacheHelper { // configure JCS static { + init(); + } + + public static void init() { + init(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_CONF_LOC)); + } + + public static void init(String configFileLocation) { Properties config = null; try { Properties p = new Properties(); - final InputStream is = - new FileInputStream(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_CONF_LOC)); + final InputStream is = new FileInputStream(configFileLocation); p.load(is); is.close(); config = p; diff --git a/src/main/java/caosdb/server/database/BackendTransaction.java b/src/main/java/caosdb/server/database/BackendTransaction.java index 4899996e6c4df2b18837259112ac7e90c534b793..42cce21af9f7e851d27c960b9704aae46b96350f 100644 --- a/src/main/java/caosdb/server/database/BackendTransaction.java +++ b/src/main/java/caosdb/server/database/BackendTransaction.java @@ -130,21 +130,21 @@ public abstract class BackendTransaction implements Undoable { private final UndoHandler undoHandler = new UndoHandler(); private Access access; - BackendTransaction parent = null; + private TransactionBenchmark benchmark; private static HashMap< Class<? extends BackendTransactionImpl>, Class<? extends BackendTransactionImpl>> impl = new HashMap<>(); protected abstract void execute(); - final void executeTransaction() { + public final void executeTransaction() { final long t1 = System.currentTimeMillis(); execute(); final long t2 = System.currentTimeMillis(); - TransactionBenchmark.getInstance().addBenchmark(this, t2 - t1); + this.addMeasurement(this, t2 - t1); } - private static void init() { + public static void init() { if (impl.isEmpty()) { setImpl(DeleteEntityPropertiesImpl.class, MySQLDeleteEntityProperties.class); setImpl(DeleteSparseEntityImpl.class, MySQLDeleteSparseEntity.class); @@ -202,11 +202,13 @@ public abstract class BackendTransaction implements Undoable { assert t != this; this.undoHandler.append(t); t.setAccess(this.access); - t.parent = this; + if (benchmark != null) { + t.setTransactionBenchmark(benchmark.getBenchmark(t.getClass())); + } final long t1 = System.currentTimeMillis(); t.execute(); final long t2 = System.currentTimeMillis(); - TransactionBenchmark.getInstance().addBenchmark(t, t2 - t1); + this.addMeasurement(t, t2 - t1); return t; } @@ -215,7 +217,7 @@ public abstract class BackendTransaction implements Undoable { impl.put(k, l); } - void setAccess(final Access access) { + public void setAccess(final Access access) { this.access = access; } @@ -223,10 +225,14 @@ public abstract class BackendTransaction implements Undoable { protected <T extends BackendTransactionImpl> T getImplementation(final Class<T> clz) { init(); try { - final T ret = (T) impl.get(clz).getConstructor(Access.class).newInstance(this.access); + Class<?> implclz = impl.get(clz); + final T ret = (T) implclz.getConstructor(Access.class).newInstance(this.access); if (ret instanceof Undoable) { this.undoHandler.append((Undoable) ret); } + if (benchmark != null) { + ret.setTransactionBenchmark(benchmark.getBenchmark(ret.getClass())); + } return ret; } catch (final Exception e) { throw new TransactionException(e); @@ -253,7 +259,16 @@ public abstract class BackendTransaction implements Undoable { @Override public String toString() { - return (this.parent != null ? this.parent.toString() + " -> " : "") - + this.getClass().getSimpleName(); + return this.getClass().getSimpleName(); + } + + public void setTransactionBenchmark(TransactionBenchmark b) { + this.benchmark = b; + } + + public void addMeasurement(Object o, long time) { + if (this.benchmark != null) { + this.benchmark.addMeasurement(o, time); + } } } diff --git a/src/main/java/caosdb/server/database/Database.java b/src/main/java/caosdb/server/database/Database.java index c30b68c7c16cecf4d59f3d6adda10e066a42763f..d67acdff9d8fbacdbdefdfdeb5013c3838156461 100644 --- a/src/main/java/caosdb/server/database/Database.java +++ b/src/main/java/caosdb/server/database/Database.java @@ -22,18 +22,17 @@ */ package caosdb.server.database; -import caosdb.server.database.access.Access; -import caosdb.server.database.misc.RollBackHandler; - public class Database { - public static <K extends BackendTransaction> K execute(final K t, final Access access) { - - final RollBackHandler handler = (RollBackHandler) access.getHelper("RollBack"); - handler.append(t); - t.setAccess(access); - - t.executeTransaction(); - return t; - } + // public static <K extends BackendTransaction> K execute( + // final K t, final Access access, TransactionBenchmark b) { + // + // final RollBackHandler handler = (RollBackHandler) access.getHelper("RollBack"); + // handler.append(t); + // t.setAccess(access); + // + // t.setTransactionBenchmark(b); + // t.executeTransaction(); + // return t; + // } } diff --git a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java index 329a4e81b211815ac3ab5059e4b789eed9dce1b9..8b9a547bac69cf221dbf7c204a93e95326bb484c 100644 --- a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java +++ b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java @@ -49,6 +49,7 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev final PreparedStatement prepareStatement = prepareStatement(stmtStr); final List<FlatProperty> props = retrieveFlatPropertiesStage1(0, entity, prepareStatement); + final ArrayList<ProtoProperty> protos = new ArrayList<ProtoProperty>(); for (final FlatProperty p : props) { final ProtoProperty proto = new ProtoProperty(); @@ -56,6 +57,7 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev final List<FlatProperty> subProps = retrieveFlatPropertiesStage1(entity, p.id, prepareStatement); + proto.subProperties = subProps; protos.add(proto); @@ -80,7 +82,10 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev } stmt.setInt(2, entity); + long t1 = System.currentTimeMillis(); rs = stmt.executeQuery(); + long t2 = System.currentTimeMillis(); + addMeasurement(this.getClass().getSimpleName() + ".retrieveFlatPropertiesStage1", t2 - t1); final List<FlatProperty> props = DatabaseUtils.parsePropertyResultset(rs); @@ -107,7 +112,10 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev try { stmt2.setInt(1, domain); stmt2.setInt(2, entity); + long t1 = System.currentTimeMillis(); rs = stmt2.executeQuery(); + long t2 = System.currentTimeMillis(); + addMeasurement(this.getClass().getSimpleName() + ".retrieveOverrides", t2 - t1); DatabaseUtils.parseOverrides(props, rs); } finally { if (rs != null && !rs.isClosed()) { diff --git a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLTransaction.java b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLTransaction.java index 1eb398634a665672bfbd266c51d819565fbea04d..f116a136c1b3e1942ddc2400139db3c82210fac8 100644 --- a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLTransaction.java +++ b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLTransaction.java @@ -23,13 +23,16 @@ package caosdb.server.database.backend.implementation.MySQL; import caosdb.server.database.access.Access; +import caosdb.server.database.backend.interfaces.BackendTransactionImpl; import caosdb.server.database.misc.DBHelper; +import caosdb.server.database.misc.TransactionBenchmark; import java.sql.PreparedStatement; import java.sql.SQLException; -public class MySQLTransaction { +public class MySQLTransaction implements BackendTransactionImpl { protected final Access access; + private TransactionBenchmark benchmark; public MySQLTransaction(final Access access) { this.access = access; @@ -54,4 +57,20 @@ public class MySQLTransaction { public final void undo() {} public final void cleanUp() {} + + @Override + public TransactionBenchmark getBenchmark() { + return benchmark; + } + + @Override + public void setTransactionBenchmark(TransactionBenchmark b) { + this.benchmark = b; + } + + protected void addMeasurement(String string, long l) { + if (benchmark != null) { + benchmark.addMeasurement(string, l); + } + } } diff --git a/src/main/java/caosdb/server/database/backend/implementation/UnixFileSystem/UnixFileSystemTransaction.java b/src/main/java/caosdb/server/database/backend/implementation/UnixFileSystem/UnixFileSystemTransaction.java index 851e0b0d6bfdbe0b29f9ce8ec51d26f1b26954e8..63e87d6a4f968d3d4833111f9ca9875daf18d9cc 100644 --- a/src/main/java/caosdb/server/database/backend/implementation/UnixFileSystem/UnixFileSystemTransaction.java +++ b/src/main/java/caosdb/server/database/backend/implementation/UnixFileSystem/UnixFileSystemTransaction.java @@ -24,19 +24,27 @@ package caosdb.server.database.backend.implementation.UnixFileSystem; import caosdb.server.FileSystem; import caosdb.server.database.access.Access; +import caosdb.server.database.backend.interfaces.BackendTransactionImpl; import caosdb.server.database.misc.DBHelper; +import caosdb.server.database.misc.TransactionBenchmark; import caosdb.server.entity.Message; import java.io.File; import java.io.IOException; -public abstract class UnixFileSystemTransaction { +public abstract class UnixFileSystemTransaction implements BackendTransactionImpl { private final Access access; + private TransactionBenchmark benchmark; public UnixFileSystemTransaction(final Access access) { this.access = access; } + @Override + public void setTransactionBenchmark(TransactionBenchmark b) { + this.benchmark = b; + } + protected File getFile(final String path) throws IOException, Message { return new File(getHelper().getBasePath() + path); } @@ -56,4 +64,9 @@ public abstract class UnixFileSystemTransaction { return (UnixFileSystemHelper) dbHelper; } } + + @Override + public TransactionBenchmark getBenchmark() { + return benchmark; + } } diff --git a/src/main/java/caosdb/server/database/backend/interfaces/BackendTransactionImpl.java b/src/main/java/caosdb/server/database/backend/interfaces/BackendTransactionImpl.java index cc2af6e2d8a421eab23b466986413bf2819b10b5..d4751f94cda0b0bdea703d5f207527ea756681f3 100644 --- a/src/main/java/caosdb/server/database/backend/interfaces/BackendTransactionImpl.java +++ b/src/main/java/caosdb/server/database/backend/interfaces/BackendTransactionImpl.java @@ -22,4 +22,11 @@ */ package caosdb.server.database.backend.interfaces; -public interface BackendTransactionImpl {} +import caosdb.server.database.misc.TransactionBenchmark; + +public interface BackendTransactionImpl { + + public void setTransactionBenchmark(TransactionBenchmark b); + + public TransactionBenchmark getBenchmark(); +} diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java index 650cae3676ed2b6b50f86c76a5ce92b195290fc3..487feb56cf848e948fcacb8f33f49e4a0bc2267d 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java +++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java @@ -40,8 +40,9 @@ public class RetrieveProperties extends CacheableBackendTransaction<Integer, ArrayList<ProtoProperty>> { private final EntityInterface entity; + public static final String CACHE_REGION = "BACKEND_EntityProperties"; private static final ICacheAccess<Integer, ArrayList<ProtoProperty>> cache = - Cache.getCache("BACKEND_EntityProperties"); + Cache.getCache(CACHE_REGION); /** * To be called by DeleteEntityProperties on execution. diff --git a/src/main/java/caosdb/server/database/misc/TransactionBenchmark.java b/src/main/java/caosdb/server/database/misc/TransactionBenchmark.java index 80b60e80893e8b512abededb345e286438ec22bb..f7c9e80f811418392b6567fcda5bfb8a9948bbff 100644 --- a/src/main/java/caosdb/server/database/misc/TransactionBenchmark.java +++ b/src/main/java/caosdb/server/database/misc/TransactionBenchmark.java @@ -27,49 +27,122 @@ import caosdb.server.ServerProperties; import caosdb.server.utils.CronJob; import caosdb.server.utils.Info; import caosdb.server.utils.ServerStat; +import java.io.Serializable; import java.util.Date; import java.util.HashMap; import java.util.Locale; +import java.util.Map; import java.util.Map.Entry; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.jdom2.Element; -public class TransactionBenchmark implements ServerStat { +class Counter implements Serializable { + private static final long serialVersionUID = 8679355597595634790L; + private int c; - private static final long serialVersionUID = -8916163825450491067L; - private long since = System.currentTimeMillis(); - private final HashMap<String, Integer> counts = new HashMap<String, Integer>(); - private final HashMap<String, Long> acc = new HashMap<String, Long>(); - private transient boolean synced = false; - private static final TransactionBenchmark instance = new TransactionBenchmark(); - private static final boolean isActive = - Boolean.valueOf( - CaosDBServer.getServerProperty(ServerProperties.KEY_TRANSACTION_BENCHMARK_ENABLED) - .toLowerCase()); + public Counter(int initial) { + this.c = initial; + } - static { - if (isActive) { - instance.init(); - } + public void add(int inc) { + this.c += inc; + } + + public int toInteger() { + return c; + } +} + +class Timer implements Serializable { + private static final long serialVersionUID = 7895352555775799409L; + private long c; + + public Timer(long initial) { + this.c = initial; + } + + public void add(long inc) { + this.c += inc; + } + + public long toLong() { + return c; + } +} + +class Measurement implements Serializable { + private static final long serialVersionUID = -2429348657382168470L; + private final Timer timer; + private final Counter counter; + private final String name; + + public Measurement(String name, long time, int count) { + this.name = name; + this.timer = new Timer(time); + this.counter = new Counter(count); + } + + public void add(long time, int count) { + this.timer.add(time); + this.counter.add(count); + } + + public double getAvg() { + return (double) this.getAccTime() / this.getCount(); } + public StringBuilder toStringBuilder() { + StringBuilder sb = new StringBuilder(); + sb.append('#'); + sb.append(name); + sb.append(": "); + sb.append('('); + sb.append(this.getCount()); + sb.append(", "); + sb.append(this.getAccTime()); + sb.append(", "); + sb.append(String.format(Locale.US, "%3.2f", this.getAvg())); + sb.append(')'); + return sb; + } + + public int getCount() { + return counter.toInteger(); + } + + public long getAccTime() { + return timer.toLong(); + } + + public String getName() { + return this.name; + } +} + +class RootBenchmark extends TransactionBenchmark implements ServerStat { + + private static final long serialVersionUID = 8070554107783826602L; + private transient boolean synced = false; /** * Fetch old data (from before last shutdown) and fill it into this instance. * * @return */ - private TransactionBenchmark init() { - synchronized (this.counts) { + protected TransactionBenchmark init() { + final RootBenchmark b = this; + synchronized (this.measurements) { final Runnable updater = new Runnable() { @Override public void run() { try { - synchronized (TransactionBenchmark.this.counts) { - Info.syncDatabase(TransactionBenchmark.this); + synchronized (b.measurements) { + Info.getInstance().syncDatabase(b); } } catch (final Exception e) { - e.printStackTrace(); + logger.error(e); } } }; @@ -81,38 +154,166 @@ public class TransactionBenchmark implements ServerStat { return this; } + @Override + public final String getName() { + return "TransactionBenchmark"; + } + /** - * Add a benchmark for a certain object. The object will be toString()'ed. The string serves as a - * key. + * Add data from s to this instance. * - * @param object - * @param time + * @param s another TransactionBenchmark instance */ - public void addBenchmark(final Object object, final long time) { + @Override + public final void update(final ServerStat s) { + if (!this.synced && isActive) { + final RootBenchmark t = (RootBenchmark) s; + this.synced = true; + merge(this, t); + } + } + + public void merge(TransactionBenchmark target, TransactionBenchmark src) { if (isActive) { - addBenchmark(instance, object.toString(), time, 1); + target.since = Long.min(target.since, src.since); + synchronized (target.measurements) { + for (final Measurement m : src.measurements.values()) { + // add all measurements from src + target.addMeasurement(m); + } + } + + // merge subBenchmarks + synchronized (src.subBenchmarks) { + for (final SubBenchmark srcsb : src.getSubBenchmarks()) { + synchronized (target.subBenchmarks) { + if (target.subBenchmarks.containsKey(srcsb.getName())) { + merge(target.subBenchmarks.get(srcsb.getName()), srcsb); + } else { + target.subBenchmarks.put(srcsb.getName(), srcsb); + } + } + } + } } } +} - private static void addBenchmark( - final TransactionBenchmark b, final String name, final long time, final int count) { - synchronized (b.counts) { - if (b.counts.containsKey(name)) { - int c = b.counts.get(name); - c += count; - b.counts.put(name, c); - long a = b.acc.get(name); - a += time; - b.acc.put(name, a); - } else { - b.counts.put(name, count); - b.acc.put(name, time); +class SubBenchmark extends TransactionBenchmark { + + private static final long serialVersionUID = 323147917189195973L; + private final String name; + + public SubBenchmark(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } +} + +class JdomConverter { + public Element convert(Measurement m) { + Element ret = new Element("Measurement"); + ret.setAttribute("name", m.getName()); + ret.setAttribute("acc_time", Long.toString(m.getAccTime())); + ret.setAttribute("avg_time", String.format(Locale.US, "%3.2f", m.getAvg())); + ret.setAttribute("count", Integer.toString(m.getCount())); + return ret; + } + + public Element convert(TransactionBenchmark b) { + Element ret = new Element(b.getName()); + ret.setAttribute("since", new Date(b.since).toString()); + Iterable<Measurement> measurements = b.getMeasurements(); + + synchronized (measurements) { + for (Measurement m : measurements) { + ret.addContent(this.convert(m)); } } + + // tree view of subBenchmarks + Iterable<SubBenchmark> subBenchmarks = b.getSubBenchmarks(); + synchronized (subBenchmarks) { + for (SubBenchmark s : subBenchmarks) { + ret.addContent(this.convert(s)); + } + } + return ret; + } +} + +public abstract class TransactionBenchmark implements Serializable { + + private static final long serialVersionUID = -8916163825450491067L; + private static final TransactionBenchmark rootService = new RootBenchmark().init(); + public final transient Logger logger = LogManager.getLogger(getClass()); + protected static final transient boolean isActive = + Boolean.valueOf( + CaosDBServer.getServerProperty(ServerProperties.KEY_TRANSACTION_BENCHMARK_ENABLED) + .toLowerCase()); + + long since = System.currentTimeMillis(); + + protected final Map<String, Measurement> measurements = new HashMap<>(); + protected final Map<String, SubBenchmark> subBenchmarks = new HashMap<>(); + + protected TransactionBenchmark() {}; + + public Iterable<SubBenchmark> getSubBenchmarks() { + return this.subBenchmarks.values(); } - public static TransactionBenchmark getInstance() { - return instance; + public Iterable<Measurement> getMeasurements() { + return this.measurements.values(); + } + + /** + * Add a measurement. The object will be toString()'ed. The string serves as a key. + * + * @param object + * @param time + */ + public void addMeasurement(final Object object, final long time) { + this.addMeasurement(object, time, 1); + } + + /** + * Add a measurement. The object will be toString()'ed. The string serves as a key. + * + * @param object + * @param time + * @param count + */ + public void addMeasurement(final Object object, final long time, int count) { + if (isActive) { + String name = object.toString(); + + synchronized (this.measurements) { + Measurement existing = this.measurements.get(name); + if (existing == null) { + this.measurements.put(name, new Measurement(name, time, count)); + } else { + existing.add(time, count); + } + } + } + } + + /** + * Add a measurement. + * + * @param measurement + */ + public void addMeasurement(Measurement measurement) { + this.addMeasurement(measurement.getName(), measurement.getAccTime(), measurement.getCount()); + } + + public static TransactionBenchmark getRootInstance() { + return rootService; } @Override @@ -121,23 +322,11 @@ public class TransactionBenchmark implements ServerStat { final StringBuilder sb = new StringBuilder(); sb.append( "\nNAME: (execution count, accumulated execution time [ms], avg time per execution [ms])\n"); - synchronized (this.counts) { - for (final Entry<String, Integer> e : this.counts.entrySet()) { - final int c = e.getValue(); - final long acc = this.acc.get(e.getKey()); - final String name = e.getKey(); - final double avg = (double) acc / c; + synchronized (this.measurements) { + for (final Entry<String, Measurement> e : this.measurements.entrySet()) { + final Measurement m = e.getValue(); sb.append('\n'); - sb.append('#'); - sb.append(name); - sb.append(": "); - sb.append('('); - sb.append(c); - sb.append(", "); - sb.append(acc); - sb.append(", "); - sb.append(String.format(Locale.US, "%3.2f", avg)); - sb.append(')'); + sb.append(m.toStringBuilder()); } } return sb.toString(); @@ -147,73 +336,54 @@ public class TransactionBenchmark implements ServerStat { } public Element toElememt() { - final Element ret = new Element("TransactionBenchmark"); if (isActive) { - ret.setAttribute("since", new Date(this.since).toString()); - synchronized (this.counts) { - for (final Entry<String, Integer> e : this.counts.entrySet()) { - final int c = e.getValue(); - final long acc = TransactionBenchmark.this.acc.get(e.getKey()); - final String name = e.getKey(); - final double avg = (double) acc / c; - - final Element b = new Element("Benchmark"); - b.setAttribute("name", name); - b.setAttribute("execution_count", Integer.toString(c)); - b.setAttribute("accumulated_execution_time", Long.toString(acc) + "ms"); - b.setAttribute("avg_execution_time", String.format(Locale.US, "%3.2f", avg) + "ms"); - - ret.addContent(b); - } - } + return new JdomConverter().convert(this).setName("TransactionBenchmark"); } else { + final Element ret = new Element("TransactionBenchmark"); ret.setAttribute("info", "TransactionBenchmark is disabled."); + return ret; } - return ret; } - @Override - public String getName() { - return this.getClass().getSimpleName(); - } + public abstract String getName(); /** - * Add data from s to this instance + * Create a new independent {@link TransactionBenchmark}. * - * @param s another TransactionBenchmark instance + * <p>This is for starting a series of measurements from a clean slate. + * + * <p>However, the Measurements and Benchmarks are still recorded in the {@link RootBenchmark} + * too. + * + * @param name the name of the new {@link TransactionBenchmark}. + * @return a new {@link TransactionBenchmark} */ - @Override - public void update(final ServerStat s) { - final TransactionBenchmark t = (TransactionBenchmark) s; - if (!this.synced) { - this.synced = true; - this.since = t.since; - for (final String key : t.counts.keySet()) { - addBenchmark(this, key, t.acc.get(key), t.counts.get(key)); - } + public TransactionBenchmark createBenchmark(String name) { + synchronized (subBenchmarks) { + SubBenchmark b = new SubBenchmark(name); + subBenchmarks.put(name, b); + return b; } } - /** - * Get a SubBenchmark which can be used to produce a separate benchmark (e.g. for single - * transactions). The SubBenchmark's data will also available to the main benchmark. - * - * @return A SubBenchmark - */ - public static TransactionBenchmark getSubBenchmark() { - return new SubBenchmark(); + public TransactionBenchmark getBenchmark(String name) { + synchronized (subBenchmarks) { + SubBenchmark existing = subBenchmarks.get(name); + if (existing != null) { + return existing; + } else { + SubBenchmark b = new SubBenchmark(name); + subBenchmarks.put(name, b); + return b; + } + } } - private static class SubBenchmark extends TransactionBenchmark { - - private static final long serialVersionUID = 1L; + public TransactionBenchmark getBenchmark(Class<?> class1) { + return this.getBenchmark(class1.getSimpleName()); + } - @Override - public void addBenchmark(final Object object, final long time) { - if (isActive) { - super.addBenchmark(object, time); - TransactionBenchmark.addBenchmark(this, object.toString(), time, 1); - } - } + public TransactionBenchmark createBenchmark(Class<?> class1) { + return this.createBenchmark(class1.getSimpleName()); } } diff --git a/src/main/java/caosdb/server/entity/Role.java b/src/main/java/caosdb/server/entity/Role.java index 58cd7ba4f19ff89dad10a0a1c18fc3a417274255..79b6548f82f41568ec44c574c4ad35502379e58b 100644 --- a/src/main/java/caosdb/server/entity/Role.java +++ b/src/main/java/caosdb/server/entity/Role.java @@ -22,7 +22,6 @@ */ package caosdb.server.entity; -import caosdb.server.database.Database; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.GetIDByName; import caosdb.server.entity.xml.EntityToElementStrategy; @@ -44,10 +43,16 @@ public enum Role { ids = new HashMap<Role, Integer>(); for (final Role r : Role.values()) { - ids.put(r, Database.execute(new GetIDByName(r.name(), "ROLE"), access).getId()); + ids.put(r, execute(new GetIDByName(r.name(), "ROLE"), access).getId()); } } + private static GetIDByName execute(GetIDByName getIDByName, Access access) { + getIDByName.setAccess(access); + getIDByName.executeTransaction(); + return getIDByName; + } + public static Role parse(final String str) { for (final Role r : Role.values()) { if (r.toString().equalsIgnoreCase(str)) { diff --git a/src/main/java/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/caosdb/server/entity/container/TransactionContainer.java index ff799a4df5eb74a0d15e48a990e735af609925ec..ea4cc02e7d16bda586ff3c700e3f2fb237b15426 100644 --- a/src/main/java/caosdb/server/entity/container/TransactionContainer.java +++ b/src/main/java/caosdb/server/entity/container/TransactionContainer.java @@ -103,15 +103,15 @@ public class TransactionContainer extends Container<Entity> implements ToElement @Override public void addToElement(final Element element) { element.setAttribute("count", Integer.toString(size())); + if (this.benchmark != null && CaosDBServer.isDebugMode()) { + element.addContent(this.benchmark.toElememt()); + } for (final ToElementable m : this.messages) { m.addToElement(element); } for (final EntityInterface entity : this) { entity.addToElement(element); } - if (this.benchmark != null && CaosDBServer.isDebugMode()) { - element.addContent(this.benchmark.toElememt()); - } } public void print() { @@ -180,7 +180,7 @@ public class TransactionContainer extends Container<Entity> implements ToElement public TransactionBenchmark getTransactionBenchmark() { if (this.benchmark == null) { - this.benchmark = TransactionBenchmark.getSubBenchmark(); + this.benchmark = TransactionBenchmark.getRootInstance().createBenchmark(getClass()); } return this.benchmark; } diff --git a/src/main/java/caosdb/server/jobs/Job.java b/src/main/java/caosdb/server/jobs/Job.java index 681098b76a9deb90bc05dbea6f13ad2acd937ea6..b3551b4dd92084e6296a57be4166b341efa68262 100644 --- a/src/main/java/caosdb/server/jobs/Job.java +++ b/src/main/java/caosdb/server/jobs/Job.java @@ -23,7 +23,7 @@ package caosdb.server.jobs; import caosdb.server.CaosDBException; -import caosdb.server.database.Database; +import caosdb.server.database.BackendTransaction; import caosdb.server.database.backend.transaction.GetIDByName; import caosdb.server.database.backend.transaction.IsSubType; import caosdb.server.database.backend.transaction.RetrieveFullEntity; @@ -78,6 +78,10 @@ public abstract class Job extends AbstractObservable implements Observer { return getTransaction().getTransactor(); } + public <K extends BackendTransaction> K execute(final K t) { + return getTransaction().execute(t, getTransaction().getAccess()); + } + protected ScheduledJob appendJob(final EntityInterface entity, final Class<? extends Job> clazz) { try { final Job job = clazz.newInstance(); @@ -156,8 +160,7 @@ public abstract class Job extends AbstractObservable implements Observer { } protected final boolean isValidSubTypeNoCache(final int child, final int parent) { - return child == parent - || Database.execute(new IsSubType(child, parent), getTransaction().getAccess()).isSubType(); + return child == parent || execute(new IsSubType(child, parent)).isSubType(); } protected final EntityInterface retrieveValidSparseEntityByName(final String name) @@ -166,8 +169,7 @@ public abstract class Job extends AbstractObservable implements Observer { } protected final EntityInterface retrieveValidSparseEntityById(final Integer id) throws Message { - final EntityInterface ret = - Database.execute(new RetrieveSparseEntity(id), getTransaction().getAccess()).getEntity(); + final EntityInterface ret = execute(new RetrieveSparseEntity(id)).getEntity(); if (ret.getEntityStatus() == EntityStatus.NONEXISTENT) { throw ServerMessages.ENTITY_DOES_NOT_EXIST; } @@ -175,17 +177,15 @@ public abstract class Job extends AbstractObservable implements Observer { } protected final EntityInterface retrieveValidEntity(Integer id) { - return Database.execute(new RetrieveFullEntity(id), getTransaction().getAccess()) - .getContainer() - .get(0); + return execute(new RetrieveFullEntity(id)).getContainer().get(0); } protected final Integer retrieveValidIDByName(final String name) { - return Database.execute(new GetIDByName(name), getTransaction().getAccess()).getId(); + return execute(new GetIDByName(name)).getId(); } protected EntityInterface retrieveParentsOfValidEntity(final EntityInterface entity) { - Database.execute(new RetrieveParents(entity), getTransaction().getAccess()); + execute(new RetrieveParents(entity)); return entity; } @@ -257,16 +257,16 @@ public abstract class Job extends AbstractObservable implements Observer { } protected List<Job> loadDataTypeSpecificJobs() { - return Job.loadDataTypeSpecificJobs(getEntity(), getTransaction()); + return loadDataTypeSpecificJobs(getEntity(), getTransaction()); } - public static List<Job> loadDataTypeSpecificJobs( + public List<Job> loadDataTypeSpecificJobs( final EntityInterface entity, final Transaction<? extends TransactionContainer> transaction) { return loadDataTypeSpecificJobs(entity.getDatatype(), entity, transaction); } - private static List<Job> loadDataTypeSpecificJobs( + private List<Job> loadDataTypeSpecificJobs( final AbstractDatatype dt, final EntityInterface entity, final Transaction<? extends TransactionContainer> transaction) { @@ -275,19 +275,19 @@ public abstract class Job extends AbstractObservable implements Observer { } if (dt instanceof ReferenceDatatype2) { final RuleLoader t = new RuleLoader(0, 17, entity, transaction); - return Database.execute(t, transaction.getAccess()).getJobs(); + return execute(t).getJobs(); } else if (dt instanceof AbstractCollectionDatatype) { final AbstractDatatype datatype = ((AbstractCollectionDatatype) dt).getDatatype(); return loadDataTypeSpecificJobs(datatype, entity, transaction); } else if (dt.getId() != null) { final RuleLoader t = new RuleLoader(0, dt.getId(), entity, transaction); - return Database.execute(t, transaction.getAccess()).getJobs(); + return execute(t).getJobs(); } else { return null; } } - public static List<Job> loadStandardJobs( + public List<Job> loadStandardJobs( final EntityInterface entity, final Transaction<? extends TransactionContainer> transaction) { final ArrayList<Job> jobs = new ArrayList<>(); @@ -302,13 +302,13 @@ public abstract class Job extends AbstractObservable implements Observer { // load general rules { final RuleLoader t = new RuleLoader(0, 0, entity, transaction); - jobs.addAll(Database.execute(t, transaction.getAccess()).getJobs()); + jobs.addAll(execute(t).getJobs()); } // load Role specific rules if (entity.hasRole()) { final RuleLoader t = new RuleLoader(0, entity.getRole().getId(), entity, transaction); - jobs.addAll(Database.execute(t, transaction.getAccess()).getJobs()); + jobs.addAll(execute(t).getJobs()); } // load data type specific rules @@ -336,7 +336,7 @@ public abstract class Job extends AbstractObservable implements Observer { } } - public static List<Job> loadJobs( + public List<Job> loadJobs( final EntityInterface entity, final Transaction<? extends TransactionContainer> transaction) { final LinkedList<Job> jobs = new LinkedList<>(); diff --git a/src/main/java/caosdb/server/jobs/Schedule.java b/src/main/java/caosdb/server/jobs/Schedule.java index 367fdcbd13c5830f46205ef05d386f98bb14492d..4e7f005f3d2f790008a991a0138d62013f6a545a 100644 --- a/src/main/java/caosdb/server/jobs/Schedule.java +++ b/src/main/java/caosdb/server/jobs/Schedule.java @@ -55,7 +55,7 @@ class ScheduledJob { this.job .getContainer() .getTransactionBenchmark() - .addBenchmark(this.job.getClass().getSimpleName(), this.runtime); + .addMeasurement(this.job.getClass().getSimpleName(), this.runtime); } void pause() { diff --git a/src/main/java/caosdb/server/jobs/core/AccessControl.java b/src/main/java/caosdb/server/jobs/core/AccessControl.java index 8b51cd582933d9c993c2427be7c399e7dc553df2..0dd2ef4740d1a17d6e6ed8b0cc04c8d66a56c918 100644 --- a/src/main/java/caosdb/server/jobs/core/AccessControl.java +++ b/src/main/java/caosdb/server/jobs/core/AccessControl.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveSparseEntity; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.wrapper.Parent; @@ -66,7 +65,7 @@ public class AccessControl extends ContainerJob { if (e.hasParents() && e.getParents().size() == 1) { final Parent par1 = e.getParents().get(0); if (par1.hasId() && par1.getId() > 0) { - Database.execute(new RetrieveSparseEntity(par1), getTransaction().getAccess()); + execute(new RetrieveSparseEntity(par1)); } if (par1.hasName() && par1.getName().equals("CommentAnnotation") diff --git a/src/main/java/caosdb/server/jobs/core/CheckChildDependencyExistent.java b/src/main/java/caosdb/server/jobs/core/CheckChildDependencyExistent.java index 407c6e549bdcb8968a7ca91093534574ec6e5e2e..a3d9f4e493b189e7fb49de69347c5b6149f9f885 100644 --- a/src/main/java/caosdb/server/jobs/core/CheckChildDependencyExistent.java +++ b/src/main/java/caosdb/server/jobs/core/CheckChildDependencyExistent.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.GetChildren; import caosdb.server.entity.EntityInterface; import caosdb.server.jobs.EntityJob; @@ -42,9 +41,7 @@ public class CheckChildDependencyExistent extends EntityJob { public final void run() { if (getEntity().getDomain() == null || getEntity().getDomain() == 0) { - final List<Integer> children = - Database.execute(new GetChildren(getEntity().getId()), getTransaction().getAccess()) - .getList(); + final List<Integer> children = execute(new GetChildren(getEntity().getId())).getList(); // loop: for (final Integer id : children) { diff --git a/src/main/java/caosdb/server/jobs/core/CheckFileStorageConsistency.java b/src/main/java/caosdb/server/jobs/core/CheckFileStorageConsistency.java index b74a0319c981753a52d5fb962f9bf3add3347ba1..5af12ad71b4b3c5b12ac8321131b4d9cb29013d5 100644 --- a/src/main/java/caosdb/server/jobs/core/CheckFileStorageConsistency.java +++ b/src/main/java/caosdb/server/jobs/core/CheckFileStorageConsistency.java @@ -28,9 +28,9 @@ import caosdb.server.database.exceptions.TransactionException; import caosdb.server.entity.Message; import caosdb.server.jobs.FlagJob; import caosdb.server.jobs.JobAnnotation; +import caosdb.server.transaction.FileStorageConsistencyCheck; import caosdb.server.transaction.Retrieve; import caosdb.server.transaction.Transaction; -import caosdb.server.utils.FileStorageConsistencyCheck; import caosdb.server.utils.FileUtils; import caosdb.server.utils.Observable; import caosdb.server.utils.Observer; diff --git a/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java b/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java index ead4248f63fe5af4bf6e35778ecc34c7e3459da4..bee056c5763593ce6ef6a71f713019fae30a8bb5 100644 --- a/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java +++ b/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveFullEntity; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.StatementStatus; @@ -49,8 +48,7 @@ public class CheckParOblPropPresent extends EntityJob { runJobFromSchedule(getEntity(), CheckParValid.class); if (getEntity().hasParents()) { - Database.execute( - new RetrieveFullEntity(getEntity().getParents()), getTransaction().getAccess()); + execute(new RetrieveFullEntity(getEntity().getParents())); } // inherit properties diff --git a/src/main/java/caosdb/server/jobs/core/CheckReferenceDependencyExistent.java b/src/main/java/caosdb/server/jobs/core/CheckReferenceDependencyExistent.java index eec99f5ed00384d4be447a7ef3cd51b19178dccf..fd5eaab0f0d302e9b5586693ef502c32d607d773 100644 --- a/src/main/java/caosdb/server/jobs/core/CheckReferenceDependencyExistent.java +++ b/src/main/java/caosdb/server/jobs/core/CheckReferenceDependencyExistent.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.GetDependentEntities; import caosdb.server.entity.EntityInterface; import caosdb.server.jobs.EntityJob; @@ -45,9 +44,7 @@ public class CheckReferenceDependencyExistent extends EntityJob { // retrieve dependent entities final List<Integer> depends = - Database.execute( - new GetDependentEntities(getEntity().getId()), getTransaction().getAccess()) - .getList(); + execute(new GetDependentEntities(getEntity().getId())).getList(); // loop: for (final Integer id : depends) { diff --git a/src/main/java/caosdb/server/jobs/core/CheckTargetPathValid.java b/src/main/java/caosdb/server/jobs/core/CheckTargetPathValid.java index 3dc0c4bba460dfa7f6eb2eec338e5dea738da9e2..404e6b3a0d82950061ba4168a7a6f32e5f847400 100644 --- a/src/main/java/caosdb/server/jobs/core/CheckTargetPathValid.java +++ b/src/main/java/caosdb/server/jobs/core/CheckTargetPathValid.java @@ -55,7 +55,8 @@ public class CheckTargetPathValid extends EntityJob { } try { - FileSystem.checkTarget(getEntity(), getTransaction().getAccess()); + FileSystem.checkTarget( + getEntity(), getTransaction().getAccess(), getTransaction().getTransactionBenchmark()); } catch (final Message m) { getEntity().setEntityStatus(EntityStatus.UNQUALIFIED); getEntity().addError(m); diff --git a/src/main/java/caosdb/server/jobs/core/History.java b/src/main/java/caosdb/server/jobs/core/History.java index 7e7643040196333b923536b13d8b84ae6b962311..ee72413a46e65f8b8a020315e3c2e93c7b8ccd97 100644 --- a/src/main/java/caosdb/server/jobs/core/History.java +++ b/src/main/java/caosdb/server/jobs/core/History.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveTransactionHistory; import caosdb.server.entity.EntityInterface; import caosdb.server.jobs.FlagJob; @@ -44,7 +43,7 @@ public class History extends FlagJob { try { entity.checkPermission(EntityPermission.RETRIEVE_HISTORY); final RetrieveTransactionHistory t = new RetrieveTransactionHistory(entity); - Database.execute(t, getTransaction().getAccess()); + execute(t); } catch (final AuthorizationException e) { entity.setEntityStatus(EntityStatus.UNQUALIFIED); entity.addError(ServerMessages.AUTHORIZATION_ERROR); diff --git a/src/main/java/caosdb/server/jobs/core/Inheritance.java b/src/main/java/caosdb/server/jobs/core/Inheritance.java index ed25c64cbf02d16566addc79961e36e0fdffad81..f7149eb3c74270012db011385e17bbf01fdd01a2 100644 --- a/src/main/java/caosdb/server/jobs/core/Inheritance.java +++ b/src/main/java/caosdb/server/jobs/core/Inheritance.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveFullEntity; import caosdb.server.entity.Entity; import caosdb.server.entity.EntityInterface; @@ -74,7 +73,7 @@ public class Inheritance extends EntityJob { runJobFromSchedule(getEntity(), CheckParValid.class); - Database.execute(new RetrieveFullEntity(parent), getTransaction().getAccess()); + execute(new RetrieveFullEntity(parent)); if (parent.hasProperties()) { // loop over all properties of the parent and @@ -163,7 +162,7 @@ public class Inheritance extends EntityJob { } } } else { - Database.execute(new RetrieveFullEntity(validProperty), getTransaction().getAccess()); + execute(new RetrieveFullEntity(validProperty)); } if (validProperty.getEntityStatus() == EntityStatus.VALID diff --git a/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java b/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java index 9dbc2a68b684b7a5757a00c816f81f3716e55dc9..7db04f124aa45b81d3484db3a9d0ea33ca74a5ba 100644 --- a/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java +++ b/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java @@ -224,7 +224,10 @@ public class InsertFilesInDir extends FlagJob { // add create symlink and file record to this // container if the target // path is allowed - if (FileSystem.checkTarget(newFileEntity, getTransaction().getAccess()) + if (FileSystem.checkTarget( + newFileEntity, + getTransaction().getAccess(), + getTransaction().getTransactionBenchmark()) && newFileEntity.getEntityStatus() != EntityStatus.UNQUALIFIED) { final File link = @@ -301,7 +304,7 @@ public class InsertFilesInDir extends FlagJob { } private void loadJobs(final Entity e) { - final List<Job> loadJobs = Job.loadJobs(e, getTransaction()); + final List<Job> loadJobs = loadJobs(e, getTransaction()); getTransaction().getSchedule().addAll(loadJobs); } diff --git a/src/main/java/caosdb/server/jobs/core/ResolveNames.java b/src/main/java/caosdb/server/jobs/core/ResolveNames.java index fd5498f468e44801279655ba21a1702da12c168e..f5e1695f34c30a78f136950f7aae3ae00be170e4 100644 --- a/src/main/java/caosdb/server/jobs/core/ResolveNames.java +++ b/src/main/java/caosdb/server/jobs/core/ResolveNames.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.GetIDByName; import caosdb.server.database.exceptions.EntityDoesNotExistException; import caosdb.server.entity.Entity; @@ -45,9 +44,7 @@ public class ResolveNames extends ContainerJob { for (final Entity e : container) { if (e.hasName() && !e.hasId()) { try { - final List<Integer> c = - Database.execute(new GetIDByName(e.getName(), false), getTransaction().getAccess()) - .getList(); + final List<Integer> c = execute(new GetIDByName(e.getName(), false)).getList(); e.setId(c.get(0)); e.setEntityStatus(EntityStatus.QUALIFIED); diff --git a/src/main/java/caosdb/server/jobs/core/RetrieveAllJob.java b/src/main/java/caosdb/server/jobs/core/RetrieveAllJob.java index f522986c6b40ed73fdbb752226a7dd66de4d040e..0fba1223a3bd0e984c5c2b6ff43dd58070b5bbc5 100644 --- a/src/main/java/caosdb/server/jobs/core/RetrieveAllJob.java +++ b/src/main/java/caosdb/server/jobs/core/RetrieveAllJob.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveAll; import caosdb.server.jobs.FlagJob; import caosdb.server.jobs.JobAnnotation; @@ -37,7 +36,7 @@ public class RetrieveAllJob extends FlagJob { if (value == null) { value = "ENTITY"; } - Database.execute(new RetrieveAll(getContainer(), value), getTransaction().getAccess()); + execute(new RetrieveAll(getContainer(), value)); } } } diff --git a/src/main/java/caosdb/server/jobs/core/UpdateUnitConverters.java b/src/main/java/caosdb/server/jobs/core/UpdateUnitConverters.java index 86f5b2d23721e97cef6e1b9ebd356cbf140b0cc6..8d0118b80582e3a65b613caae2200719af428819 100644 --- a/src/main/java/caosdb/server/jobs/core/UpdateUnitConverters.java +++ b/src/main/java/caosdb/server/jobs/core/UpdateUnitConverters.java @@ -22,7 +22,6 @@ */ package caosdb.server.jobs.core; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.InsertLinCon; import caosdb.server.jobs.EntityJob; import caosdb.server.jobs.JobAnnotation; @@ -66,7 +65,7 @@ public class UpdateUnitConverters extends EntityJob { if (signature_from != signature_to) { final InsertLinCon t = new InsertLinCon(signature_from, signature_to, a, b_dividend, b_divisor, c); - Database.execute(t, getTransaction().getAccess()); + execute(t); } } } diff --git a/src/main/java/caosdb/server/query/Backreference.java b/src/main/java/caosdb/server/query/Backreference.java index f8d4f86f5d04d6b724a3fdec66c1a24d739726af..c39ce43923372811caf8607550a9852d1a518c63 100644 --- a/src/main/java/caosdb/server/query/Backreference.java +++ b/src/main/java/caosdb/server/query/Backreference.java @@ -192,7 +192,7 @@ public class Backreference implements EntityFilterInterface, QueryInterface { addBenchmark("initBackreference()", t2 - t1); if (this.entitiesTable != null) { - Query.applyQueryTemplates(query, this.entitiesTable); + getQuery().applyQueryTemplates(query, this.entitiesTable); addBenchmark("applyQueryTemplates()", System.currentTimeMillis() - t2); } } diff --git a/src/main/java/caosdb/server/query/POV.java b/src/main/java/caosdb/server/query/POV.java index 01d2cb1b9bb2bd51e18ccacc438ff8ac75788762..6a57caa780d76c5279a37eaba09d44c021215d7c 100644 --- a/src/main/java/caosdb/server/query/POV.java +++ b/src/main/java/caosdb/server/query/POV.java @@ -412,7 +412,7 @@ public class POV implements EntityFilterInterface { query.addBenchmark(getClass().getSimpleName() + ".initPOVPropertiesTable()", t3 - t2); if (this.refIdsTable != null) { - Query.applyQueryTemplates(query, this.refIdsTable); + query.getQuery().applyQueryTemplates(query, this.refIdsTable); query.addBenchmark( getClass().getSimpleName() + ".applyQueryTemplates()", System.currentTimeMillis() - t3); } diff --git a/src/main/java/caosdb/server/query/Query.java b/src/main/java/caosdb/server/query/Query.java index d3e0e927d14d0b2021f056ad52f10df548c5734c..a62a6acae9bcc413e7ab06c812312f8e8b8fe323 100644 --- a/src/main/java/caosdb/server/query/Query.java +++ b/src/main/java/caosdb/server/query/Query.java @@ -26,7 +26,6 @@ import static caosdb.server.database.DatabaseUtils.bytes2UTF8; import caosdb.server.CaosDBServer; import caosdb.server.ServerProperties; -import caosdb.server.database.Database; import caosdb.server.database.access.Access; import caosdb.server.database.backend.implementation.MySQL.ConnectionException; import caosdb.server.database.backend.implementation.MySQL.MySQLHelper; @@ -284,7 +283,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac * @throws SQLException * @throws QueryException */ - public static void applyQueryTemplates(final QueryInterface query, final String resultSet) + public void applyQueryTemplates(final QueryInterface query, final String resultSet) throws QueryException { try { final Map<Integer, String> queryTemplates = getQueryTemplates(query, resultSet); @@ -300,7 +299,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac // ... check for RETRIEVE:ENTITY permission... final EntityInterface e = - Database.execute(new RetrieveSparseEntity(q.getKey()), query.getAccess()).getEntity(); + execute(new RetrieveSparseEntity(q.getKey()), query.getAccess()).getEntity(); final EntityACL entityACL = e.getEntityACL(); if (!entityACL.isPermitted(query.getUser(), EntityPermission.RETRIEVE_ENTITY)) { // ... and ignore if not. @@ -436,7 +435,9 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac this.filter = cq.filter; this.selections = cq.s; final long t2 = System.currentTimeMillis(); - addBenchmark("parse (" + this.query + ")", t2 - t1); + if (t2 - t1 > 1000) { + addBenchmark("LONG_PARSING: " + this.query, t2 - t1); + } } private String executeStrategy() throws QueryException { @@ -531,8 +532,6 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac this.access = access; } - private final TransactionBenchmark benchmark = TransactionBenchmark.getSubBenchmark(); - /** * Filter out all entities which may not be retrieved by this user due to a missing RETRIEVE * permission. This one is also designed for filtering of intermediate results. @@ -542,7 +541,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac * @throws SQLException * @throws TransactionException */ - public static void filterEntitiesWithoutRetrievePermission( + public void filterEntitiesWithoutRetrievePermission( final QueryInterface query, final String resultSet) throws SQLException, TransactionException { if (!filterEntitiesWithoutRetrievePermisions) { @@ -554,7 +553,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac while (rs.next()) { final long t1 = System.currentTimeMillis(); final Integer id = rs.getInt("id"); - if (!Database.execute(new RetrieveSparseEntity(id), query.getAccess()) + if (!execute(new RetrieveSparseEntity(id), query.getAccess()) .getEntity() .getEntityACL() .isPermitted(query.getUser(), EntityPermission.RETRIEVE_ENTITY)) { @@ -587,7 +586,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac while (iterator.hasNext()) { final long t1 = System.currentTimeMillis(); final Integer id = iterator.next(); - if (!Database.execute(new RetrieveSparseEntity(id), getAccess()) + if (!execute(new RetrieveSparseEntity(id), getAccess()) .getEntity() .getEntityACL() .isPermitted(getUser(), EntityPermission.RETRIEVE_ENTITY)) { @@ -641,6 +640,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac private int targetSetCount = -1; + private TransactionBenchmark benchmark; + @Override public void addToElement(final Element parent) { final Element ret = new Element("Query"); @@ -695,8 +696,6 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac ret.addContent(selection); } - ret.addContent(this.benchmark.toElememt()); - parent.addContent(ret); } @@ -726,6 +725,19 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac @Override public void addBenchmark(final String str, final long time) { - this.benchmark.addBenchmark(this.getClass().getSimpleName().toString() + "." + str, time); + getTransactionBenchmark() + .addMeasurement(this.getClass().getSimpleName().toString() + "." + str, time); + } + + @Override + public TransactionBenchmark getTransactionBenchmark() { + if (benchmark == null) { + if (container != null) { + benchmark = container.getTransactionBenchmark().getBenchmark(getClass()); + } else { + benchmark = TransactionBenchmark.getRootInstance().getBenchmark(getClass()); + } + } + return benchmark; } } diff --git a/src/main/java/caosdb/server/query/SubProperty.java b/src/main/java/caosdb/server/query/SubProperty.java index a5abe0b7b6cd3940f16cfe29461c13a019416d41..12629640ec4e7780c1b1d5933e7d6e1711f635f7 100644 --- a/src/main/java/caosdb/server/query/SubProperty.java +++ b/src/main/java/caosdb/server/query/SubProperty.java @@ -87,7 +87,7 @@ public class SubProperty implements QueryInterface, EntityFilterInterface { this.filter.apply(this); - Query.filterEntitiesWithoutRetrievePermission(this, this.sourceSet); + getQuery().filterEntitiesWithoutRetrievePermission(this, this.sourceSet); final CallableStatement callFinishSubProperty = getConnection().prepareCall("call finishSubProperty(?,?,?)"); diff --git a/src/main/java/caosdb/server/resource/FileSystemResource.java b/src/main/java/caosdb/server/resource/FileSystemResource.java index 0e8d59a107d3f8dbb83d966a9e251641ac9bdd8a..290a88801b4f14401981f9d91a6ba00cf27c12a4 100644 --- a/src/main/java/caosdb/server/resource/FileSystemResource.java +++ b/src/main/java/caosdb/server/resource/FileSystemResource.java @@ -117,7 +117,7 @@ public class FileSystemResource extends AbstractCaosDBServerResource { rootElem.addContent(folder); final long t2 = System.currentTimeMillis(); - getBenchmark().addBenchmark(this.getClass().getSimpleName(), t2 - t1); + getBenchmark().addMeasurement(this.getClass().getSimpleName(), t2 - t1); rootElem.addContent(getBenchmark().toElememt()); final Document doc = new Document(rootElem); return ok(doc); @@ -132,6 +132,10 @@ public class FileSystemResource extends AbstractCaosDBServerResource { } } + TransactionBenchmark getBenchmark() { + return TransactionBenchmark.getRootInstance().getBenchmark(getClass()); + } + protected Attribute getThumbnailAttribute( final File file, final File child, final String referenceString) { final String thpath = @@ -145,15 +149,6 @@ public class FileSystemResource extends AbstractCaosDBServerResource { return null; } - private TransactionBenchmark benchmark; - - private TransactionBenchmark getBenchmark() { - if (this.benchmark == null) { - this.benchmark = TransactionBenchmark.getSubBenchmark(); - } - return this.benchmark; - } - Element getFileElement(final String directory, final File file) throws Exception { final Element celem = new Element("file"); celem.setAttribute( @@ -177,7 +172,7 @@ public class FileSystemResource extends AbstractCaosDBServerResource { final Transaction<?> t = new RetrieveSparseEntityByPath(c); t.execute(); final long t2 = System.currentTimeMillis(); - getBenchmark().addBenchmark(this.getClass().getSimpleName() + ".getEntity", t2 - t1); + getBenchmark().addMeasurement(this.getClass().getSimpleName() + ".getEntity", t2 - t1); return e; } @@ -193,7 +188,7 @@ public class FileSystemResource extends AbstractCaosDBServerResource { final long t1 = System.currentTimeMillis(); getEntity(path).checkPermission(EntityPermission.RETRIEVE_FILE); final long t2 = System.currentTimeMillis(); - getBenchmark().addBenchmark(this.getClass().getSimpleName() + ".checkPermissions", t2 - t1); + getBenchmark().addMeasurement(this.getClass().getSimpleName() + ".checkPermissions", t2 - t1); } @Override diff --git a/src/main/java/caosdb/server/resource/InfoResource.java b/src/main/java/caosdb/server/resource/InfoResource.java index c2342cc46f7e62fd6a398218b39e804ab9f1767d..924d66980e5da27ec998fd361b95a8f0769e4229 100644 --- a/src/main/java/caosdb/server/resource/InfoResource.java +++ b/src/main/java/caosdb/server/resource/InfoResource.java @@ -45,7 +45,7 @@ public class InfoResource extends AbstractCaosDBServerResource { final Element root = generateRootElement(); root.addContent(Info.toElement()); root.addContent(FlagInfo.toElement()); - root.addContent(TransactionBenchmark.getInstance().toElememt()); + root.addContent(TransactionBenchmark.getRootInstance().toElememt()); doc.setRootElement(root); return ok(doc); } diff --git a/src/main/java/caosdb/server/resource/transaction/EntityResource.java b/src/main/java/caosdb/server/resource/transaction/EntityResource.java index 54882bcab6211bdbbd6921871ef4709413738543..0c853096c1af71dcacf2ef775c46f4dceecb1673 100644 --- a/src/main/java/caosdb/server/resource/transaction/EntityResource.java +++ b/src/main/java/caosdb/server/resource/transaction/EntityResource.java @@ -115,7 +115,7 @@ public class EntityResource extends AbstractCaosDBServerResource { final long t2 = System.currentTimeMillis(); entityContainer .getTransactionBenchmark() - .addBenchmark(getClass().getSimpleName() + ".httpGetInChildClass", t2 - t1); + .addMeasurement(getClass().getSimpleName() + ".httpGetInChildClass", t2 - t1); final Element rootElem = generateRootElement(); entityContainer.addToElement(rootElem); doc.setRootElement(rootElem); diff --git a/src/main/java/caosdb/server/utils/ChecksumUpdater.java b/src/main/java/caosdb/server/transaction/ChecksumUpdater.java similarity index 92% rename from src/main/java/caosdb/server/utils/ChecksumUpdater.java rename to src/main/java/caosdb/server/transaction/ChecksumUpdater.java index 6a1e0e927002eff7669d3a6dc7bcae39e761d859..30313478c263a131658005daa39da3b495c85eb2 100644 --- a/src/main/java/caosdb/server/utils/ChecksumUpdater.java +++ b/src/main/java/caosdb/server/transaction/ChecksumUpdater.java @@ -20,10 +20,9 @@ * * ** end header */ -package caosdb.server.utils; +package caosdb.server.transaction; import caosdb.server.CaosDBException; -import caosdb.server.database.Database; import caosdb.server.database.DatabaseMonitor; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.GetUpdateableChecksums; @@ -34,7 +33,7 @@ import caosdb.server.entity.EntityInterface; import caosdb.server.entity.FileProperties; import caosdb.server.entity.Message; import caosdb.server.entity.container.TransactionContainer; -import caosdb.server.transaction.WriteTransaction; +import caosdb.server.utils.FileUtils; import java.io.IOException; import java.security.NoSuchAlgorithmException; @@ -86,7 +85,7 @@ public class ChecksumUpdater extends WriteTransaction<TransactionContainer> impl DatabaseMonitor.getInstance().acquireStrongAccess(this); // update - Database.execute(new UpdateSparseEntity(fileEntity), strongAccess); + execute(new UpdateSparseEntity(fileEntity), strongAccess); strongAccess.commit(); } catch (final InterruptedException e) { @@ -108,7 +107,7 @@ public class ChecksumUpdater extends WriteTransaction<TransactionContainer> impl final EntityInterface fileEntity, final Access access, final long lastModified) throws NoSuchAlgorithmException, IOException, CaosDBException, Message { final EntityInterface checkEntity = - Database.execute(new RetrieveSparseEntity(fileEntity), access).getEntity(); + execute(new RetrieveSparseEntity(fileEntity), access).getEntity(); final FileProperties thatFP = checkEntity.getFileProperties(); final FileProperties thisFP = fileEntity.getFileProperties(); @@ -136,13 +135,13 @@ public class ChecksumUpdater extends WriteTransaction<TransactionContainer> impl synchronized (instance.running) { // test for updatable checksums - final Integer id = Database.execute(new GetUpdateableChecksums(), weakAccess).getID(); + final Integer id = execute(new GetUpdateableChecksums(), weakAccess).getID(); if (id == null) { // nothing to be updated... instance.running = false; return null; } - return Database.execute(new RetrieveSparseEntity(id), weakAccess).getEntity(); + return execute(new RetrieveSparseEntity(id), weakAccess).getEntity(); } } catch (final Exception e) { e.printStackTrace(); diff --git a/src/main/java/caosdb/server/transaction/Delete.java b/src/main/java/caosdb/server/transaction/Delete.java index f371f0d64e32ddc5a6f4812943b2c9be08b5bcbc..1d3aacbc78043fef6982b2b7663dc5d033e50e50 100644 --- a/src/main/java/caosdb/server/transaction/Delete.java +++ b/src/main/java/caosdb/server/transaction/Delete.java @@ -22,7 +22,6 @@ */ package caosdb.server.transaction; -import caosdb.server.database.Database; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.DeleteEntity; import caosdb.server.database.backend.transaction.RetrieveFullEntity; @@ -53,7 +52,7 @@ public class Delete extends WriteTransaction<DeleteContainer> { setAccess(getMonitor().allocateStrongAccess(this)); // retrieve all entities which are to be deleted. - Database.execute(new RetrieveFullEntity(getContainer()), getAccess()); + execute(new RetrieveFullEntity(getContainer()), getAccess()); for (final EntityInterface e : getContainer()) { if (e.getEntityStatus() == EntityStatus.NONEXISTENT) { @@ -104,10 +103,9 @@ public class Delete extends WriteTransaction<DeleteContainer> { delete(getContainer(), getAccess()); } - private static void delete(final TransactionContainer container, final Access access) - throws Exception { + private void delete(final TransactionContainer container, final Access access) throws Exception { if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) { - Database.execute(new DeleteEntity(container), access); + execute(new DeleteEntity(container), access); } } diff --git a/src/main/java/caosdb/server/transaction/DeleteRoleTransaction.java b/src/main/java/caosdb/server/transaction/DeleteRoleTransaction.java index 3f3758823a2b554edbfb1e400c2a8f2f14916ba1..e1ba3bec80663cb3b30d2dbdc48d9f9024c8f2d7 100644 --- a/src/main/java/caosdb/server/transaction/DeleteRoleTransaction.java +++ b/src/main/java/caosdb/server/transaction/DeleteRoleTransaction.java @@ -23,7 +23,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.ACMPermissions; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.DeleteRole; import caosdb.server.database.backend.transaction.RetrieveRole; import caosdb.server.database.backend.transaction.SetPermissionRules; @@ -42,10 +41,10 @@ public class DeleteRoleTransaction extends AccessControlTransaction { protected void transaction() throws Exception { SecurityUtils.getSubject().checkPermission(ACMPermissions.PERMISSION_DELETE_ROLE(this.name)); - if (Database.execute(new RetrieveRole(this.name), getAccess()).getRole() == null) { + if (execute(new RetrieveRole(this.name), getAccess()).getRole() == null) { throw ServerMessages.ROLE_DOES_NOT_EXIST; } - Database.execute(new SetPermissionRules(this.name, null), getAccess()); - Database.execute(new DeleteRole(this.name), getAccess()); + execute(new SetPermissionRules(this.name, null), getAccess()); + execute(new DeleteRole(this.name), getAccess()); } } diff --git a/src/main/java/caosdb/server/transaction/DeleteUserTransaction.java b/src/main/java/caosdb/server/transaction/DeleteUserTransaction.java index 729512a2a6dfae734b152e2ddd4c1e71362681d5..cdedce31b34153494ceb0be28e4c3a9da360bb6e 100644 --- a/src/main/java/caosdb/server/transaction/DeleteUserTransaction.java +++ b/src/main/java/caosdb/server/transaction/DeleteUserTransaction.java @@ -25,7 +25,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.ACMPermissions; import caosdb.server.accessControl.CredentialsValidator; import caosdb.server.accessControl.UserSources; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.DeletePassword; import caosdb.server.database.backend.transaction.DeleteUser; import caosdb.server.database.backend.transaction.RetrievePasswordValidator; @@ -51,14 +50,14 @@ public class DeleteUserTransaction extends AccessControlTransaction { .checkPermission(ACMPermissions.PERMISSION_DELETE_USER(this.realm, this.user)); final CredentialsValidator<String> validator = - Database.execute(new RetrievePasswordValidator(this.user), getAccess()).getValidator(); + execute(new RetrievePasswordValidator(this.user), getAccess()).getValidator(); if (validator == null) { throw ServerMessages.ACCOUNT_DOES_NOT_EXIST; } - Database.execute(new DeletePassword(this.user), getAccess()); - Database.execute(new DeleteUser(this.realm, this.user), getAccess()); + execute(new DeletePassword(this.user), getAccess()); + execute(new DeleteUser(this.realm, this.user), getAccess()); } public Element getUserElement() { diff --git a/src/main/java/caosdb/server/utils/FileStorageConsistencyCheck.java b/src/main/java/caosdb/server/transaction/FileStorageConsistencyCheck.java similarity index 91% rename from src/main/java/caosdb/server/utils/FileStorageConsistencyCheck.java rename to src/main/java/caosdb/server/transaction/FileStorageConsistencyCheck.java index c750bb4e6f4de884cf39289d82df79138206f057..d1055b5e4c4a3bf0676883cc221e60d47442f304 100644 --- a/src/main/java/caosdb/server/utils/FileStorageConsistencyCheck.java +++ b/src/main/java/caosdb/server/transaction/FileStorageConsistencyCheck.java @@ -20,10 +20,9 @@ * * ** end header */ -package caosdb.server.utils; +package caosdb.server.transaction; import caosdb.datetime.UTCDateTime; -import caosdb.server.database.Database; import caosdb.server.database.DatabaseMonitor; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.FileConsistencyCheck; @@ -34,7 +33,7 @@ import caosdb.server.database.backend.transaction.SetFileCheckedTimestamp; import caosdb.server.database.proto.SparseEntity; import caosdb.server.entity.Message; import caosdb.server.entity.xml.ToElementable; -import caosdb.server.transaction.TransactionInterface; +import caosdb.server.utils.SHA512; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -69,7 +68,7 @@ public class FileStorageConsistencyCheck extends Thread // test all files in file system. final Iterator<String> iterator = - Database.execute(new GetFileIterator(this.location), this.access).getIterator(); + execute(new GetFileIterator(this.location), this.access).getIterator(); this.ts = System.currentTimeMillis(); while (iterator != null && iterator.hasNext()) { @@ -87,14 +86,14 @@ public class FileStorageConsistencyCheck extends Thread continue; } - final GetFileRecordByPath t = Database.execute(new GetFileRecordByPath(path), this.access); + final GetFileRecordByPath t = execute(new GetFileRecordByPath(path), this.access); if (t.getEntity() == null) { this.results.put(path, FileConsistencyCheck.UNKNOWN_FILE); continue; } final int result = - Database.execute( + execute( new FileConsistencyCheck( path, t.getSize(), t.getHash(), t.getLastConsistencyCheck(), new SHA512()), this.access) @@ -104,18 +103,17 @@ public class FileStorageConsistencyCheck extends Thread this.results.put(path, result); } - Database.execute(new SetFileCheckedTimestamp(t.getId(), this.ts), this.access); + execute(new SetFileCheckedTimestamp(t.getId(), this.ts), this.access); } // test all remaining file records final Iterator<SparseEntity> iterator2 = - Database.execute(new RetrieveAllUncheckedFiles(this.ts, this.location), this.access) - .getIterator(); + execute(new RetrieveAllUncheckedFiles(this.ts, this.location), this.access).getIterator(); while (iterator2 != null && iterator2.hasNext()) { final SparseEntity entity = iterator2.next(); final int result = - Database.execute( + execute( new FileConsistencyCheck( entity.filePath, entity.fileSize, @@ -129,7 +127,7 @@ public class FileStorageConsistencyCheck extends Thread this.results.put(entity.filePath, result); } - Database.execute(new SetFileCheckedTimestamp(entity.id, this.ts), this.access); + execute(new SetFileCheckedTimestamp(entity.id, this.ts), this.access); } } catch (final Exception e) { diff --git a/src/main/java/caosdb/server/transaction/Insert.java b/src/main/java/caosdb/server/transaction/Insert.java index 0dbda080ce33ea1fbcfdd4f43f36860f44e55db1..627ada52655c5e7802e98172d1c32f8280a95fb4 100644 --- a/src/main/java/caosdb/server/transaction/Insert.java +++ b/src/main/java/caosdb/server/transaction/Insert.java @@ -22,7 +22,6 @@ */ package caosdb.server.transaction; -import caosdb.server.database.Database; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.InsertEntity; import caosdb.server.entity.EntityInterface; @@ -101,10 +100,9 @@ public class Insert extends WriteTransaction<InsertContainer> { insert(getContainer(), getAccess()); } - public static void insert(final TransactionContainer container, final Access access) - throws Exception { + public void insert(final TransactionContainer container, final Access access) throws Exception { if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) { - Database.execute(new InsertEntity(container), access); + execute(new InsertEntity(container), access); } } diff --git a/src/main/java/caosdb/server/transaction/InsertLogRecordTransaction.java b/src/main/java/caosdb/server/transaction/InsertLogRecordTransaction.java index 89b48418843f326ac42bf49f96b0e6dfa8d0f17a..3762b0bed3f726dd521f754043d0e99a5d2a3913 100644 --- a/src/main/java/caosdb/server/transaction/InsertLogRecordTransaction.java +++ b/src/main/java/caosdb/server/transaction/InsertLogRecordTransaction.java @@ -22,7 +22,6 @@ */ package caosdb.server.transaction; -import caosdb.server.database.Database; import caosdb.server.database.DatabaseMonitor; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.InsertLogRecord; @@ -41,7 +40,7 @@ public class InsertLogRecordTransaction implements TransactionInterface { public void execute() throws Exception { final Access access = DatabaseMonitor.getInstance().acquiredWeakAccess(this); try { - Database.execute(new InsertLogRecord(this.toBeFlushed), access); + execute(new InsertLogRecord(this.toBeFlushed), access); } finally { access.release(); } diff --git a/src/main/java/caosdb/server/transaction/InsertRoleTransaction.java b/src/main/java/caosdb/server/transaction/InsertRoleTransaction.java index 250ca37bba0eedaba25d105072617b20fbf94cd5..8377210690692c8819e5197e35a8e549d27f2a30 100644 --- a/src/main/java/caosdb/server/transaction/InsertRoleTransaction.java +++ b/src/main/java/caosdb/server/transaction/InsertRoleTransaction.java @@ -24,7 +24,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.ACMPermissions; import caosdb.server.accessControl.Role; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.InsertRole; import caosdb.server.database.backend.transaction.RetrieveRole; import caosdb.server.utils.ServerMessages; @@ -42,10 +41,10 @@ public class InsertRoleTransaction extends AccessControlTransaction { protected void transaction() throws Exception { SecurityUtils.getSubject().checkPermission(ACMPermissions.PERMISSION_INSERT_ROLE()); - if (Database.execute(new RetrieveRole(this.role.name), getAccess()).getRole() != null) { + if (execute(new RetrieveRole(this.role.name), getAccess()).getRole() != null) { throw ServerMessages.ROLE_NAME_IS_NOT_UNIQUE; } - Database.execute(new InsertRole(this.role), getAccess()); + execute(new InsertRole(this.role), getAccess()); } } diff --git a/src/main/java/caosdb/server/transaction/InsertUserTransaction.java b/src/main/java/caosdb/server/transaction/InsertUserTransaction.java index d6cc2f46b397cf194a32f6ab5d7ec7e7fdc7407c..75b876b8bc291ea246746b4a8e85ccd26055c173 100644 --- a/src/main/java/caosdb/server/transaction/InsertUserTransaction.java +++ b/src/main/java/caosdb/server/transaction/InsertUserTransaction.java @@ -25,7 +25,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.ACMPermissions; import caosdb.server.accessControl.UserSources; import caosdb.server.accessControl.UserStatus; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrievePasswordValidator; import caosdb.server.database.backend.transaction.SetPassword; import caosdb.server.database.backend.transaction.UpdateUser; @@ -67,14 +66,14 @@ public class InsertUserTransaction extends AccessControlTransaction { UpdateUserTransaction.checkEntityExists(this.user.entity); } - if (Database.execute(new RetrievePasswordValidator(this.user.name), getAccess()).getValidator() + if (execute(new RetrievePasswordValidator(this.user.name), getAccess()).getValidator() == null) { if (this.password != null) { Utils.checkPasswordStrength(this.password); } - Database.execute(new SetPassword(this.user.name, this.password), getAccess()); - Database.execute(new UpdateUser(this.user), getAccess()); + execute(new SetPassword(this.user.name, this.password), getAccess()); + execute(new UpdateUser(this.user), getAccess()); } else { throw ServerMessages.ACCOUNT_NAME_NOT_UNIQUE; } diff --git a/src/main/java/caosdb/server/transaction/Retrieve.java b/src/main/java/caosdb/server/transaction/Retrieve.java index 3110ee97e68e38a955ad0ae146228a27eb7677d6..0de1b8e06b66a4293668fb499fb28f33fa398187 100644 --- a/src/main/java/caosdb/server/transaction/Retrieve.java +++ b/src/main/java/caosdb/server/transaction/Retrieve.java @@ -22,11 +22,9 @@ */ package caosdb.server.transaction; -import caosdb.server.database.Database; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.RetrieveFullEntity; import caosdb.server.entity.EntityInterface; -import caosdb.server.entity.container.Container; import caosdb.server.entity.container.RetrieveContainer; import caosdb.server.entity.xml.SetFieldStrategy; import caosdb.server.entity.xml.ToElementStrategy; @@ -137,9 +135,9 @@ public class Retrieve extends Transaction<RetrieveContainer> { retrieveFullEntities(getContainer(), getAccess()); } - private static void retrieveFullEntities( - final Container<? extends EntityInterface> container, final Access access) throws Exception { - Database.execute(new RetrieveFullEntity(container), access); + private void retrieveFullEntities(final RetrieveContainer container, final Access access) + throws Exception { + execute(new RetrieveFullEntity(container), access); } @Override diff --git a/src/main/java/caosdb/server/transaction/RetrieveLogRecordTransaction.java b/src/main/java/caosdb/server/transaction/RetrieveLogRecordTransaction.java index 14b5ea3140b685db77be79ff680180fea6e379b3..bbe2e1f11a7bd4c7705a790dec78903fb0e7c20a 100644 --- a/src/main/java/caosdb/server/transaction/RetrieveLogRecordTransaction.java +++ b/src/main/java/caosdb/server/transaction/RetrieveLogRecordTransaction.java @@ -23,7 +23,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.ACMPermissions; -import caosdb.server.database.Database; import caosdb.server.database.DatabaseMonitor; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.RetrieveLogRecord; @@ -64,7 +63,7 @@ public class RetrieveLogRecordTransaction implements TransactionInterface { final Access access = DatabaseMonitor.getInstance().acquiredWeakAccess(this); try { this.logRecords = - Database.execute(new RetrieveLogRecord(this.logger, this.level, this.message), access) + execute(new RetrieveLogRecord(this.logger, this.level, this.message), access) .getLogRecords(); } finally { access.release(); diff --git a/src/main/java/caosdb/server/transaction/RetrievePasswordValidatorTransaction.java b/src/main/java/caosdb/server/transaction/RetrievePasswordValidatorTransaction.java index 15817a5b405d18f80b23e26ac8b16d3a545483dd..d18b5c306373d6b89aa924bd154db444fbdb8f9a 100644 --- a/src/main/java/caosdb/server/transaction/RetrievePasswordValidatorTransaction.java +++ b/src/main/java/caosdb/server/transaction/RetrievePasswordValidatorTransaction.java @@ -23,7 +23,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.CredentialsValidator; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrievePasswordValidator; import caosdb.server.utils.ServerMessages; @@ -38,8 +37,7 @@ public class RetrievePasswordValidatorTransaction extends AccessControlTransacti @Override protected void transaction() throws Exception { - this.validator = - Database.execute(new RetrievePasswordValidator(this.name), getAccess()).getValidator(); + this.validator = execute(new RetrievePasswordValidator(this.name), getAccess()).getValidator(); if (this.validator == null) { throw ServerMessages.ACCOUNT_DOES_NOT_EXIST; } diff --git a/src/main/java/caosdb/server/transaction/RetrievePermissionRulesTransaction.java b/src/main/java/caosdb/server/transaction/RetrievePermissionRulesTransaction.java index 187a277bf8724eb343e52b84364b7b10fc781641..d02722fd9e89e70c26e8782252c65fb9e199158c 100644 --- a/src/main/java/caosdb/server/transaction/RetrievePermissionRulesTransaction.java +++ b/src/main/java/caosdb/server/transaction/RetrievePermissionRulesTransaction.java @@ -22,7 +22,6 @@ */ package caosdb.server.transaction; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrievePermissionRules; import caosdb.server.database.backend.transaction.RetrieveRole; import caosdb.server.permissions.PermissionRule; @@ -40,10 +39,10 @@ public class RetrievePermissionRulesTransaction extends AccessControlTransaction @Override protected void transaction() throws Exception { - if (Database.execute(new RetrieveRole(this.role), getAccess()).getRole() == null) { + if (execute(new RetrieveRole(this.role), getAccess()).getRole() == null) { throw ServerMessages.ROLE_DOES_NOT_EXIST; } - this.rules = Database.execute(new RetrievePermissionRules(this.role), getAccess()).getRules(); + this.rules = execute(new RetrievePermissionRules(this.role), getAccess()).getRules(); } public HashSet<PermissionRule> getRules() { diff --git a/src/main/java/caosdb/server/transaction/RetrieveRoleTransaction.java b/src/main/java/caosdb/server/transaction/RetrieveRoleTransaction.java index bcadbac85942a4b1e66e7676c1675647427251ff..4d019f87fb572ce8e75393302764e8146034ee22 100644 --- a/src/main/java/caosdb/server/transaction/RetrieveRoleTransaction.java +++ b/src/main/java/caosdb/server/transaction/RetrieveRoleTransaction.java @@ -23,7 +23,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.Role; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveRole; import caosdb.server.utils.ServerMessages; @@ -38,7 +37,7 @@ public class RetrieveRoleTransaction extends AccessControlTransaction { @Override protected void transaction() throws Exception { - this.role = Database.execute(new RetrieveRole(this.name), getAccess()).getRole(); + this.role = execute(new RetrieveRole(this.name), getAccess()).getRole(); if (this.role == null) { throw ServerMessages.ROLE_DOES_NOT_EXIST; } diff --git a/src/main/java/caosdb/server/transaction/RetrieveSparseEntityByPath.java b/src/main/java/caosdb/server/transaction/RetrieveSparseEntityByPath.java index 3530d6dad9ec5a134a9613a0a7ece61f53a20edb..2b936247bba9ece2d4bb9ab5cb1a5a1b2cbada74 100644 --- a/src/main/java/caosdb/server/transaction/RetrieveSparseEntityByPath.java +++ b/src/main/java/caosdb/server/transaction/RetrieveSparseEntityByPath.java @@ -22,7 +22,6 @@ */ package caosdb.server.transaction; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.GetFileRecordByPath; import caosdb.server.database.backend.transaction.RetrieveSparseEntity; import caosdb.server.entity.EntityInterface; @@ -58,9 +57,9 @@ public class RetrieveSparseEntityByPath extends Transaction<TransactionContainer protected void transaction() throws Exception { for (final EntityInterface e : getContainer()) { final GetFileRecordByPath r = - Database.execute(new GetFileRecordByPath(e.getFileProperties().getPath()), getAccess()); + execute(new GetFileRecordByPath(e.getFileProperties().getPath()), getAccess()); e.setId(r.getId()); - Database.execute(new RetrieveSparseEntity(e), getAccess()); + execute(new RetrieveSparseEntity(e), getAccess()); } } diff --git a/src/main/java/caosdb/server/transaction/RetrieveUserTransaction.java b/src/main/java/caosdb/server/transaction/RetrieveUserTransaction.java index 93c5eb5c638ff8d4ee36d0c1416bd7f980c10378..f2728a64664ad72f113e55a91ef87496810ad7c6 100644 --- a/src/main/java/caosdb/server/transaction/RetrieveUserTransaction.java +++ b/src/main/java/caosdb/server/transaction/RetrieveUserTransaction.java @@ -25,7 +25,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.Principal; import caosdb.server.accessControl.UserSources; import caosdb.server.accessControl.UserStatus; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveUser; import caosdb.server.database.proto.ProtoUser; import caosdb.server.utils.ServerMessages; @@ -46,7 +45,7 @@ public class RetrieveUserTransaction extends AccessControlTransaction { if (!UserSources.isUserExisting(this.principal)) { throw ServerMessages.ACCOUNT_DOES_NOT_EXIST; } - this.user = Database.execute(new RetrieveUser(this.principal), getAccess()).getUser(); + this.user = execute(new RetrieveUser(this.principal), getAccess()).getUser(); if (this.user == null) { this.user = new ProtoUser(); diff --git a/src/main/java/caosdb/server/transaction/Transaction.java b/src/main/java/caosdb/server/transaction/Transaction.java index 3e511257b239627c61064acc5d011d79516bbb08..28b8276e2b93699f2315fb754303194208bb37e5 100644 --- a/src/main/java/caosdb/server/transaction/Transaction.java +++ b/src/main/java/caosdb/server/transaction/Transaction.java @@ -25,11 +25,11 @@ package caosdb.server.transaction; import caosdb.datetime.UTCDateTime; import caosdb.server.accessControl.AuthenticationUtils; import caosdb.server.accessControl.Principal; -import caosdb.server.database.Database; import caosdb.server.database.DatabaseMonitor; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.InsertTransactionHistory; import caosdb.server.database.exceptions.TransactionException; +import caosdb.server.database.misc.TransactionBenchmark; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.Message; import caosdb.server.entity.Message.MessageType; @@ -55,6 +55,11 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra public static final Message ERROR_INTEGRITY_VIOLATION = new Message(MessageType.Error, 0, "This entity caused an unexpected integrity violation."); + @Override + public TransactionBenchmark getTransactionBenchmark() { + return getContainer().getTransactionBenchmark(); + } + private static final DatabaseMonitor monitor = DatabaseMonitor.getInstance(); public static final String CLEAN_UP = "TransactionCleanUp"; @@ -93,7 +98,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra this.schedule.addAll(Job.loadPermanentContainerJobs(this)); for (final EntityInterface e : getContainer()) { - final List<Job> loadJobs = Job.loadJobs(e, this); + final List<Job> loadJobs = loadContainerFlags.loadJobs(e, this); this.schedule.addAll(loadJobs); // additionally load datatype job @@ -126,21 +131,22 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra this.schedule.runJobs(JobExecutionTime.INIT); getContainer() .getTransactionBenchmark() - .addBenchmark(this.getClass().getSimpleName() + ".init", System.currentTimeMillis() - t1); + .addMeasurement( + this.getClass().getSimpleName() + ".init", System.currentTimeMillis() - t1); t1 = System.currentTimeMillis(); preCheck(); this.schedule.runJobs(JobExecutionTime.PRE_CHECK); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".pre_check", System.currentTimeMillis() - t1); t1 = System.currentTimeMillis(); check(); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".check", System.currentTimeMillis() - t1); t1 = System.currentTimeMillis(); @@ -148,7 +154,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra postCheck(); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".post_check", System.currentTimeMillis() - t1); t1 = System.currentTimeMillis(); @@ -156,7 +162,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra this.schedule.runJobs(JobExecutionTime.PRE_TRANSACTION); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".pre_transaction", System.currentTimeMillis() - t1); @@ -164,7 +170,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra transaction(); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".transaction", System.currentTimeMillis() - t1); t1 = System.currentTimeMillis(); @@ -172,7 +178,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra postTransaction(); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".post_transaction", System.currentTimeMillis() - t1); @@ -180,14 +186,14 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra writeHistory(); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".history", System.currentTimeMillis() - t1); t1 = System.currentTimeMillis(); commit(); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".commit", System.currentTimeMillis() - t1); } catch (final Exception e) { @@ -198,7 +204,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra cleanUp(); getContainer() .getTransactionBenchmark() - .addBenchmark( + .addMeasurement( this.getClass().getSimpleName() + ".cleanup", System.currentTimeMillis() - t1); notifyObservers(CLEAN_UP); } @@ -229,7 +235,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra getTransactor().getPrincipal() == AuthenticationUtils.ANONYMOUS_USER.getPrincipal() ? "anonymous" : ((Principal) getTransactor().getPrincipal()).getUsername(); - Database.execute( + execute( new InsertTransactionHistory( getContainer(), this.getClass().getSimpleName(), realm, username, getTimestamp()), getAccess()); diff --git a/src/main/java/caosdb/server/transaction/TransactionInterface.java b/src/main/java/caosdb/server/transaction/TransactionInterface.java index 2dfb3d4201a864795ca76bcdbe6872fa76ab8e9d..1aaf2786cc613709c59c92b7102474cead00ca1c 100644 --- a/src/main/java/caosdb/server/transaction/TransactionInterface.java +++ b/src/main/java/caosdb/server/transaction/TransactionInterface.java @@ -22,7 +22,26 @@ */ package caosdb.server.transaction; +import caosdb.server.database.BackendTransaction; +import caosdb.server.database.access.Access; +import caosdb.server.database.misc.RollBackHandler; +import caosdb.server.database.misc.TransactionBenchmark; + public interface TransactionInterface { public void execute() throws Exception; + + public default TransactionBenchmark getTransactionBenchmark() { + return TransactionBenchmark.getRootInstance().getBenchmark(getClass()); + } + + public default <K extends BackendTransaction> K execute(K t, Access access) { + final RollBackHandler handler = (RollBackHandler) access.getHelper("RollBack"); + handler.append(t); + t.setAccess(access); + + t.setTransactionBenchmark(getTransactionBenchmark().getBenchmark(t.getClass())); + t.executeTransaction(); + return t; + } } diff --git a/src/main/java/caosdb/server/transaction/Update.java b/src/main/java/caosdb/server/transaction/Update.java index 8cb14a66716c711656acf6af2dd037110b0f5025..8edd27d0aa0250ffebadc8d9a9639490daf1e2c7 100644 --- a/src/main/java/caosdb/server/transaction/Update.java +++ b/src/main/java/caosdb/server/transaction/Update.java @@ -23,7 +23,6 @@ package caosdb.server.transaction; import caosdb.server.CaosDBException; -import caosdb.server.database.Database; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.RetrieveFullEntity; import caosdb.server.database.backend.transaction.UpdateEntity; @@ -82,7 +81,7 @@ public class Update extends WriteTransaction<UpdateContainer> { // retrieve a container which contains all id of those entities // which are to be updated. - Database.execute(new RetrieveFullEntity(oldContainer), getAccess()); + execute(new RetrieveFullEntity(oldContainer), getAccess()); // Check if any updates are to be processed. for (final EntityInterface newEntity : getContainer()) { @@ -169,10 +168,9 @@ public class Update extends WriteTransaction<UpdateContainer> { update(getContainer(), getAccess()); } - public static void update(final TransactionContainer container, final Access access) - throws Exception { + private void update(final TransactionContainer container, final Access access) throws Exception { if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) { - Database.execute(new UpdateEntity(container), access); + execute(new UpdateEntity(container), access); } } diff --git a/src/main/java/caosdb/server/transaction/UpdatePermissionRulesTransaction.java b/src/main/java/caosdb/server/transaction/UpdatePermissionRulesTransaction.java index 450e89e0d900a34964976d668ff5cb0a3e500cf4..e537b001f2af65e35c65e8c8ad88d37a2fd2bc01 100644 --- a/src/main/java/caosdb/server/transaction/UpdatePermissionRulesTransaction.java +++ b/src/main/java/caosdb/server/transaction/UpdatePermissionRulesTransaction.java @@ -23,7 +23,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.ACMPermissions; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveRole; import caosdb.server.database.backend.transaction.SetPermissionRules; import caosdb.server.permissions.PermissionRule; @@ -46,10 +45,10 @@ public class UpdatePermissionRulesTransaction extends AccessControlTransaction { SecurityUtils.getSubject() .checkPermission(ACMPermissions.PERMISSION_UPDATE_ROLE_PERMISSIONS(this.role)); - if (Database.execute(new RetrieveRole(this.role), getAccess()).getRole() == null) { + if (execute(new RetrieveRole(this.role), getAccess()).getRole() == null) { throw ServerMessages.ROLE_DOES_NOT_EXIST; } - Database.execute(new SetPermissionRules(this.role, this.rules), getAccess()); + execute(new SetPermissionRules(this.role, this.rules), getAccess()); } } diff --git a/src/main/java/caosdb/server/transaction/UpdateRoleTransaction.java b/src/main/java/caosdb/server/transaction/UpdateRoleTransaction.java index e4ca75051e757dfb227585b11153b2ae5c802a82..dfec776005800469654f144a0c5ae6f0213a04ad 100644 --- a/src/main/java/caosdb/server/transaction/UpdateRoleTransaction.java +++ b/src/main/java/caosdb/server/transaction/UpdateRoleTransaction.java @@ -25,7 +25,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.ACMPermissions; import caosdb.server.accessControl.Role; import caosdb.server.accessControl.UserSources; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.InsertRole; import caosdb.server.database.backend.transaction.RetrieveRole; import caosdb.server.utils.ServerMessages; @@ -48,7 +47,7 @@ public class UpdateRoleTransaction extends AccessControlTransaction { throw ServerMessages.ROLE_DOES_NOT_EXIST; } - Database.execute(new InsertRole(this.role), getAccess()); + execute(new InsertRole(this.role), getAccess()); RetrieveRole.removeCached(this.role.name); } } diff --git a/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java b/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java index 6b8a93b0c3da1674e1ab9b1589c85b9b0116f1ec..257e8c06cc9d9c9f24774e541cea611663f5ff0d 100644 --- a/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java +++ b/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java @@ -25,7 +25,6 @@ package caosdb.server.transaction; import caosdb.server.accessControl.ACMPermissions; import caosdb.server.accessControl.Principal; import caosdb.server.accessControl.UserSources; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveRole; import caosdb.server.database.backend.transaction.UpdateUserRoles; import caosdb.server.utils.ServerMessages; @@ -56,7 +55,7 @@ public class UpdateUserRolesTransaction extends AccessControlTransaction { SecurityUtils.getSubject().checkPermission(ACMPermissions.PERMISSION_ASSIGN_ROLE(role)); // test if role is existent - if (Database.execute(new RetrieveRole(role), getAccess()).getRole() == null) { + if (execute(new RetrieveRole(role), getAccess()).getRole() == null) { throw ServerMessages.ROLE_DOES_NOT_EXIST; } } @@ -65,7 +64,7 @@ public class UpdateUserRolesTransaction extends AccessControlTransaction { throw ServerMessages.ACCOUNT_DOES_NOT_EXIST; } - Database.execute(new UpdateUserRoles(this.realm, this.user, this.roles), getAccess()); + execute(new UpdateUserRoles(this.realm, this.user, this.roles), getAccess()); } public Element getUserRolesElement() { diff --git a/src/main/java/caosdb/server/transaction/UpdateUserTransaction.java b/src/main/java/caosdb/server/transaction/UpdateUserTransaction.java index 663367c21a34c14392bcd0b60113d1e82e1e0539..ca29bb7977da8fc677c774b30a1f3fa78879c5a7 100644 --- a/src/main/java/caosdb/server/transaction/UpdateUserTransaction.java +++ b/src/main/java/caosdb/server/transaction/UpdateUserTransaction.java @@ -26,7 +26,6 @@ import caosdb.server.accessControl.ACMPermissions; import caosdb.server.accessControl.Principal; import caosdb.server.accessControl.UserSources; import caosdb.server.accessControl.UserStatus; -import caosdb.server.database.Database; import caosdb.server.database.backend.transaction.RetrieveUser; import caosdb.server.database.backend.transaction.SetPassword; import caosdb.server.database.backend.transaction.UpdateUser; @@ -88,23 +87,22 @@ public class UpdateUserTransaction extends AccessControlTransaction { if (this.password.isEmpty()) { // reset password - Database.execute(new SetPassword(this.user.name, null), getAccess()); + execute(new SetPassword(this.user.name, null), getAccess()); } else { Utils.checkPasswordStrength(this.password); - Database.execute(new SetPassword(this.user.name, this.password), getAccess()); + execute(new SetPassword(this.user.name, this.password), getAccess()); } } if (isToBeUpdated()) { - Database.execute(new UpdateUser(this.user), getAccess()); + execute(new UpdateUser(this.user), getAccess()); } } private boolean isToBeUpdated() throws Exception { boolean isToBeUpdated = false; final ProtoUser validUser = - Database.execute( - new RetrieveUser(new Principal(this.user.realm, this.user.name)), getAccess()) + execute(new RetrieveUser(new Principal(this.user.realm, this.user.name)), getAccess()) .getUser(); if (this.user.status != null && (validUser == null || this.user.status != validUser.status)) { SecurityUtils.getSubject() diff --git a/src/main/java/caosdb/server/transaction/WriteTransaction.java b/src/main/java/caosdb/server/transaction/WriteTransaction.java index a666e9737a50af039d124178ddf507905e38d7ef..e67ae0600bc573efbdf67b9b341299fe1fe3ca00 100644 --- a/src/main/java/caosdb/server/transaction/WriteTransaction.java +++ b/src/main/java/caosdb/server/transaction/WriteTransaction.java @@ -25,7 +25,6 @@ package caosdb.server.transaction; import caosdb.server.database.misc.RollBackHandler; import caosdb.server.entity.FileProperties; import caosdb.server.entity.container.TransactionContainer; -import caosdb.server.utils.ChecksumUpdater; public abstract class WriteTransaction<C extends TransactionContainer> extends Transaction<C> { diff --git a/src/main/java/caosdb/server/utils/Info.java b/src/main/java/caosdb/server/utils/Info.java index 445374a105fbe8fbff1bc95a90fcceba197b09f4..e35b77bfbd18e12b3fd5c82112bffc4d337eac3a 100644 --- a/src/main/java/caosdb/server/utils/Info.java +++ b/src/main/java/caosdb/server/utils/Info.java @@ -24,7 +24,6 @@ package caosdb.server.utils; import caosdb.server.CaosDBServer; import caosdb.server.FileSystem; -import caosdb.server.database.Database; import caosdb.server.database.DatabaseMonitor; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.GetInfo; @@ -37,6 +36,8 @@ import java.io.File; import java.io.IOException; import java.sql.SQLException; import java.util.LinkedList; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.jdom2.Element; public class Info extends AbstractObservable implements Observer, TransactionInterface { @@ -44,33 +45,32 @@ public class Info extends AbstractObservable implements Observer, TransactionInt private static Info instance = new Info(); public static final String SYNC_DATABASE_EVENT = "SyncDatabaseEvent"; private final Access access; + public Logger logger = LogManager.getLogger(getClass()); @Override public boolean notifyObserver(final String e, final Observable o) { try { syncDatabase(); } catch (final Exception exc) { - exc.printStackTrace(); + logger.error(exc); } return true; } - static { + private Info() { + this.access = DatabaseMonitor.getInfoAccess(this); try { syncDatabase(); - } catch (final Exception e) { - e.printStackTrace(); + } catch (final Exception exc) { + logger.error(exc); } } - private Info() { - this.access = DatabaseMonitor.getInfoAccess(this); - } - public static Info getInstance() { return instance; } + private Long lastSync = 0L; private static File dropOffBox = null; private static int filesCount = -1; private static int propertiesCount = -1; @@ -145,12 +145,22 @@ public class Info extends AbstractObservable implements Observer, TransactionInt return ret; } - public static void syncDatabase() throws Exception { - final Access access = getInstance().access; + public long timeSinceSync() { + long time = System.currentTimeMillis(); + return time - lastSync; + } + + public void syncDatabase() throws Exception { + synchronized (lastSync) { + if (timeSinceSync() < 10000) { + return; + } + lastSync = System.currentTimeMillis(); + } final ProtoInfo i = new ProtoInfo(); final GetInfo t = new GetInfo(i); - Database.execute(t, access); + execute(t, access); filesCount = i.filesCount; recordsCount = i.recordsCount; recordTypesCount = i.recordTypesCount; @@ -158,7 +168,7 @@ public class Info extends AbstractObservable implements Observer, TransactionInt fssize = Utils.getReadableByteSize(i.fssize); tmpFilesCount = countTmpFiles(); - getInstance().notifyObservers(SYNC_DATABASE_EVENT); + notifyObservers(SYNC_DATABASE_EVENT); } private static int countTmpFiles() throws IOException { @@ -221,12 +231,12 @@ public class Info extends AbstractObservable implements Observer, TransactionInt return info; } - public static void syncDatabase(final ServerStat stat) throws TransactionException, Message { + public void syncDatabase(final ServerStat stat) throws TransactionException, Message { final Access access = getInstance().access; final SyncStats t = new SyncStats(stat); - Database.execute(t, access); + execute(t, access); } @Override diff --git a/src/test/java/caosdb/server/Misc.java b/src/test/java/caosdb/server/Misc.java index 92e8b198bf8cd60b8407dac4e7fcd4e9ed671a25..bcdc1729f008dbb1393fe238a3eb763c67d69e0f 100644 --- a/src/test/java/caosdb/server/Misc.java +++ b/src/test/java/caosdb/server/Misc.java @@ -25,7 +25,6 @@ package caosdb.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import caosdb.server.database.misc.TransactionBenchmark; @@ -37,11 +36,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.jcs.JCS; -import org.apache.commons.jcs.access.CacheAccess; import org.apache.shiro.SecurityUtils; import org.apache.shiro.config.Ini; import org.apache.shiro.config.IniSecurityManagerFactory; @@ -205,26 +201,6 @@ public class Misc { assertEquals(null, m.group(2)); } - @Test - public void testCache() throws IOException { - final Properties p = new Properties(); - p.load( - new FileInputStream( - System.getProperty("user.dir") + "/src/test/java/caosdb/server/cache.ccf")); - JCS.setConfigProperties(p); - - final CacheAccess<Object, Object> cache = JCS.getInstance("default"); - JCS.getInstance("default"); - - final String key = "KEY"; - final String value = "VALUE"; - - cache.put(key, value); - - assertEquals(value, cache.get(key)); - assertSame(value, cache.get(key)); - } - @Test public void testCrobJob() throws InterruptedException { new CronJob( @@ -295,11 +271,11 @@ public class Misc { @Test public void benchmarkSerialization() throws IOException, ClassNotFoundException { - TransactionBenchmark.getInstance().addBenchmark("bla", 1000); + TransactionBenchmark.getRootInstance().addMeasurement("bla", 1000); final FileOutputStream fileOut = new FileOutputStream("/tmp/benchmark.java.ser"); final ObjectOutputStream out = new ObjectOutputStream(fileOut); - out.writeObject(TransactionBenchmark.getInstance()); + out.writeObject(TransactionBenchmark.getRootInstance()); out.close(); fileOut.close(); System.out.printf("Serialized data is saved in /tmp/benchmark.java.ser"); diff --git a/src/test/java/caosdb/server/cache.ccf b/src/test/java/caosdb/server/cache.ccf deleted file mode 100644 index d57b1c9f63d44f6436532e686b3609dd33df00d3..0000000000000000000000000000000000000000 --- a/src/test/java/caosdb/server/cache.ccf +++ /dev/null @@ -1,4 +0,0 @@ -jcs.default=DC -jcs.default.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes -jcs.default.cacheattributes.MaxObjects=1000 -jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache \ No newline at end of file diff --git a/src/test/java/caosdb/server/caching/TestCaching.java b/src/test/java/caosdb/server/caching/TestCaching.java new file mode 100644 index 0000000000000000000000000000000000000000..56d8e750ab75663e29808a0f97962df88006d080 --- /dev/null +++ b/src/test/java/caosdb/server/caching/TestCaching.java @@ -0,0 +1,52 @@ +package caosdb.server.caching; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import caosdb.server.CaosDBServer; +import caosdb.server.accessControl.Pam; +import caosdb.server.database.backend.transaction.RetrieveProperties; +import java.io.IOException; +import org.apache.commons.jcs.JCS; +import org.apache.commons.jcs.access.CacheAccess; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestCaching { + + @BeforeClass + public static void init() throws IOException { + CaosDBServer.initServerProperties(); + JCSCacheHelper.init(); + } + + @Test + public void testCacheConfig() { + CacheAccess<String, String> retrieve_properties_cache = + JCS.getInstance(RetrieveProperties.CACHE_REGION); + assertEquals(1003, retrieve_properties_cache.getCacheAttributes().getMaxObjects()); + + CacheAccess<String, String> retrieve_entities_cache = JCS.getInstance("BACKEND_SparseEntities"); + assertEquals(1002, retrieve_entities_cache.getCacheAttributes().getMaxObjects()); + + CacheAccess<String, String> pam_groups_cache = JCS.getInstance(Pam.CACHE_REGION_GROUPS); + assertEquals(1000, pam_groups_cache.getCacheAttributes().getMaxObjects()); + assertEquals(false, pam_groups_cache.getCacheAttributes().isUseMemoryShrinker()); + assertEquals(false, pam_groups_cache.getDefaultElementAttributes().getIsEternal()); + assertEquals(61, pam_groups_cache.getDefaultElementAttributes().getIdleTime()); + assertEquals(601, pam_groups_cache.getDefaultElementAttributes().getMaxLife()); + } + + @Test + public void testCacheElements() throws IOException { + final CacheAccess<Object, Object> cache = JCS.getInstance("default"); + + final String key = "KEY"; + final String value = "VALUE"; + + cache.put(key, value); + + assertEquals(value, cache.get(key)); + assertSame(value, cache.get(key)); + } +} diff --git a/src/test/java/caosdb/server/resource/TestScriptingResource.java b/src/test/java/caosdb/server/resource/TestScriptingResource.java index 353a2ea220984705b2612e01fe8460d5c2d7b457..2edfb82b53b56324996293a469fadf807264d86c 100644 --- a/src/test/java/caosdb/server/resource/TestScriptingResource.java +++ b/src/test/java/caosdb/server/resource/TestScriptingResource.java @@ -38,6 +38,7 @@ import caosdb.server.database.backend.interfaces.RetrievePermissionRulesImpl; import caosdb.server.database.backend.interfaces.RetrieveRoleImpl; import caosdb.server.database.backend.interfaces.RetrieveUserImpl; import caosdb.server.database.exceptions.TransactionException; +import caosdb.server.database.misc.TransactionBenchmark; import caosdb.server.database.proto.ProtoUser; import caosdb.server.entity.Message; import caosdb.server.permissions.PermissionRule; @@ -76,6 +77,14 @@ public class TestScriptingResource { ret.description = "bla"; return ret; } + + @Override + public TransactionBenchmark getBenchmark() { + return null; + } + + @Override + public void setTransactionBenchmark(TransactionBenchmark b) {} } public static class RetrievePermissionRules implements RetrievePermissionRulesImpl { @@ -86,6 +95,14 @@ public class TestScriptingResource { public HashSet<PermissionRule> retrievePermissionRule(String role) throws TransactionException { return new HashSet<>(); } + + @Override + public TransactionBenchmark getBenchmark() { + return null; + } + + @Override + public void setTransactionBenchmark(TransactionBenchmark b) {} } public static class RetrieveUser implements RetrieveUserImpl { @@ -96,6 +113,14 @@ public class TestScriptingResource { public ProtoUser execute(Principal principal) throws TransactionException { return new ProtoUser(); } + + @Override + public TransactionBenchmark getBenchmark() { + return null; + } + + @Override + public void setTransactionBenchmark(TransactionBenchmark b) {} } public static class RetrievePasswordValidator implements RetrievePasswordValidatorImpl { @@ -112,6 +137,14 @@ public class TestScriptingResource { } }; } + + @Override + public void setTransactionBenchmark(TransactionBenchmark b) {} + + @Override + public TransactionBenchmark getBenchmark() { + return null; + } } @BeforeClass diff --git a/src/test/java/caosdb/server/utils/FileUtilsTest.java b/src/test/java/caosdb/server/utils/FileUtilsTest.java index c80f8ebb8b71785dcf8b6f5c8adaaec5e61b0332..e4b2411dc0e77ce0225c0637422c84bbab2cc4aa 100644 --- a/src/test/java/caosdb/server/utils/FileUtilsTest.java +++ b/src/test/java/caosdb/server/utils/FileUtilsTest.java @@ -31,7 +31,7 @@ import caosdb.server.CaosDBException; import caosdb.server.CaosDBServer; import caosdb.server.FileSystem; import caosdb.server.ServerProperties; -import caosdb.server.database.Database; +import caosdb.server.database.BackendTransaction; import caosdb.server.database.access.Access; import caosdb.server.database.backend.implementation.UnixFileSystem.UnixFileSystemGetFileIterator.FileNameIterator; import caosdb.server.database.backend.implementation.UnixFileSystem.UnixFileSystemHelper; @@ -557,7 +557,7 @@ public class FileUtilsTest { access.setHelper("UnixFileSystemHelper", h); FileConsistencyCheck check = - Database.execute(new FileConsistencyCheck("test1.dat", 0, null, 0L, null), access); + execute(new FileConsistencyCheck("test1.dat", 0, null, 0L, null), access); assertEquals(FileConsistencyCheck.FILE_DOES_NOT_EXIST, check.getResult()); final File f = new File(rootPath + "test1.dat"); @@ -573,9 +573,7 @@ public class FileUtilsTest { final long size = f.length(); final long timestamp = f.lastModified(); - check = - Database.execute( - new FileConsistencyCheck("test1.dat", size, hash, timestamp, hasher), access); + check = execute(new FileConsistencyCheck("test1.dat", size, hash, timestamp, hasher), access); assertEquals(FileConsistencyCheck.OK, check.getResult()); // timestamp has 1 second accuracy @@ -592,9 +590,7 @@ public class FileUtilsTest { assertTrue(timestamp2 > timestamp); assertTrue(f.exists()); - check = - Database.execute( - new FileConsistencyCheck("test1.dat", size2, hash, timestamp, hasher), access); + check = execute(new FileConsistencyCheck("test1.dat", size2, hash, timestamp, hasher), access); assertEquals(FileConsistencyCheck.OK, check.getResult()); out = new PrintStream(f); @@ -602,12 +598,16 @@ public class FileUtilsTest { out.flush(); out.close(); - check = - Database.execute( - new FileConsistencyCheck("test1.dat", size, hash, timestamp, hasher), access); + check = execute(new FileConsistencyCheck("test1.dat", size, hash, timestamp, hasher), access); assertEquals(FileConsistencyCheck.FILE_MODIFIED, check.getResult()); } + private <K extends BackendTransaction> K execute(K t, Access access2) { + t.setAccess(access2); + t.executeTransaction(); + return t; + } + @Test public void testFileIterator() throws IOException { final String rootPath = "./testFileIterator/"; @@ -674,8 +674,7 @@ public class FileUtilsTest { dat3.deleteOnExit(); dat3.createNewFile(); - final Iterator<String> iterator = - Database.execute(new GetFileIterator(rootPath), access).getIterator(); + final Iterator<String> iterator = execute(new GetFileIterator(rootPath), access).getIterator(); assertEquals(rootPath + "dat1", iterator.next()); assertEquals(rootPath + "dat2", iterator.next());