blob: 353478f46cc5525fc4774bd6f63cf5d832fdd4e7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2007 Boeing.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Boeing - initial API and implementation
*******************************************************************************/
package org.eclipse.osee.framework.skynet.core.transaction;
import static org.eclipse.osee.framework.db.connection.core.schema.SkynetDatabase.TRANSACTION_DETAIL_TABLE;
import static org.eclipse.osee.framework.db.connection.core.schema.SkynetDatabase.TXD_COMMENT;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.osee.framework.core.client.ClientSessionManager;
import org.eclipse.osee.framework.core.data.OseeSql;
import org.eclipse.osee.framework.core.enums.TransactionDetailsType;
import org.eclipse.osee.framework.db.connection.ConnectionHandler;
import org.eclipse.osee.framework.db.connection.ConnectionHandlerStatement;
import org.eclipse.osee.framework.db.connection.core.SequenceManager;
import org.eclipse.osee.framework.db.connection.exception.BranchDoesNotExist;
import org.eclipse.osee.framework.db.connection.exception.OseeCoreException;
import org.eclipse.osee.framework.db.connection.exception.OseeDataStoreException;
import org.eclipse.osee.framework.db.connection.exception.TransactionDoesNotExist;
import org.eclipse.osee.framework.jdk.core.type.Pair;
import org.eclipse.osee.framework.jdk.core.util.time.GlobalTime;
import org.eclipse.osee.framework.skynet.core.User;
import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
import org.eclipse.osee.framework.skynet.core.artifact.Branch;
import org.eclipse.osee.framework.skynet.core.artifact.BranchManager;
/**
* Manages a cache of <code>TransactionId</code>.
*
* @author Jeff C. Phillips
*/
public final class TransactionIdManager {
private static final String INSERT_INTO_TRANSACTION_DETAIL =
"INSERT INTO osee_tx_details (transaction_id, osee_comment, time, author, branch_id, tx_type) VALUES (?, ?, ?, ?, ?, ?)";
private static final String SELECT_TRANSACTIONS =
"SELECT " + TRANSACTION_DETAIL_TABLE.columns("transaction_id", "commit_art_id", TXD_COMMENT, "time", "author",
"branch_id", "tx_type") + " FROM " + TRANSACTION_DETAIL_TABLE + " WHERE " + TRANSACTION_DETAIL_TABLE.column("branch_id") + " = ?" + " ORDER BY transaction_id DESC";
private static final String SELECT_COMMIT_TRANSACTIONS =
"SELECT transaction_id from osee_tx_details where commit_art_id = ?";
private final Map<Integer, TransactionId> transactionIdCache = new HashMap<Integer, TransactionId>();
private static final TransactionIdManager instance = new TransactionIdManager();
private static final HashMap<Artifact, List<TransactionId>> commitArtifactMap =
new HashMap<Artifact, List<TransactionId>>();
private TransactionIdManager() {
}
public static List<TransactionId> getTransactionsForBranch(Branch branch) throws OseeCoreException {
ArrayList<TransactionId> transactions = new ArrayList<TransactionId>();
ConnectionHandlerStatement chStmt = new ConnectionHandlerStatement();
try {
chStmt.runPreparedQuery(SELECT_TRANSACTIONS, branch.getBranchId());
while (chStmt.next()) {
transactions.add(getTransactionId(chStmt.getInt("transaction_id"), chStmt));
}
} finally {
chStmt.close();
}
return transactions;
}
public synchronized static Collection<TransactionId> getCommittedArtifactTransactionIds(Artifact artifact) throws OseeCoreException {
List<TransactionId> transactionIds = commitArtifactMap.get(artifact);
if (transactionIds == null) {
transactionIds = new ArrayList<TransactionId>(5);
ConnectionHandlerStatement chStmt = new ConnectionHandlerStatement();
try {
chStmt.runPreparedQuery(SELECT_COMMIT_TRANSACTIONS, artifact.getArtId());
while (chStmt.next()) {
transactionIds.add(getTransactionId(chStmt.getInt("transaction_id")));
}
commitArtifactMap.put(artifact, transactionIds);
} finally {
chStmt.close();
}
}
return transactionIds;
}
public synchronized static void cacheCommittedArtifactTransaction(Artifact artifact, TransactionId transactionId) throws OseeCoreException {
Collection<TransactionId> transactionIds = getCommittedArtifactTransactionIds(artifact);
if (!transactionIds.contains(transactionId)) {
transactionIds.add(transactionId);
}
}
/**
* @param branch
* @return the largest (most recent) transaction on the given branch
* @throws OseeCoreException
*/
public static TransactionId getlatestTransactionForBranch(Branch branch) throws OseeCoreException {
int transactionNumber =
ConnectionHandler.runPreparedQueryFetchInt(-1,
ClientSessionManager.getSQL(OseeSql.Transaction.SELECT_MAX_AS_LARGEST_TX), branch.getBranchId());
if (transactionNumber == -1) {
throw new TransactionDoesNotExist("No transactions where found in the database for branch: " + branch);
}
return getTransactionId(transactionNumber);
}
public static synchronized TransactionId createNextTransactionId(Branch branch, User userToBlame, String comment) throws OseeDataStoreException {
Integer transactionNumber = SequenceManager.getNextTransactionId();
if (comment == null) {
comment = "";
}
int authorArtId = userToBlame.getArtId();
Date transactionTime = GlobalTime.GreenwichMeanTimestamp();
ConnectionHandler.runPreparedUpdate(INSERT_INTO_TRANSACTION_DETAIL, transactionNumber, comment, transactionTime,
authorArtId, branch.getBranchId(), TransactionDetailsType.NonBaselined.getId());
TransactionId transactionId =
new TransactionId(transactionNumber, branch, comment, transactionTime, authorArtId, -1,
TransactionDetailsType.NonBaselined);
instance.transactionIdCache.put(transactionNumber, transactionId);
return transactionId;
}
public static Pair<TransactionId, TransactionId> getStartEndPoint(Branch branch) throws OseeCoreException {
ConnectionHandlerStatement chStmt = new ConnectionHandlerStatement();
try {
chStmt.runPreparedQuery(ClientSessionManager.getSQL(OseeSql.Transaction.SELECT_MAX_AND_MIN_TX),
branch.getBranchId());
// the max, min query will return exactly 1 row by definition (even if there is no max or min)
chStmt.next();
int minId = chStmt.getInt("min_id");
int maxId = chStmt.getInt("max_id");
if (chStmt.wasNull()) {
throw new TransactionDoesNotExist("Branch " + branch + " has no transactions");
}
return new Pair<TransactionId, TransactionId>(getTransactionId(minId), getTransactionId(maxId));
} finally {
chStmt.close();
}
}
/**
* @param transactionId
* @return The prior transactionId, or null if there is no prior.
* @throws BranchDoesNotExist
* @throws TransactionDoesNotExist
* @throws OseeDataStoreException
*/
public static TransactionId getPriorTransaction(TransactionId transactionId) throws OseeCoreException {
TransactionId priorTransactionId = null;
ConnectionHandlerStatement chStmt = new ConnectionHandlerStatement();
try {
chStmt.runPreparedQuery(
"SELECT max(transaction_id) as prior_id FROM " + TRANSACTION_DETAIL_TABLE + " WHERE " + TRANSACTION_DETAIL_TABLE.column("branch_id") + " = ? " + " AND " + TRANSACTION_DETAIL_TABLE.column("transaction_id") + " < ?",
transactionId.getBranch().getBranchId(), transactionId.getTransactionNumber());
if (chStmt.next()) {
int priorId = chStmt.getInt("prior_id");
if (chStmt.wasNull()) {
throw new TransactionDoesNotExist("the prior transation id was null");
}
priorTransactionId = getTransactionId(priorId);
}
} finally {
chStmt.close();
}
return priorTransactionId;
}
public static TransactionId getTransactionId(int transactionNumber) throws OseeCoreException {
return getTransactionId(transactionNumber, null);
}
public static TransactionId getTransactionId(ConnectionHandlerStatement chStmt) throws OseeCoreException {
return getTransactionId(chStmt.getInt("transaction_id"), chStmt);
}
private synchronized static TransactionId getTransactionId(int transactionNumber, ConnectionHandlerStatement chStmt) throws OseeCoreException {
TransactionId transactionId = instance.transactionIdCache.get(transactionNumber);
boolean useLocalConnection = chStmt == null;
if (transactionId == null) {
try {
if (useLocalConnection) {
chStmt = new ConnectionHandlerStatement();
chStmt.runPreparedQuery(ClientSessionManager.getSQL(OseeSql.Transaction.SELECT_ALL_TRANSACTIONS),
transactionNumber);
if (!chStmt.next()) {
throw new TransactionDoesNotExist(
"The transaction id " + transactionNumber + " does not exist in the databse.");
}
}
Branch branch = BranchManager.getBranch(chStmt.getInt("branch_id"));
TransactionDetailsType txType = TransactionDetailsType.toEnum(chStmt.getInt("tx_type"));
transactionId =
new TransactionId(transactionNumber, branch, chStmt.getString("osee_comment"),
chStmt.getTimestamp("time"), chStmt.getInt("author"), chStmt.getInt("commit_art_id"), txType);
instance.transactionIdCache.put(transactionNumber, transactionId);
} finally {
if (useLocalConnection) {
chStmt.close();
}
}
}
return transactionId;
}
}