Skip to content
Snippets Groups Projects
Verified Commit d6773d6c authored by Timm Fitschen's avatar Timm Fitschen
Browse files

Merge branch 'f-fsm' into f-fsm-v0.2

parents 71590d03 d6fbc634
No related branches found
No related tags found
3 merge requests!21Release v0.4.0,!7F fsm,!6Draft: F acm permissions2
Showing
with 228 additions and 316 deletions
...@@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
by setting the server property `EXT_ENTITY_STATE=ENABLED`. See by setting the server property `EXT_ENTITY_STATE=ENABLED`. See
[!62](https://gitlab.com/caosdb/caosdb-server/-/merge_requests/62) for more [!62](https://gitlab.com/caosdb/caosdb-server/-/merge_requests/62) for more
information. information.
* New version history feature. The "H" container flag retrieves the full
version history during a transaction (e.g. during Retrievals) and constructs
a tree of successors and predecessors of the requested entity version.
* New query functionality: `ANY VERSION OF` modifier. E.g. `FIND ANY VERSION OF * New query functionality: `ANY VERSION OF` modifier. E.g. `FIND ANY VERSION OF
RECORD WITH pname=val` returns all current and old versions of records where RECORD WITH pname=val` returns all current and old versions of records where
`pname=val`. For further information, examples and limitations see the wiki `pname=val`. For further information, examples and limitations see the wiki
......
...@@ -28,8 +28,8 @@ jcs.region.BACKEND_JobRules.cacheattributes.MaxObjects=103 ...@@ -28,8 +28,8 @@ jcs.region.BACKEND_JobRules.cacheattributes.MaxObjects=103
jcs.region.BACKEND_SparseEntities jcs.region.BACKEND_SparseEntities
jcs.region.BACKEND_SparseEntities.cacheattributes.MaxObjects=1002 jcs.region.BACKEND_SparseEntities.cacheattributes.MaxObjects=1002
jcs.region.BACKEND_RetrieveFullVersionInfo jcs.region.BACKEND_RetrieveVersionHistory
jcs.region.BACKEND_RetrieveFullVersionInfo.cacheattributes.MaxObjects=1006 jcs.region.BACKEND_RetrieveVersionHistory.cacheattributes.MaxObjects=1006
# PAM UserSource Caching: Cached Items expire after 60 seconds if they are not requested (idle) and after 600 seconds max. # PAM UserSource Caching: Cached Items expire after 60 seconds if they are not requested (idle) and after 600 seconds max.
# PAM_UnixUserGroups # PAM_UnixUserGroups
......
...@@ -68,7 +68,7 @@ MYSQL_USER_NAME=caosdb ...@@ -68,7 +68,7 @@ MYSQL_USER_NAME=caosdb
# Password for the user # Password for the user
MYSQL_USER_PASSWORD=caosdb MYSQL_USER_PASSWORD=caosdb
# Schema of mysql procedures and tables which is required by this CaosDB instance # Schema of mysql procedures and tables which is required by this CaosDB instance
MYSQL_SCHEMA_VERSION=v4.0.0-rc1 MYSQL_SCHEMA_VERSION=v4.0.0-rc2
# -------------------------------------------------- # --------------------------------------------------
......
...@@ -59,7 +59,6 @@ import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveProp ...@@ -59,7 +59,6 @@ import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveProp
import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveQueryTemplateDefinition; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveQueryTemplateDefinition;
import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveRole; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveRole;
import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveSparseEntity; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveSparseEntity;
import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveTransactionHistory;
import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveUser; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveUser;
import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveVersionHistory; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveVersionHistory;
import org.caosdb.server.database.backend.implementation.MySQL.MySQLRuleLoader; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRuleLoader;
...@@ -116,7 +115,6 @@ import org.caosdb.server.database.backend.interfaces.RetrievePropertiesImpl; ...@@ -116,7 +115,6 @@ import org.caosdb.server.database.backend.interfaces.RetrievePropertiesImpl;
import org.caosdb.server.database.backend.interfaces.RetrieveQueryTemplateDefinitionImpl; import org.caosdb.server.database.backend.interfaces.RetrieveQueryTemplateDefinitionImpl;
import org.caosdb.server.database.backend.interfaces.RetrieveRoleImpl; import org.caosdb.server.database.backend.interfaces.RetrieveRoleImpl;
import org.caosdb.server.database.backend.interfaces.RetrieveSparseEntityImpl; import org.caosdb.server.database.backend.interfaces.RetrieveSparseEntityImpl;
import org.caosdb.server.database.backend.interfaces.RetrieveTransactionHistoryImpl;
import org.caosdb.server.database.backend.interfaces.RetrieveUserImpl; import org.caosdb.server.database.backend.interfaces.RetrieveUserImpl;
import org.caosdb.server.database.backend.interfaces.RetrieveVersionHistoryImpl; import org.caosdb.server.database.backend.interfaces.RetrieveVersionHistoryImpl;
import org.caosdb.server.database.backend.interfaces.RuleLoaderImpl; import org.caosdb.server.database.backend.interfaces.RuleLoaderImpl;
...@@ -177,7 +175,6 @@ public abstract class BackendTransaction implements Undoable { ...@@ -177,7 +175,6 @@ public abstract class BackendTransaction implements Undoable {
setImpl(RetrieveAllImpl.class, MySQLRetrieveAll.class); setImpl(RetrieveAllImpl.class, MySQLRetrieveAll.class);
setImpl(RegisterSubDomainImpl.class, MySQLRegisterSubDomain.class); setImpl(RegisterSubDomainImpl.class, MySQLRegisterSubDomain.class);
setImpl(RetrieveDatatypesImpl.class, MySQLRetrieveDatatypes.class); setImpl(RetrieveDatatypesImpl.class, MySQLRetrieveDatatypes.class);
setImpl(RetrieveTransactionHistoryImpl.class, MySQLRetrieveTransactionHistory.class);
setImpl(RetrieveUserImpl.class, MySQLRetrieveUser.class); setImpl(RetrieveUserImpl.class, MySQLRetrieveUser.class);
setImpl(RetrieveParentsImpl.class, MySQLRetrieveParents.class); setImpl(RetrieveParentsImpl.class, MySQLRetrieveParents.class);
setImpl(GetFileRecordByPathImpl.class, MySQLGetFileRecordByPath.class); setImpl(GetFileRecordByPathImpl.class, MySQLGetFileRecordByPath.class);
......
...@@ -216,10 +216,7 @@ public class DatabaseUtils { ...@@ -216,10 +216,7 @@ public class DatabaseUtils {
ret.fileSize = rs.getLong("FileSize"); ret.fileSize = rs.getLong("FileSize");
ret.fileHash = bytes2UTF8(rs.getBytes("FileHash")); ret.fileHash = bytes2UTF8(rs.getBytes("FileHash"));
ret.version = bytes2UTF8(rs.getBytes("Version")); ret.versionId = bytes2UTF8(rs.getBytes("Version"));
ret.versionSeconds = rs.getLong("VersionSeconds");
ret.versionNanos = rs.getInt("VersionNanos");
return ret; return ret;
} }
......
...@@ -57,7 +57,7 @@ public class MySQLInsertSparseEntity extends MySQLTransaction implements InsertS ...@@ -57,7 +57,7 @@ public class MySQLInsertSparseEntity extends MySQLTransaction implements InsertS
try (final ResultSet rs = insertEntityStmt.executeQuery()) { try (final ResultSet rs = insertEntityStmt.executeQuery()) {
if (rs.next()) { if (rs.next()) {
entity.id = rs.getInt("EntityID"); entity.id = rs.getInt("EntityID");
entity.version = DatabaseUtils.bytes2UTF8(rs.getBytes("Version")); entity.versionId = DatabaseUtils.bytes2UTF8(rs.getBytes("Version"));
} else { } else {
throw new TransactionException("Didn't get new EntityID back."); throw new TransactionException("Didn't get new EntityID back.");
} }
......
/*
* ** header v3.0
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2018 Research Group Biomedical Physics,
* Max-Planck-Institute for Dynamics and Self-Organization Göttingen
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ** end header
*/
package org.caosdb.server.database.backend.implementation.MySQL;
import static org.caosdb.server.database.DatabaseUtils.bytes2UTF8;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.caosdb.server.database.access.Access;
import org.caosdb.server.database.backend.interfaces.RetrieveTransactionHistoryImpl;
import org.caosdb.server.database.exceptions.TransactionException;
import org.caosdb.server.database.proto.ProtoTransactionLogMessage;
public class MySQLRetrieveTransactionHistory extends MySQLTransaction
implements RetrieveTransactionHistoryImpl {
public MySQLRetrieveTransactionHistory(final Access access) {
super(access);
}
public static final String STMT_RETRIEVE_HISTORY =
"SELECT transaction, realm, username, seconds, nanos FROM transaction_log WHERE entity_id=? ";
@Override
public ArrayList<ProtoTransactionLogMessage> execute(final Integer id)
throws TransactionException {
try {
final PreparedStatement stmt = prepareStatement(STMT_RETRIEVE_HISTORY);
final ArrayList<ProtoTransactionLogMessage> ret = new ArrayList<ProtoTransactionLogMessage>();
stmt.setInt(1, id);
final ResultSet rs = stmt.executeQuery();
try {
while (rs.next()) {
final String transaction = bytes2UTF8(rs.getBytes("transaction"));
final String realm = bytes2UTF8(rs.getBytes("realm"));
final String username = bytes2UTF8(rs.getBytes("username"));
final Integer seconds = rs.getInt("seconds");
final Integer nanos = rs.getInt("nanos");
ret.add(new ProtoTransactionLogMessage(transaction, realm, username, seconds, nanos));
}
return ret;
} finally {
rs.close();
}
} catch (final SQLException e) {
throw new TransactionException(e);
} catch (final ConnectionException e) {
throw new TransactionException(e);
}
}
}
...@@ -61,12 +61,16 @@ public class MySQLRetrieveVersionHistory extends MySQLTransaction ...@@ -61,12 +61,16 @@ public class MySQLRetrieveVersionHistory extends MySQLTransaction
String parentId = DatabaseUtils.bytes2UTF8(rs.getBytes("parent")); String parentId = DatabaseUtils.bytes2UTF8(rs.getBytes("parent"));
Long childSeconds = rs.getLong("child_seconds"); Long childSeconds = rs.getLong("child_seconds");
Integer childNanos = rs.getInt("child_nanos"); Integer childNanos = rs.getInt("child_nanos");
String childUsername = DatabaseUtils.bytes2UTF8(rs.getBytes("child_username"));
String childRealm = DatabaseUtils.bytes2UTF8(rs.getBytes("child_realm"));
VersionHistoryItem v = result.get(childId); VersionHistoryItem v = result.get(childId);
if (v == null) { if (v == null) {
v = new VersionHistoryItem(); v = new VersionHistoryItem();
v.id = childId; v.id = childId;
v.seconds = childSeconds; v.seconds = childSeconds;
v.nanos = childNanos; v.nanos = childNanos;
v.username = childUsername;
v.realm = childRealm;
result.put(childId, v); result.put(childId, v);
} }
......
...@@ -80,7 +80,7 @@ public class MySQLUpdateSparseEntity extends MySQLTransaction implements UpdateS ...@@ -80,7 +80,7 @@ public class MySQLUpdateSparseEntity extends MySQLTransaction implements UpdateS
ResultSet rs = updateEntityStmt.executeQuery(); ResultSet rs = updateEntityStmt.executeQuery();
if (rs.next()) { if (rs.next()) {
spe.version = DatabaseUtils.bytes2UTF8(rs.getBytes("Version")); spe.versionId = DatabaseUtils.bytes2UTF8(rs.getBytes("Version"));
} }
} catch (final SQLIntegrityConstraintViolationException e) { } catch (final SQLIntegrityConstraintViolationException e) {
......
/*
* ** header v3.0
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2018 Research Group Biomedical Physics,
* Max-Planck-Institute for Dynamics and Self-Organization Göttingen
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ** end header
*/
package org.caosdb.server.database.backend.interfaces;
import java.util.ArrayList;
import org.caosdb.server.database.exceptions.TransactionException;
import org.caosdb.server.database.proto.ProtoTransactionLogMessage;
public interface RetrieveTransactionHistoryImpl extends BackendTransactionImpl {
public ArrayList<ProtoTransactionLogMessage> execute(Integer id) throws TransactionException;
}
...@@ -69,6 +69,7 @@ public class InsertSparseEntity extends BackendTransaction { ...@@ -69,6 +69,7 @@ public class InsertSparseEntity extends BackendTransaction {
public void cleanUp() {} public void cleanUp() {}
}); });
this.entity.setId(e.id); this.entity.setId(e.id);
this.entity.setVersion(new Version(e.version)); this.entity.setVersion(new Version(e.versionId));
this.entity.getVersion().setHead(true);
} }
} }
/*
* ** header v3.0
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2018 Research Group Biomedical Physics,
* Max-Planck-Institute for Dynamics and Self-Organization Göttingen
* Copyright (C) 2019 IndiScale GmbH
* Copyright (C) 2019 Timm Fitschen (t.fitschen@indiscale.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ** end header
*/
package org.caosdb.server.database.backend.transaction;
import java.util.ArrayList;
import org.caosdb.datetime.UTCDateTime;
import org.caosdb.server.database.BackendTransaction;
import org.caosdb.server.database.backend.interfaces.RetrieveTransactionHistoryImpl;
import org.caosdb.server.database.exceptions.TransactionException;
import org.caosdb.server.database.proto.ProtoTransactionLogMessage;
import org.caosdb.server.entity.EntityInterface;
import org.caosdb.server.utils.TransactionLogMessage;
public class RetrieveTransactionHistory extends BackendTransaction {
private final EntityInterface entity;
public RetrieveTransactionHistory(final EntityInterface entity) {
this.entity = entity;
}
@Override
protected void execute() {
final RetrieveTransactionHistoryImpl t =
getImplementation(RetrieveTransactionHistoryImpl.class);
process(t.execute(entity.getId()));
}
private void process(final ArrayList<ProtoTransactionLogMessage> l) throws TransactionException {
for (final ProtoTransactionLogMessage t : l) {
final UTCDateTime dateTime = UTCDateTime.UTCSeconds(t.seconds, t.nanos);
this.entity.addTransactionLog(
new TransactionLogMessage(t.transaction, this.entity, t.username, dateTime));
}
}
}
...@@ -22,58 +22,43 @@ ...@@ -22,58 +22,43 @@
*/ */
package org.caosdb.server.database.backend.transaction; package org.caosdb.server.database.backend.transaction;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import org.caosdb.server.database.CacheableBackendTransaction; import org.caosdb.datetime.UTCDateTime;
import org.caosdb.server.database.backend.interfaces.RetrieveVersionHistoryImpl;
import org.caosdb.server.database.exceptions.TransactionException; import org.caosdb.server.database.exceptions.TransactionException;
import org.caosdb.server.database.proto.VersionHistoryItem; import org.caosdb.server.database.proto.VersionHistoryItem;
import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.EntityInterface;
import org.caosdb.server.entity.Version;
public abstract class RetrieveVersionHistory public class RetrieveVersionHistory extends VersionTransaction {
extends CacheableBackendTransaction<Integer, HashMap<String, VersionHistoryItem>> {
// TODO
// private static final ICacheAccess<String, Version> cache =
// Cache.getCache("BACKEND_RetrieveVersionHistory");
private EntityInterface entity;
private HashMap<String, VersionHistoryItem> map;
public static void removeCached(Integer entityId) {
// TODO
}
public RetrieveVersionHistory(EntityInterface e) { public RetrieveVersionHistory(EntityInterface e) {
super(null); // TODO caching super(e);
this.entity = e;
}
@Override
public HashMap<String, VersionHistoryItem> executeNoCache() throws TransactionException {
RetrieveVersionHistoryImpl impl = getImplementation(RetrieveVersionHistoryImpl.class);
return impl.execute(getKey());
} }
/** After this method call, the version map is available to the object. */
@Override @Override
protected void process(HashMap<String, VersionHistoryItem> map) throws TransactionException { protected void process(HashMap<String, VersionHistoryItem> map) throws TransactionException {
this.map = map; super.process(map);
if (!map.isEmpty()) getEntity().setVersion(getHistory());
} }
@Override @Override
protected Integer getKey() { protected Version getVersion(String id) {
return entity.getId(); Version v = new Version(id);
} VersionHistoryItem i = getHistoryItems().get(v.getId());
if (i != null) {
public HashMap<String, VersionHistoryItem> getMap() { v.setDate(UTCDateTime.UTCSeconds(i.seconds, i.nanos));
return this.map; v.setUsername(i.username);
} v.setRealm(i.realm);
}
public EntityInterface getEntity() { return v;
return this.entity;
} }
public Collection<VersionHistoryItem> getList() { private Version getHistory() {
return this.map.values(); Version v = getVersion(getEntity().getVersion().getId());
v.setSuccessors(getSuccessors(v.getId(), true));
v.setPredecessors(getPredecessors(v.getId(), true));
v.setHead(v.getSuccessors().isEmpty());
v.setCompleteHistory(true);
return v;
} }
} }
...@@ -23,14 +23,12 @@ ...@@ -23,14 +23,12 @@
package org.caosdb.server.database.backend.transaction; package org.caosdb.server.database.backend.transaction;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import org.caosdb.datetime.UTCDateTime;
import org.caosdb.server.database.exceptions.TransactionException; import org.caosdb.server.database.exceptions.TransactionException;
import org.caosdb.server.database.proto.VersionHistoryItem; import org.caosdb.server.database.proto.VersionHistoryItem;
import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.EntityInterface;
import org.caosdb.server.entity.Version; import org.caosdb.server.entity.Version;
public class RetrieveVersionInfo extends RetrieveVersionHistory { public class RetrieveVersionInfo extends VersionTransaction {
public RetrieveVersionInfo(EntityInterface e) { public RetrieveVersionInfo(EntityInterface e) {
super(e); super(e);
...@@ -39,46 +37,19 @@ public class RetrieveVersionInfo extends RetrieveVersionHistory { ...@@ -39,46 +37,19 @@ public class RetrieveVersionInfo extends RetrieveVersionHistory {
@Override @Override
protected void process(HashMap<String, VersionHistoryItem> map) throws TransactionException { protected void process(HashMap<String, VersionHistoryItem> map) throws TransactionException {
super.process(map); // Make the map available to the object. super.process(map); // Make the map available to the object.
if (!map.isEmpty()) getVersion(); if (!map.isEmpty()) getEntity().setVersion(getVersion());
} }
public Version getVersion() { @Override
Version v = getEntity().getVersion(); protected Version getVersion(String id) {
VersionHistoryItem i = getMap().get(v.getId()); return new Version(id);
if (i != null) v.setDate(UTCDateTime.UTCSeconds(i.seconds, i.nanos));
v.setPredecessors(getPredecessors(v.getId()));
v.setSuccessors(getSuccessors(v.getId()));
return v;
}
/** Return a list of direct children. */
private LinkedList<Version> getSuccessors(String id) {
LinkedList<Version> result = new LinkedList<>();
outer:
for (VersionHistoryItem i : getList()) {
if (i.parents != null)
for (String p : i.parents) {
if (id.equals(p)) {
Version successor = new Version(i.id, i.seconds, i.nanos);
result.add(successor);
continue outer;
}
}
}
return result;
} }
/** Return a list of direct parents. */ public Version getVersion() {
private LinkedList<Version> getPredecessors(String id) { Version v = getVersion(getEntity().getVersion().getId());
LinkedList<Version> result = new LinkedList<>(); v.setPredecessors(getPredecessors(v.getId(), false));
if (getMap().containsKey(id) && getMap().get(id).parents != null) v.setSuccessors(getSuccessors(v.getId(), false));
for (String p : getMap().get(id).parents) { v.setHead(v.getSuccessors().isEmpty());
VersionHistoryItem i = getMap().get(p); return v;
Version predecessor = new Version(i.id, i.seconds, i.nanos);
result.add(predecessor);
}
return result;
} }
} }
...@@ -54,6 +54,7 @@ public class UpdateEntity extends BackendTransaction { ...@@ -54,6 +54,7 @@ public class UpdateEntity extends BackendTransaction {
execute(new InsertEntityProperties(e)); execute(new InsertEntityProperties(e));
VersionTransaction.removeCached(e.getId());
execute(new RetrieveVersionInfo(e)); execute(new RetrieveVersionInfo(e));
} }
} }
......
...@@ -52,6 +52,6 @@ public class UpdateSparseEntity extends BackendTransaction { ...@@ -52,6 +52,6 @@ public class UpdateSparseEntity extends BackendTransaction {
t.execute(spe); t.execute(spe);
this.entity.setVersion(new Version(spe.version)); this.entity.setVersion(new Version(spe.versionId));
} }
} }
/*
* ** header v3.0
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
* Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ** end header
*/
package org.caosdb.server.database.backend.transaction;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.jcs.access.behavior.ICacheAccess;
import org.caosdb.server.caching.Cache;
import org.caosdb.server.database.CacheableBackendTransaction;
import org.caosdb.server.database.backend.interfaces.RetrieveVersionHistoryImpl;
import org.caosdb.server.database.exceptions.TransactionException;
import org.caosdb.server.database.proto.VersionHistoryItem;
import org.caosdb.server.entity.EntityInterface;
import org.caosdb.server.entity.Version;
/**
* Abstract base class which retrieves and caches the full, but flag version history. The
* implementations then use the flat version history to construct either single version information
* items (see {@link RetrieveVersionInfo}) or the complete history as a tree (see {@link
* RetrieveVersionHistory})
*
* @author Timm Fitschen (t.fitschen@indiscale.com)
*/
public abstract class VersionTransaction
extends CacheableBackendTransaction<Integer, HashMap<String, VersionHistoryItem>> {
private static final ICacheAccess<Integer, HashMap<String, VersionHistoryItem>> cache =
Cache.getCache("BACKEND_RetrieveVersionHistory");
private EntityInterface entity;
/** A map of all history items which belong to this entity. The keys are the version ids. */
private HashMap<String, VersionHistoryItem> historyItems;
/**
* Invalidate a cache item. This should be called upon update of entities.
*
* @param entityId
*/
public static void removeCached(Integer entityId) {
cache.remove(entityId);
}
public VersionTransaction(EntityInterface e) {
super(cache);
this.entity = e;
}
@Override
public HashMap<String, VersionHistoryItem> executeNoCache() throws TransactionException {
RetrieveVersionHistoryImpl impl = getImplementation(RetrieveVersionHistoryImpl.class);
return impl.execute(getKey());
}
/** After this method call, the version map is available to the object. */
@Override
protected void process(HashMap<String, VersionHistoryItem> historyItems)
throws TransactionException {
this.historyItems = historyItems;
}
@Override
protected Integer getKey() {
return entity.getId();
}
public HashMap<String, VersionHistoryItem> getHistoryItems() {
return this.historyItems;
}
public EntityInterface getEntity() {
return this.entity;
}
/**
* Return a list of direct predecessors. The predecessors are constructed by {@link
* #getVersion(String)}.
*
* <p>If transitive is true, this function is called recursively on the predecessors as well,
* resulting in a list of trees of predecessors, with the direct predecessors at the root(s).
*
* @param versionId
* @param transitive
* @return A list of predecessors.
*/
protected List<Version> getPredecessors(String versionId, boolean transitive) {
LinkedList<Version> result = new LinkedList<>();
if (getHistoryItems().containsKey(versionId)
&& getHistoryItems().get(versionId).parents != null)
for (String p : getHistoryItems().get(versionId).parents) {
Version predecessor = getVersion(p);
if (transitive) {
predecessor.setPredecessors(getPredecessors(p, transitive));
}
result.add(predecessor);
}
return result;
}
/**
* To be implemented by the base class. The idea is, that the base class decides which information
* is being included into the Version instance.
*
* @param versionId - the id of the version
* @return
*/
protected abstract Version getVersion(String versionId);
/**
* Return a list of direct successors. The successors are constructed by {@link
* #getVersion(String)}.
*
* <p>If transitive is true, this function is called recursively on the successors as well,
* resulting in a list of trees of successors, with the direct successors at the root(s).
*
* @param versionId
* @param transitive
* @return A list of successors.
*/
protected List<Version> getSuccessors(String versionId, boolean transitive) {
LinkedList<Version> result = new LinkedList<>();
outer:
for (VersionHistoryItem i : getHistoryItems().values()) {
if (i.parents != null)
for (String p : i.parents) {
if (versionId.equals(p)) {
Version successor = getVersion(i.id);
result.add(successor);
if (transitive) {
successor.setSuccessors(getSuccessors(i.id, transitive));
}
continue outer;
}
}
}
return result;
}
}
/*
* ** header v3.0
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2018 Research Group Biomedical Physics,
* Max-Planck-Institute for Dynamics and Self-Organization Göttingen
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ** end header
*/
package org.caosdb.server.database.proto;
import java.io.Serializable;
public class ProtoTransactionLogMessage implements Serializable {
public ProtoTransactionLogMessage(
final String transaction,
final String realm,
final String username,
final long seconds,
final int nanos) {
this.transaction = transaction;
this.realm = realm;
this.username = username;
this.seconds = seconds;
this.nanos = nanos;
}
public ProtoTransactionLogMessage() {}
private static final long serialVersionUID = -5856887517281480754L;
public String transaction = null;
public String realm;
public String username = null;
public Long seconds = null;
public Integer nanos = null;
}
...@@ -38,9 +38,7 @@ public class SparseEntity extends VerySparseEntity { ...@@ -38,9 +38,7 @@ public class SparseEntity extends VerySparseEntity {
public String filePath = null; public String filePath = null;
public Long fileSize = null; public Long fileSize = null;
public Long fileChecked = null; public Long fileChecked = null;
public String version = null; public String versionId = null;
public Long versionSeconds = null;
public Integer versionNanos = null;
@Override @Override
public String toString() { public String toString() {
...@@ -54,9 +52,7 @@ public class SparseEntity extends VerySparseEntity { ...@@ -54,9 +52,7 @@ public class SparseEntity extends VerySparseEntity {
.append(this.fileHash) .append(this.fileHash)
.append(this.filePath) .append(this.filePath)
.append(this.fileSize) .append(this.fileSize)
.append(this.version) .append(this.versionId)
.append(this.versionSeconds)
.append(this.versionNanos)
.toString(); .toString();
} }
} }
package org.caosdb.server.database.proto; package org.caosdb.server.database.proto;
import java.io.Serializable; import java.io.Serializable;
import java.util.LinkedList; import java.util.List;
/**
* This class is a flat, data-only representation of a single item of version information. This
* class is an intermediate representation which abstracts away the data base results and comes in a
* form which is easily cacheable.
*
* @author Timm Fitschen (t.fitschen@indiscale.com)
*/
public class VersionHistoryItem implements Serializable { public class VersionHistoryItem implements Serializable {
private static final long serialVersionUID = 6319362462701459355L; private static final long serialVersionUID = 428030617967255942L;
public String id = null; public String id = null;
public LinkedList<String> parents = null; public List<String> parents = null;
public Long seconds = null; public Long seconds = null;
public Integer nanos = null; public Integer nanos = null;
public String username = null;
public String realm = null;
@Override
public String toString() {
return id;
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment