Merged V2.0 to HEAD

5523: Merged V1.4 to V2.0
      5494: db.schema.update=false disables ALL metadata queries
      5500: AR-1399 NTProtocolHander search handle leakage
      5522: AR-1412 IndexRemoteTransactionTracker startup
   5541: Merged V1.4 to V2.0
      5525: Pass-through authentication and domain mapping
         Resolved minor conflict on AlfrescoAuthenticator.java
      5526: Domain mapping support


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5546 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-04-25 02:44:53 +00:00
parent 08897ad76b
commit fb1dd4080b
24 changed files with 885 additions and 74 deletions

View File

@@ -277,6 +277,7 @@ public interface NodeDaoService
public Transaction getTxnById(long txnId);
public Transaction getLastTxn();
public Transaction getLastRemoteTxn();
public Transaction getLastTxnForStore(final StoreRef storeRef);
public int getTxnUpdateCount(final long txnId);
public int getTxnDeleteCount(final long txnId);

View File

@@ -1185,6 +1185,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
* Queries for transactions
*/
private static final String QUERY_GET_LAST_TXN_ID = "txn.GetLastTxnId";
private static final String QUERY_GET_LAST_REMOTE_TXN_ID = "txn.GetLastRemoteTxnId";
private static final String QUERY_GET_LAST_TXN_ID_FOR_STORE = "txn.GetLastTxnIdForStore";
private static final String QUERY_GET_TXN_UPDATE_COUNT_FOR_STORE = "txn.GetTxnUpdateCountForStore";
private static final String QUERY_GET_TXN_DELETE_COUNT_FOR_STORE = "txn.GetTxnDeleteCountForStore";
@@ -1222,6 +1223,30 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
return txn;
}
@SuppressWarnings("unchecked")
public Transaction getLastRemoteTxn()
{
HibernateCallback callback = new HibernateCallback()
{
public Object doInHibernate(Session session)
{
Query query = session.getNamedQuery(QUERY_GET_LAST_REMOTE_TXN_ID);
query.setString("serverIpAddress", ipAddress)
.setMaxResults(1)
.setReadOnly(true);
return query.uniqueResult();
}
};
Long txnId = (Long) getHibernateTemplate().execute(callback);
Transaction txn = null;
if (txnId != null)
{
txn = (Transaction) getSession().get(TransactionImpl.class, txnId);
}
// done
return txn;
}
@SuppressWarnings("unchecked")
public Transaction getLastTxnForStore(final StoreRef storeRef)
{

View File

@@ -242,37 +242,19 @@ public abstract class AbstractReindexComponent implements IndexRecovery
}
}
}
/**
* Gets the last indexed transaction working back from the provided index.
* This method can be used to hunt for a starting point for indexing of
* transactions not yet in the index.
*/
protected long getLastIndexedTxn(long lastTxnId)
protected enum InIndex
{
// get the last transaction
long lastFoundTxnId = lastTxnId + 10L;
boolean found = false;
while (!found && lastFoundTxnId >= 0)
{
// reduce the transaction ID
lastFoundTxnId = lastFoundTxnId - 10L;
// break out as soon as we find a transaction that is in the index
found = isTxnIdPresentInIndex(lastFoundTxnId);
if (found)
{
break;
}
}
// done
if (logger.isDebugEnabled())
{
logger.debug("Found last index txn before " + lastTxnId + ": " + lastFoundTxnId);
}
return lastFoundTxnId;
YES, NO, INDETERMINATE;
}
protected boolean isTxnIdPresentInIndex(long txnId)
/**
* Determines if a given transaction is definitely in the index or not.
*
* @param txnId a specific transaction
* @return Returns <tt>true</tt> if the transaction is definitely in the index
*/
protected InIndex isTxnIdPresentInIndex(long txnId)
{
if (logger.isDebugEnabled())
{
@@ -282,7 +264,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
Transaction txn = nodeDaoService.getTxnById(txnId);
if (txn == null)
{
return true;
return InIndex.YES;
}
// count the changes in the transaction
@@ -290,28 +272,38 @@ public abstract class AbstractReindexComponent implements IndexRecovery
int deleteCount = nodeDaoService.getTxnDeleteCount(txnId);
if (logger.isDebugEnabled())
{
logger.debug("Transaction has " + updateCount + " updates and " + deleteCount + " deletes: " + txnId);
logger.debug("Transaction " + txnId + " has " + updateCount + " updates and " + deleteCount + " deletes.");
}
// get the stores
boolean found = false;
List<StoreRef> storeRefs = nodeService.getStores();
for (StoreRef storeRef : storeRefs)
InIndex result = InIndex.NO;
if (updateCount == 0 && deleteCount == 0)
{
boolean inStore = isTxnIdPresentInIndex(storeRef, txn, updateCount, deleteCount);
if (inStore)
// If there are no update or deletes, then it is impossible to know if the transaction was removed
// from the index or was never there in the first place.
result = InIndex.INDETERMINATE;
}
else
{
// get the stores
List<StoreRef> storeRefs = nodeService.getStores();
for (StoreRef storeRef : storeRefs)
{
// found in a particular store
found = true;
break;
boolean inStore = isTxnIdPresentInIndex(storeRef, txn, updateCount, deleteCount);
if (inStore)
{
// found in a particular store
result = InIndex.YES;
break;
}
}
}
// done
if (logger.isDebugEnabled())
{
logger.debug("Transaction " + txnId + " was " + (found ? "found" : "not found") + " in indexes.");
logger.debug("Transaction " + txnId + " present in indexes: " + result);
}
return found;
return result;
}
/**
@@ -340,7 +332,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
{
if (logger.isDebugEnabled())
{
logger.debug("Index has results for txn (OK): " + txnId);
logger.debug("Index has results for txn " + txnId + " for store " + storeRef);
}
return true; // there were updates/creates and results for the txn were found
}
@@ -348,7 +340,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
{
if (logger.isDebugEnabled())
{
logger.debug("Index has no results for txn (Index out of date): " + txnId);
logger.debug("Transaction " + txnId + " not in index for store " + storeRef + ". Possibly out of date.");
}
return false;
}
@@ -450,7 +442,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
null,
null,
nodeRef);
indexer.deleteNode(assocRef);
indexer.deleteNode(assocRef);
}
else // node created
{

View File

@@ -132,8 +132,8 @@ public class FullIndexRecoveryComponent extends AbstractReindexComponent
return;
}
long txnId = txn.getId();
boolean txnInIndex = isTxnIdPresentInIndex(txnId);
if (!txnInIndex)
InIndex txnInIndex = isTxnIdPresentInIndex(txnId);
if (txnInIndex != InIndex.YES)
{
String msg = I18NUtil.getMessage(ERR_INDEX_OUT_OF_DATE);
logger.warn(msg);

View File

@@ -40,6 +40,7 @@ public class IndexRemoteTransactionTracker extends AbstractReindexComponent
private static Log logger = LogFactory.getLog(IndexRemoteTransactionTracker.class);
private boolean remoteOnly;
private boolean started;
private long currentTxnId;
public IndexRemoteTransactionTracker()
@@ -67,17 +68,11 @@ public class IndexRemoteTransactionTracker extends AbstractReindexComponent
@Override
protected void reindexImpl()
{
if (currentTxnId < 0)
if (!started)
{
// initialize the starting point
Transaction lastTxn = nodeDaoService.getLastTxn();
if (lastTxn == null)
{
// there is nothing to do
return;
}
long lastTxnId = lastTxn.getId();
currentTxnId = getLastIndexedTxn(lastTxnId);
// Initialize the starting poing
currentTxnId = getLastIndexedTxn();
started = true;
}
if (logger.isDebugEnabled())
@@ -109,6 +104,88 @@ public class IndexRemoteTransactionTracker extends AbstractReindexComponent
}
}
private static final long DECREMENT_COUNT = 10L;
/**
* Finds the last indexed transaction. It works backwards from the
* last index in increments, respecting the {@link #setRemoteOnly(boolean) remoteOnly}
* flag.
*
* @return Returns the last index transaction or -1 if there is none
*/
protected long getLastIndexedTxn()
{
// get the last transaction
Transaction txn = null;
if (remoteOnly)
{
txn = nodeDaoService.getLastRemoteTxn();
}
else
{
txn = nodeDaoService.getLastTxn();
}
if (txn == null)
{
// There is no last transaction to use
return -1L;
}
long currentTxnId = txn.getId();
while (currentTxnId >= 0L)
{
// Check if the current txn is in the index
InIndex txnInIndex = isTxnIdPresentInIndex(currentTxnId);
if (txnInIndex == InIndex.YES)
{
// We found somewhere to start
break;
}
// Get back in time
long lastCheckTxnId = currentTxnId;
currentTxnId -= DECREMENT_COUNT;
if (currentTxnId < 0L)
{
currentTxnId = -1L;
}
// We don't know if this number we have is a local or remote txn, so get the very next one
Transaction nextTxn = null;
if (remoteOnly)
{
List<Transaction> nextTxns = nodeDaoService.getNextRemoteTxns(currentTxnId, 1);
if (nextTxns.size() > 0)
{
nextTxn = nextTxns.get(0);
}
}
else
{
List<Transaction> nextTxns = nodeDaoService.getNextTxns(currentTxnId, 1);
if (nextTxns.size() > 0)
{
nextTxn = nextTxns.get(0);
}
}
if (nextTxn == null)
{
// There was nothing relevant after this, so keep going back in time
continue;
}
else if (nextTxn.getId() >= lastCheckTxnId)
{
// Decrementing by DECREMENT_COUNT was not enough
continue;
}
// Adjust the last one we looked at to reflect the correct txn id
currentTxnId = nextTxn.getId();
}
// We are close enough to the beginning, so just go for the first transaction
if (currentTxnId < 0L)
{
currentTxnId = -1L;
}
return currentTxnId;
}
private static final int MAX_TXN_COUNT = 1000;
private List<Transaction> getNextTransactions(long currentTxnId)
{