blob: 11bd89e4ed18d29d96f73ff632221270fcf4ea2c [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* one or more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
#include "TombstoneList.hpp"
#include "TombstoneExpiryHandler.hpp"
#include "MapSegment.hpp"
#include <unordered_map>
using namespace gemfire;
#define SIZEOF_PTR (sizeof(void*))
#define SIZEOF_SHAREDPTR (SIZEOF_PTR + 4)
// 3 variables in expiry handler, two variables for ace_reactor expiry, one pointer to expiry handle
#define SIZEOF_EXPIRYHANDLER ((SIZEOF_PTR * 5) + 4)
#define SIZEOF_TOMBSTONEENTRY (SIZEOF_PTR + 8 + 8)
// one shared ptr for map entry, one sharedPtr for tombstone entry, one sharedptr for key, one shared ptr for tombstone value,
// one ptr for tombstone list, one ptr for mapsegment, one tombstone entry
#define SIZEOF_TOMBSTONELISTENTRY (SIZEOF_SHAREDPTR *4 + SIZEOF_PTR * 2 + SIZEOF_TOMBSTONEENTRY)
#define SIZEOF_TOMBSTONEOVERHEAD (SIZEOF_EXPIRYHANDLER + SIZEOF_TOMBSTONELISTENTRY)
long TombstoneList::getExpiryTask(TombstoneExpiryHandler** handler)
{
// This function is not guarded as all functions of this class are called from MapSegment
//read TombstoneTImeout from systemProperties.
uint32_t duration = DistributedSystem::getSystemProperties()->tombstoneTimeoutInMSec()/1000;
ACE_Time_Value currTime( ACE_OS::gettimeofday( ) );
TombstoneEntryPtr tombstoneEntryPtr = TombstoneEntryPtr(new TombstoneEntry(NULL, (int64_t)currTime.get_msec()));
*handler = new TombstoneExpiryHandler(tombstoneEntryPtr, this, duration);
tombstoneEntryPtr->setHandler(*handler);
long id = CacheImpl::expiryTaskManager->scheduleExpiryTask(
*handler, duration, 0);
return id;
}
void TombstoneList::add(RegionInternal* rptr, MapEntryImpl* entry, TombstoneExpiryHandler* handler, long taskid)
{
// This function is not guarded as all functions of this class are called from MapSegment
//read TombstoneTImeout from systemProperties.
//uint32_t duration = DistributedSystem::getSystemProperties()->tombstoneTimeoutInMSec()/1000;
ACE_Time_Value currTime( ACE_OS::gettimeofday( ) );
TombstoneEntryPtr tombstoneEntryPtr = TombstoneEntryPtr(new TombstoneEntry(entry, (int64_t)currTime.get_msec()));
//TombstoneExpiryHandler* handler = new TombstoneExpiryHandler(tombstoneEntryPtr, this, duration);
handler->setTombstoneEntry(tombstoneEntryPtr);
tombstoneEntryPtr->setHandler(handler);
//long id = CacheImpl::expiryTaskManager->scheduleExpiryTask(
// handler, duration, 0);
CacheableKeyPtr key;
entry->getKeyI(key);
/*if (Log::finestEnabled()) {
LOGFINEST("tombstone expiry for key [%s], task id = %d, "
"duration = %d",
Utils::getCacheableKeyString(key)->asChar(), id, duration);
}*/
tombstoneEntryPtr->setExpiryTaskId(taskid);
if (!m_tombstoneMap.insert(key, tombstoneEntryPtr))
m_tombstoneMap[key] = tombstoneEntryPtr;
rptr->getCacheImpl()->m_cacheStats->incTombstoneCount();
int32_t tombstonesize = key->objectSize() + SIZEOF_TOMBSTONEOVERHEAD;
rptr->getCacheImpl()->m_cacheStats->incTombstoneSize(tombstonesize);
}
// Reaps the tombstones which have been gc'ed on server.
// A map that has identifier for ClientProxyMembershipID as key
// and server version of the tombstone with highest version as the
// value is passed as paramter
void TombstoneList::reapTombstones(std::map<uint16_t, int64_t>& gcVersions)
{
// This function is not guarded as all functions of this class are called from MapSegment
std::unordered_set<CacheableKeyPtr> tobeDeleted;
for(HashMapT<CacheableKeyPtr, TombstoneEntryPtr>::Iterator queIter=m_tombstoneMap.begin();
queIter!=m_tombstoneMap.end(); ++queIter)
{
std::map<uint16_t, int64_t>::iterator mapIter =
gcVersions.find(queIter.second()->getEntry()->getVersionStamp().getMemberId());
if (mapIter == gcVersions.end ()) {
continue;
}
int64_t version = (*mapIter).second;
if (version >= queIter.second()->getEntry()->getVersionStamp().getRegionVersion())
{
tobeDeleted.insert(queIter.first());
}
}
for (std::unordered_set<CacheableKeyPtr>::iterator itr = tobeDeleted.begin(); itr != tobeDeleted.end(); itr++)
unguardedRemoveEntryFromMapSegment(*itr);
}
// Reaps the tombstones whose keys are specified in the hash set .
void TombstoneList::reapTombstones(CacheableHashSetPtr removedKeys)
{
// This function is not guarded as all functions of this class are called from MapSegment
for(HashSetT<CacheableKeyPtr>::Iterator queIter = removedKeys->begin(); queIter!=removedKeys->end(); ++queIter)
{
unguardedRemoveEntryFromMapSegment(*queIter);
}
}
// Call this when the lock of MapSegment has not been taken
void TombstoneList::removeEntryFromMapSegment(CacheableKeyPtr key)
{
m_mapSegment->removeActualEntry(key, false);
}
// Call this when the lock of MapSegment has already been taken
void TombstoneList::unguardedRemoveEntryFromMapSegment(CacheableKeyPtr key)
{
m_mapSegment->unguardedRemoveActualEntry(key);
}
void TombstoneList::eraseEntryFromTombstoneList(CacheableKeyPtr key, RegionInternal* region, bool cancelTask)
{
// This function is not guarded as all functions of this class are called from MapSegment
bool exists = (key != NULLPTR) ? m_tombstoneMap.contains(key) : false;
if (cancelTask && exists) {
CacheImpl::expiryTaskManager->cancelTask((long)(m_tombstoneMap[key]->getExpiryTaskId()));
delete m_tombstoneMap[key]->getHandler();
}
if (exists) {
region->getCacheImpl()->m_cacheStats->decTombstoneCount();
int32_t tombstonesize = key->objectSize() + SIZEOF_TOMBSTONEOVERHEAD;
region->getCacheImpl()->m_cacheStats->decTombstoneSize(tombstonesize);
m_tombstoneMap.erase(key);
}
}
long TombstoneList::eraseEntryFromTombstoneListWithoutCancelTask(CacheableKeyPtr key, RegionInternal* region, TombstoneExpiryHandler*& handler)
{
// This function is not guarded as all functions of this class are called from MapSegment
bool exists = (key != NULLPTR) ? m_tombstoneMap.contains(key) : false;
long taskid = -1;
if (exists) {
taskid = (long)(m_tombstoneMap[key]->getExpiryTaskId());
handler = m_tombstoneMap[key]->getHandler();
region->getCacheImpl()->m_cacheStats->decTombstoneCount();
int32_t tombstonesize = key->objectSize() + SIZEOF_TOMBSTONEOVERHEAD;
region->getCacheImpl()->m_cacheStats->decTombstoneSize(tombstonesize);
m_tombstoneMap.erase(key);
}
return taskid;
}
bool TombstoneList::getEntryFromTombstoneList(CacheableKeyPtr key)
{
// This function is not guarded as all functions of this class are called from MapSegment
return m_tombstoneMap.contains(key);
}
void TombstoneList::cleanUp()
{
// This function is not guarded as all functions of this class are called from MapSegment
for(HashMapT<CacheableKeyPtr, TombstoneEntryPtr>::Iterator queIter=m_tombstoneMap.begin();
queIter!=m_tombstoneMap.end(); ++queIter)
{
CacheImpl::expiryTaskManager->cancelTask((long)queIter.second()->getExpiryTaskId());
delete queIter.second()->getHandler();
}
}