blob: d272990f3414dbb8c42590a3963aac9474c3f669 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "TombstoneList.hpp"
#include <unordered_set>
#include <geode/SystemProperties.hpp>
#include "CacheImpl.hpp"
#include "MapSegment.hpp"
#include "TombstoneEntry.hpp"
#include "TombstoneExpiryTask.hpp"
namespace apache {
namespace geode {
namespace client {
// TODO. Review this overhead is OK
#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)
ExpiryTask::id_t TombstoneList::add(
const std::shared_ptr<MapEntryImpl>& entry) {
// This function is not guarded as all functions of this class are called from
// MapSegment read TombstoneTImeout from systemProperties.
auto tombstone = std::make_shared<TombstoneEntry>(entry);
std::shared_ptr<CacheableKey> key;
entry->getKeyI(key);
auto duration =
cache_.getDistributedSystem().getSystemProperties().tombstoneTimeout();
auto& manager = cache_.getExpiryTaskManager();
auto task =
std::make_shared<TombstoneExpiryTask>(manager, segment_, tombstone);
auto task_id = manager.schedule(std::move(task), duration);
tombstone->task_id(task_id);
tombstones_[key] = tombstone;
auto& perf_stats = cache_.getCachePerfStats();
perf_stats.incTombstoneCount();
perf_stats.incTombstoneSize(key->objectSize() + SIZEOF_TOMBSTONEOVERHEAD);
return task_id;
}
// 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::reap_tombstones(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<std::shared_ptr<CacheableKey>,
dereference_hash<std::shared_ptr<CacheableKey>>,
dereference_equal_to<std::shared_ptr<CacheableKey>>>
tobeDeleted;
for (const auto& queIter : tombstones_) {
auto const& mapIter = gcVersions.find(
queIter.second->entry()->getVersionStamp().getMemberId());
if (mapIter == gcVersions.end()) {
continue;
}
auto const& version = (*mapIter).second;
if (version >=
queIter.second->entry()->getVersionStamp().getRegionVersion()) {
tobeDeleted.insert(queIter.first);
}
}
for (const auto& key : tobeDeleted) {
segment_.remove_entry(key);
}
}
// Reaps the tombstones whose keys are specified in the hash set .
void TombstoneList::reap_tombstones(
const std::shared_ptr<CacheableHashSet>& keys) {
// This function is not guarded as all functions of this class are called from
// MapSegment
for (const auto& key : *keys) {
segment_.remove_entry(key);
}
}
bool TombstoneList::exists(const std::shared_ptr<CacheableKey>& key) const {
return key != nullptr && tombstones_.find(key) != tombstones_.end();
}
bool TombstoneList::erase(const std::shared_ptr<CacheableKey>& key,
bool cancel_task) {
// This function is not guarded as all functions of this class are called from
// MapSegment
auto&& iter = tombstones_.find(key);
if (iter == tombstones_.end()) {
return false;
}
iter->second->invalidate();
if (cancel_task) {
cache_.getExpiryTaskManager().cancel(iter->second->task_id());
}
auto& perf_stats = cache_.getCachePerfStats();
perf_stats.decTombstoneCount();
perf_stats.decTombstoneSize(key->objectSize() + SIZEOF_TOMBSTONEOVERHEAD);
tombstones_.erase(iter);
return true;
}
void TombstoneList::cleanup() {
// This function is not guarded as all functions of this class are called from
// MapSegment
auto& manager = cache_.getExpiryTaskManager();
for (const auto& iter : tombstones_) {
manager.cancel(iter.second->task_id());
}
}
} // namespace client
} // namespace geode
} // namespace apache