/** * Goes direct to the shared cache in the absence of a transaction. * * <p>Where a transaction is present, a cache of removed items is lazily added to the thread and * the <tt>Object</tt> put onto that. */ public void remove(K keyIn) { final Serializable key = getTenantAwareCacheKey(keyIn); // are we in a transaction? if (AlfrescoTransactionSupport.getTransactionId() == null) // not in transaction { // no transaction sharedCache.remove(key); // done if (isDebugEnabled) { logger.debug( "No transaction - removing item from shared cache: \n" + " cache: " + this + "\n" + " key: " + key); } } else // transaction present { TransactionData txnData = getTransactionData(); // Ensure that the cache isn't being modified if (txnData.isClosed) { if (isDebugEnabled) { logger.debug("In post-commit remove: \n" + " cache: " + this + "\n" + " key: " + key); } } else if (isValueLocked(txnData, key)) { // The key has been locked if (isDebugEnabled) { logger.debug( "Ignoring remove after detecting locked key: \n" + " cache: " + this + "\n" + " key: " + key); } } else { // is the shared cache going to be cleared? if (txnData.isClearOn) { // don't store removals if we're just going to clear it all out later } else { // are we in an overflow condition? if (txnData.removedItemsCache.size() >= maxCacheSize) { // overflow about to occur or has occured - we can only guarantee non-stale // data by clearing the shared cache after the transaction. Also, the // shared cache needs to be ignored for the rest of the transaction. txnData.isClearOn = true; if (!txnData.haveIssuedFullWarning) { if (logger.isInfoEnabled()) { Exception e = new Exception("Stack: "); logger.info( "Transactional removal cache '" + name + "' is full (" + maxCacheSize + ").", e); } else if (logger.isWarnEnabled()) { logger.warn( "Transactional removal cache '" + name + "' is full (" + maxCacheSize + ")."); } txnData.haveIssuedFullWarning = true; } } else { // Create a bucket to remove the value from the shared cache txnData.removedItemsCache.add(key); } } // remove the item from the udpated cache, if present txnData.updatedItemsCache.remove(key); // done if (isDebugEnabled) { logger.debug( "In transaction - adding item direct to transactional removed cache: \n" + " cache: " + this + "\n" + " key: " + key); } } } }
/** * Goes direct to the shared cache in the absence of a transaction. * * <p>Where a transaction is present, a cache of updated items is lazily added to the thread and * the <tt>Object</tt> put onto that. */ public void put(K keyIn, V value) { final Serializable key = getTenantAwareCacheKey(keyIn); // are we in a transaction? if (AlfrescoTransactionSupport.getTransactionId() == null) // not in transaction { // no transaction TransactionalCache.putSharedCacheValue(sharedCache, key, value, null); // done if (isDebugEnabled) { logger.debug( "No transaction - adding item direct to shared cache: \n" + " cache: " + this + "\n" + " key: " + key + "\n" + " value: " + value); } } else // transaction present { TransactionData txnData = getTransactionData(); // Ensure that the cache isn't being modified if (txnData.isClosed) { if (isDebugEnabled) { logger.debug( "In post-commit add: \n" + " cache: " + this + "\n" + " key: " + key + "\n" + " value: " + value); } } else if (isValueLocked(txnData, key)) { // The key has been locked if (isDebugEnabled) { logger.debug( "Ignoring put after detecting locked key: \n" + " cache: " + this + "\n" + " key: " + key + "\n" + " value: " + value); } } else { // we have an active transaction - add the item into the updated cache for this transaction // are we in an overflow condition? if (txnData.updatedItemsCache.hasHitSize()) { // overflow about to occur or has occured - we can only guarantee non-stale // data by clearing the shared cache after the transaction. Also, the // shared cache needs to be ignored for the rest of the transaction. txnData.isClearOn = true; if (!txnData.haveIssuedFullWarning) { if (logger.isInfoEnabled()) { Exception e = new Exception("Stack: "); logger.info( "Transactional update cache '" + name + "' is full (" + maxCacheSize + ").", e); } else if (logger.isWarnEnabled()) { logger.warn( "Transactional update cache '" + name + "' is full (" + maxCacheSize + ")."); } txnData.haveIssuedFullWarning = true; } } ValueHolder<V> existingValueHolder = txnData.noSharedCacheRead ? null : sharedCache.get(key); CacheBucket<V> bucket = null; if (existingValueHolder == null) { // ALF-5134: Performance of Alfresco cluster less than performance of single node // The 'null' marker that used to be inserted also triggered an update in the afterCommit // phase; the update triggered cache invalidation in the cluster. Now, the null cannot // be verified to be the same null - there is no null equivalence // // The value didn't exist before bucket = new NewCacheBucket<V>(value); } else { // Record the existing value as is bucket = new UpdateCacheBucket<V>(existingValueHolder, value); } txnData.updatedItemsCache.put(key, bucket); // remove the item from the removed cache, if present txnData.removedItemsCache.remove(key); // done if (isDebugEnabled) { logger.debug( "In transaction - adding item direct to transactional update cache: \n" + " cache: " + this + "\n" + " key: " + key + "\n" + " value: " + value); } } } }