[Major] Implemented opt-in versioning

- fixing remaining PostgreSQL DAO tests
This commit is contained in:
Robert von Burg 2016-08-08 09:30:56 +02:00
parent 8c4c8e539e
commit 07daf34f86
9 changed files with 73 additions and 46 deletions

View File

@ -254,6 +254,7 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
Version.setInitialVersionFor(element, tx.getCertificate().getUsername()); Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
getDao(tx).save(element); getDao(tx).save(element);
getDao(tx).flush();
} }
@Override @Override
@ -266,6 +267,7 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
} }
getDao(tx).saveAll(elements); getDao(tx).saveAll(elements);
getDao(tx).flush();
} }
@Override @Override
@ -276,6 +278,7 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
Version.setInitialVersionFor(element, tx.getCertificate().getUsername()); Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
getDao(tx).update(element); getDao(tx).update(element);
getDao(tx).flush();
} }
@Override @Override
@ -288,6 +291,7 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
} }
getDao(tx).updateAll(elements); getDao(tx).updateAll(elements);
getDao(tx).flush();
} }
@Override @Override
@ -299,6 +303,7 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
Version.setInitialVersionFor(element, tx.getCertificate().getUsername()); Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
getDao(tx).remove(element); getDao(tx).remove(element);
} }
getDao(tx).flush();
} }
@Override @Override
@ -315,16 +320,21 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
} else { } else {
getDao(tx).removeAll(elements); getDao(tx).removeAll(elements);
} }
getDao(tx).flush();
} }
@Override @Override
public long removeAll(StrolchTransaction tx) { public long removeAll(StrolchTransaction tx) {
return getDao(tx).removeAll(); long removed = getDao(tx).removeAll();
getDao(tx).flush();
return removed;
} }
@Override @Override
public long removeAllBy(StrolchTransaction tx, String type) { public long removeAllBy(StrolchTransaction tx, String type) {
return getDao(tx).removeAllBy(type); long removed = getDao(tx).removeAllBy(type);
getDao(tx).flush();
return removed;
} }
@Override @Override
@ -349,6 +359,7 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
// save the new version // save the new version
getDao(tx).update(clone); getDao(tx).update(clone);
getDao(tx).flush();
// and return new version // and return new version
return clone; return clone;
@ -369,6 +380,7 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
} }
getDao(tx).removeVersion(current); getDao(tx).removeVersion(current);
getDao(tx).flush();
} }
protected abstract void assertIsRefParam(Parameter<?> refP); protected abstract void assertIsRefParam(Parameter<?> refP);

View File

@ -119,6 +119,10 @@ public abstract class AbstractTransaction implements StrolchTransaction {
this.txResult.setState(TransactionState.OPEN); this.txResult.setState(TransactionState.OPEN);
} }
public TransactionResult getTxResult() {
return this.txResult;
}
@Override @Override
public TransactionState getState() { public TransactionState getState() {
return this.txResult.getState(); return this.txResult.getState();
@ -534,7 +538,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
try { try {
validateCommands(); validateCommands();
doCommands(); doCommands();
writeChanges(this.txResult); writeChanges();
} catch (Exception e) { } catch (Exception e) {
this.closeStrategy = TransactionCloseStrategy.ROLLBACK; this.closeStrategy = TransactionCloseStrategy.ROLLBACK;
@ -553,7 +557,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
validateCommands(); validateCommands();
doCommands(); doCommands();
writeChanges(this.txResult); writeChanges();
long auditTrailDuration = writeAuditTrail(); long auditTrailDuration = writeAuditTrail();
long updateObserversDuration = updateObservers(); long updateObserversDuration = updateObservers();
@ -573,7 +577,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
} catch (Exception ex) { } catch (Exception ex) {
logger.error("Failed to commit transaction and then undo commands due to " + ex.getMessage(), ex); logger.error("Failed to commit transaction and then undo commands due to " + ex.getMessage(), ex);
try { try {
rollback(this.txResult); rollback();
handleRollback(start); handleRollback(start);
} catch (Exception exc) { } catch (Exception exc) {
logger.error("Failed to roll back after failing to undo commands: " + exc.getMessage(), exc); //$NON-NLS-1$ logger.error("Failed to roll back after failing to undo commands: " + exc.getMessage(), exc); //$NON-NLS-1$
@ -582,7 +586,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
} }
try { try {
rollback(this.txResult); rollback();
handleRollback(start); handleRollback(start);
} catch (Exception ex) { } catch (Exception ex) {
logger.error("Failed to commit transaction and then rollback due to " + ex.getMessage(), ex); logger.error("Failed to commit transaction and then rollback due to " + ex.getMessage(), ex);
@ -607,7 +611,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
try { try {
this.txResult.setState(TransactionState.ROLLING_BACK); this.txResult.setState(TransactionState.ROLLING_BACK);
undoCommands(); undoCommands();
rollback(this.txResult); rollback();
handleRollback(start); handleRollback(start);
this.txResult.setState(TransactionState.ROLLED_BACK); this.txResult.setState(TransactionState.ROLLED_BACK);
} catch (Exception e) { } catch (Exception e) {
@ -635,7 +639,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
long auditTrailDuration = writeAuditTrail(); long auditTrailDuration = writeAuditTrail();
// rollback and release any resources // rollback and release any resources
rollback(this.txResult); rollback();
handleDoNothing(start, auditTrailDuration); handleDoNothing(start, auditTrailDuration);
this.txResult.setState(TransactionState.CLOSED); this.txResult.setState(TransactionState.CLOSED);
@ -647,9 +651,9 @@ public abstract class AbstractTransaction implements StrolchTransaction {
} }
} }
protected abstract void writeChanges(TransactionResult txResult) throws Exception; protected abstract void writeChanges() throws Exception;
protected abstract void rollback(TransactionResult txResult) throws Exception; protected abstract void rollback() throws Exception;
protected abstract void commit() throws Exception; protected abstract void commit() throws Exception;

View File

@ -292,4 +292,8 @@ public interface StrolchDao<T extends StrolchRootElement> {
*/ */
public void removeVersion(T element) throws StrolchPersistenceException; public void removeVersion(T element) throws StrolchPersistenceException;
/**
* Causes the DAO to flush any actions which have not yet been sent to the underlying persistence layer
*/
public void flush();
} }

View File

@ -312,4 +312,9 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
byType.remove(element.getId()); byType.remove(element.getId());
} }
} }
@Override
public void flush() {
// nothing to do
}
} }

View File

@ -18,7 +18,6 @@ package li.strolch.persistence.inmemory;
import li.strolch.agent.api.StrolchRealm; import li.strolch.agent.api.StrolchRealm;
import li.strolch.persistence.api.AbstractTransaction; import li.strolch.persistence.api.AbstractTransaction;
import li.strolch.persistence.api.PersistenceHandler; import li.strolch.persistence.api.PersistenceHandler;
import li.strolch.persistence.api.TransactionResult;
import li.strolch.persistence.api.TransactionState; import li.strolch.persistence.api.TransactionState;
import li.strolch.privilege.model.Certificate; import li.strolch.privilege.model.Certificate;
import li.strolch.runtime.privilege.PrivilegeHandler; import li.strolch.runtime.privilege.PrivilegeHandler;
@ -34,13 +33,13 @@ public class InMemoryTransaction extends AbstractTransaction {
} }
@Override @Override
protected void writeChanges(TransactionResult txResult) throws Exception { protected void writeChanges() throws Exception {
txResult.setState(TransactionState.COMMITTED); getTxResult().setState(TransactionState.COMMITTED);
} }
@Override @Override
protected void rollback(TransactionResult txResult) throws Exception { protected void rollback() throws Exception {
txResult.setState(TransactionState.ROLLED_BACK); getTxResult().setState(TransactionState.ROLLED_BACK);
} }
@Override @Override

View File

@ -27,7 +27,6 @@ import li.strolch.persistence.api.AuditDao;
import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.OrderDao;
import li.strolch.persistence.api.PersistenceHandler; import li.strolch.persistence.api.PersistenceHandler;
import li.strolch.persistence.api.ResourceDao; import li.strolch.persistence.api.ResourceDao;
import li.strolch.persistence.api.TransactionResult;
import li.strolch.privilege.model.Certificate; import li.strolch.privilege.model.Certificate;
import li.strolch.runtime.privilege.PrivilegeHandler; import li.strolch.runtime.privilege.PrivilegeHandler;
@ -49,21 +48,21 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction {
} }
@Override @Override
protected void writeChanges(TransactionResult txResult) throws Exception { protected void writeChanges() throws Exception {
// first perform DAOs // first perform DAOs
if (this.orderDao != null) if (this.orderDao != null)
this.orderDao.commit(txResult); this.orderDao.flush();
if (this.resourceDao != null) if (this.resourceDao != null)
this.resourceDao.commit(txResult); this.resourceDao.flush();
if (this.activityDao != null) if (this.activityDao != null)
this.activityDao.commit(txResult); this.activityDao.flush();
// don't commit the connection, this is done in postCommit when we close the connection // don't commit the connection, this is done in postCommit when we close the connection
} }
@Override @Override
protected void rollback(TransactionResult txResult) throws Exception { protected void rollback() throws Exception {
if (this.connection != null) { if (this.connection != null) {
try { try {
this.connection.rollback(); this.connection.rollback();

View File

@ -28,7 +28,6 @@ import java.util.Set;
import li.strolch.model.StrolchRootElement; import li.strolch.model.StrolchRootElement;
import li.strolch.persistence.api.StrolchDao; import li.strolch.persistence.api.StrolchDao;
import li.strolch.persistence.api.StrolchPersistenceException; import li.strolch.persistence.api.StrolchPersistenceException;
import li.strolch.persistence.api.TransactionResult;
@SuppressWarnings("nls") @SuppressWarnings("nls")
public abstract class PostgresqlDao<T extends StrolchRootElement> implements StrolchDao<T> { public abstract class PostgresqlDao<T extends StrolchRootElement> implements StrolchDao<T> {
@ -471,21 +470,23 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
throw new StrolchPersistenceException(msg); throw new StrolchPersistenceException(msg);
} }
// if (!element.getVersion().isFirstVersion()) {
sql = "update " + getTableName() + " set latest = true where type = ? and id = ? and version = ?"; sql = "update " + getTableName() + " set latest = true where type = ? and id = ? and version = ?";
try (PreparedStatement updateStmt = tx().getConnection().prepareStatement(sql)) { try (PreparedStatement updateStmt = tx().getConnection().prepareStatement(sql)) {
int previousVersion = element.getVersion().getPreviousVersion(); int previousVersion = element.getVersion().getPreviousVersion();
updateStmt.setString(1, element.getType()); updateStmt.setString(1, element.getType());
updateStmt.setString(2, element.getId()); updateStmt.setString(2, element.getId());
updateStmt.setInt(3, previousVersion); updateStmt.setInt(3, previousVersion);
modCount = updateStmt.executeUpdate();
if (modCount != 1) {
String msg = "Expected to update 1 element with id {0} but SQL statement modified {1} elements! Verify that element {2} with version {3} exists!";
msg = MessageFormat.format(msg, element.getId(), modCount, element.getLocator(),
previousVersion);
throw new StrolchPersistenceException(msg);
}
modCount = updateStmt.executeUpdate();
if (modCount != 1) {
String msg = "Expected to update 1 element with id {0} but SQL statement modified {1} elements! Verify that element {2} with version {3} exists!";
msg = MessageFormat.format(msg, element.getId(), modCount, element.getLocator(), previousVersion);
throw new StrolchPersistenceException(msg);
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
@ -519,15 +520,12 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
} }
} }
void commit(TransactionResult txResult) { @Override
public void flush() {
// even though we support rollback we can clear the commands here even if we performed them because the DB transaction will be rolled back // even though we support rollback we can clear the commands here even if we performed them because the DB transaction will be rolled back
for (DaoCommand command : this.commands) { for (DaoCommand command : this.commands) {
command.doComand(txResult); command.doComand(tx().getTxResult());
} }
this.commands.clear(); this.commands.clear();
} }
void rollback() {
this.commands.clear();
}
} }

View File

@ -188,4 +188,10 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
// TODO Auto-generated method stub // TODO Auto-generated method stub
throw new UnsupportedOperationException("not yet implemented!"); throw new UnsupportedOperationException("not yet implemented!");
} }
@Override
public void flush() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("not yet implemented!");
}
} }

View File

@ -43,21 +43,21 @@ public class XmlStrolchTransaction extends AbstractTransaction {
} }
@Override @Override
protected void writeChanges(li.strolch.persistence.api.TransactionResult txResult) throws Exception { protected void writeChanges() throws Exception {
TransactionResult result = new TransactionResult(); TransactionResult result = new TransactionResult();
this.tx.setTransactionResult(result); this.tx.setTransactionResult(result);
this.tx.autoCloseableCommit(); this.tx.autoCloseableCommit();
Set<String> keys = result.getKeys(); Set<String> keys = result.getKeys();
for (String key : keys) { for (String key : keys) {
ModificationResult modificationResult = result.getModificationResult(key); ModificationResult modificationResult = result.getModificationResult(key);
txResult.incCreated(modificationResult.getCreated().size()); getTxResult().incCreated(modificationResult.getCreated().size());
txResult.incUpdated(modificationResult.getUpdated().size()); getTxResult().incUpdated(modificationResult.getUpdated().size());
txResult.incDeleted(modificationResult.getDeleted().size()); getTxResult().incDeleted(modificationResult.getDeleted().size());
} }
} }
@Override @Override
protected void rollback(li.strolch.persistence.api.TransactionResult txResult) throws Exception { protected void rollback() throws Exception {
this.tx.autoCloseableRollback(); this.tx.autoCloseableRollback();
} }