blob: 8ecef8869d5302009d2d832deb079c3a2edca8b0 [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.
*/
#pragma once
#ifndef GEODE_INTEGRATION_TEST_THINCLIENTHELPER_H_
#define GEODE_INTEGRATION_TEST_THINCLIENTHELPER_H_
#include <chrono>
#include <boost/process.hpp>
#include "testUtils.hpp"
#include "security/typedefs.hpp"
#include "security/CredentialGenerator.hpp"
#include "security/DummyCredentialGenerator.hpp"
#include "security/CredentialGenerator.cpp"
#include <string>
#ifndef ROOT_NAME
#define ROOT_NAME "ThinClientHelper"
#endif
#ifndef ROOT_SCOPE
#define ROOT_SCOPE DISTRIBUTED_ACK
#endif
#include "CacheHelper.hpp"
namespace { // NOLINT(google-build-namespaces)
using apache::geode::client::CacheableInt32;
using apache::geode::client::CacheHelper;
using apache::geode::client::CacheListener;
using apache::geode::client::DiskPolicyType;
using apache::geode::client::ExpirationAction;
using apache::geode::client::Pool;
using apache::geode::client::Properties;
using apache::geode::client::RegionAttributesFactory;
using apache::geode::client::Serializable;
using unitTests::TestUtils;
CacheHelper* cacheHelper = nullptr;
void initClient(const bool isthinClient,
const std::shared_ptr<Properties>& configPtr = nullptr) {
if (cacheHelper == nullptr) {
cacheHelper = new CacheHelper(isthinClient, configPtr);
}
ASSERT(cacheHelper, "Failed to create a CacheHelper client instance.");
}
void initClientWithPool(const bool isthinClient, const char* poolName,
const std::string& locators, const char* serverGroup,
const std::shared_ptr<Properties>& configPtr = nullptr,
int redundancy = 0, bool clientNotification = false,
int subscriptionAckInterval = -1, int connections = -1,
int loadConditioningInterval = -1,
bool prSingleHop = false, bool threadLocal = false) {
if (cacheHelper == nullptr) {
cacheHelper = new CacheHelper(
isthinClient, poolName, locators, serverGroup, configPtr, redundancy,
clientNotification, subscriptionAckInterval, connections,
loadConditioningInterval, false, prSingleHop, threadLocal);
}
ASSERT(cacheHelper, "Failed to create a CacheHelper client instance.");
}
/* For HA Clients */
void initClient(int redundancyLevel,
const std::shared_ptr<Properties>& configPtr = nullptr) {
if (cacheHelper == nullptr) {
auto config = configPtr;
if (config == nullptr) {
config = Properties::create();
}
cacheHelper = new CacheHelper(redundancyLevel, config);
}
ASSERT(cacheHelper, "Failed to create a CacheHelper client instance.");
}
void cleanProc() {
if (cacheHelper != nullptr) {
delete cacheHelper;
cacheHelper = nullptr;
}
}
void netDown() {
if (cacheHelper != nullptr) {
TestUtils::getCacheImpl(cacheHelper->cachePtr)->netDown();
}
}
void revive() {
if (cacheHelper != nullptr) {
TestUtils::getCacheImpl(cacheHelper->cachePtr)->revive();
}
}
void crashClient() {
if (cacheHelper != nullptr) {
TestUtils::getCacheImpl(cacheHelper->cachePtr)->setClientCrashTEST();
}
}
CacheHelper* getHelper() {
ASSERT(cacheHelper != nullptr, "No cacheHelper initialized.");
return cacheHelper;
}
const char* testregex[] = {"Key-*1", "Key-*2", "Key-*3",
"Key-*4", "Key-*5", "Key-*6"};
const char* keys[] = {"Key-1", "Key-2", "Key-3", "Key-4", "Key-5", "Key-6"};
const char* vals[] = {"Value-1", "Value-2", "Value-3",
"Value-4", "Value-5", "Value-6"};
const char* nvals[] = {"New Value-1", "New Value-2", "New Value-3",
"New Value-4", "New Value-5", "New Value-6"};
const char* regionNames[] = {"DistRegionAck", "DistRegionNoAck"};
const bool USE_ACK = true;
const bool NO_ACK = false;
void _verifyEntry(const std::string& name, const char* key, const char* val,
bool noKey, bool checkVal = true) {
// Verify key and value exist in this region, in this process.
const char* value = val ? val : "";
std::string msg;
if (noKey) {
msg =
std::string("Verify key ") + key + " does not exist in region " + name;
} else if (!val) {
msg = std::string("Verify value for key ") + key +
" does not exist in region " + name;
} else {
msg = std::string("Verify value for key ") + key + " is: " + value +
" in region " + name;
}
LOG(msg);
auto regPtr = getHelper()->getRegion(name);
ASSERT(regPtr != nullptr, "Region not found.");
auto keyPtr = CacheableKey::create(key);
if (noKey == false) { // need to find the key!
ASSERT(regPtr->containsKey(keyPtr), "Key not found in region.");
}
if (val != nullptr && checkVal) { // need to have a value!
ASSERT(regPtr->containsValueForKey(keyPtr), "Value not found in region.");
}
// loop up to MAX times, testing condition
uint32_t MAX = 100;
uint32_t SLEEP = 10; // milliseconds
uint32_t containsKeyCnt = 0;
uint32_t containsValueCnt = 0;
uint32_t testValueCnt = 0;
for (int i = MAX; i >= 0; i--) {
if (noKey) {
if (regPtr->containsKey(keyPtr)) {
containsKeyCnt++;
} else {
break;
}
ASSERT(containsKeyCnt < MAX, "Key found in region.");
}
if (val == nullptr) {
if (regPtr->containsValueForKey(keyPtr)) {
containsValueCnt++;
} else {
break;
}
ASSERT(containsValueCnt < MAX, "Value found in region.");
}
if (val != nullptr) {
auto checkPtr =
std::dynamic_pointer_cast<CacheableString>(regPtr->get(keyPtr));
ASSERT(checkPtr != nullptr, "Value Ptr should not be null.");
LOG("In verify loop, get returned " + checkPtr->value() + " for key " +
key);
if (strcmp(checkPtr->value().c_str(), value) != 0) {
testValueCnt++;
} else {
break;
}
ASSERT(testValueCnt < MAX, "Incorrect value found.");
}
dunit::sleep(SLEEP);
}
}
#define verifyInvalid(x, y) _verifyInvalid(x, y, __LINE__)
void _verifyInvalid(const char* name, const char* key, int line) {
LOG(std::string("verifyInvalid() called from ") + std::to_string(line) +
"\n");
_verifyEntry(name, key, nullptr, false);
LOG("Entry invalidated.");
}
#define verifyDestroyed(x, y) _verifyDestroyed(x, y, __LINE__)
void _verifyDestroyed(const char* name, const char* key, int line) {
LOG(std::string("verifyDestroyed() called from ") + std::to_string(line) +
"\n");
_verifyEntry(name, key, nullptr, true);
LOG("Entry destroyed.");
}
void verifyEntry(const std::string& name, const char* key, const char* val,
bool checkVal = true) {
LOG(std::string("verifyEntry() called from ") + std::to_string(__LINE__) +
"\n");
_verifyEntry(name, key, val, false, checkVal);
LOG("Entry verified.");
}
void _verifyIntEntry(const char* name, const char* key, const int val,
bool noKey, bool isCreated = false) {
// Verify key and value exist in this region, in this process.
int value = val;
std::string msg;
if (!isCreated) {
if (noKey) {
msg = std::string("Verify key ") + key + " does not exist in region " +
name;
} else if (val == 0) {
msg = std::string("Verify value for key ") + key +
" does not exist in region " + name;
} else {
msg = std::string("Verify value for key ") + key +
" is: " + std::to_string(value) + " in region " + name;
}
LOG(msg);
}
auto regPtr = getHelper()->getRegion(name);
ASSERT(regPtr != nullptr, "Region not found.");
auto keyPtr = CacheableKey::create(key);
// if the region is no ack, then we may need to wait...
if (!isCreated) {
if (noKey == false) { // need to find the key!
ASSERT(regPtr->containsKey(keyPtr), "Key not found in region.");
}
if (val != 0) { // need to have a value!
// ASSERT( regPtr->containsValueForKey( keyPtr ), "Value not found in
// region." );
}
}
// loop up to MAX times, testing condition
uint32_t MAX = 100;
// changed sleep from 10 ms
uint32_t SLEEP = 10; // milliseconds
uint32_t containsKeyCnt = 0;
uint32_t containsValueCnt = 0;
uint32_t testValueCnt = 0;
for (int i = MAX; i >= 0; i--) {
if (isCreated) {
if (!regPtr->containsKey(keyPtr)) {
containsKeyCnt++;
} else {
break;
}
ASSERT(containsKeyCnt < MAX, "Key has not been created in region.");
} else {
if (noKey) {
if (regPtr->containsKey(keyPtr)) {
containsKeyCnt++;
} else {
break;
}
ASSERT(containsKeyCnt < MAX, "Key found in region.");
}
if (val == 0) {
if (regPtr->containsValueForKey(keyPtr)) {
containsValueCnt++;
} else {
break;
}
ASSERT(containsValueCnt < MAX, "Value found in region.");
}
if (val != 0) {
auto checkPtr =
std::dynamic_pointer_cast<CacheableInt32>(regPtr->get(keyPtr));
ASSERT(checkPtr != nullptr, "Value Ptr should not be null.");
LOG("In verify loop, get returned " +
std::to_string(checkPtr->value()) + " for key " + key);
if (checkPtr->value() != value) {
testValueCnt++;
} else {
break;
}
ASSERT(testValueCnt < MAX, "Incorrect value found.");
}
}
dunit::sleep(SLEEP);
}
}
#define verifyIntEntry(x, y, z) _verifyIntEntry(x, y, z, __LINE__)
void _verifyIntEntry(const char* name, const char* key, const int val,
int line) {
LOG(std::string("verifyIntEntry() called from ") + std::to_string(line) +
"\n");
_verifyIntEntry(name, key, val, false);
LOG("Entry verified.");
}
void createRegion(const char* name, bool ackMode,
bool clientNotificationEnabled = false,
const std::shared_ptr<CacheListener>& listener = nullptr,
bool caching = true) {
LOG("createRegion() entered.");
std::cout << "Creating region -- " << name << " ackMode is " << ackMode
<< "\n"
<< std::flush;
// ack, caching
auto regPtr = getHelper()->createRegion(name, ackMode, caching, listener,
clientNotificationEnabled);
ASSERT(regPtr != nullptr, "Failed to create region.");
LOG("Region created.");
}
std::shared_ptr<Region> createOverflowRegion(const char* name, bool,
int lel = 0, bool caching = true) {
std::string bdb_dir = "BDB";
std::string bdb_dirEnv = "BDBEnv";
RegionAttributesFactory regionAttributesFactory;
regionAttributesFactory.setCachingEnabled(caching);
regionAttributesFactory.setLruEntriesLimit(lel);
regionAttributesFactory.setDiskPolicy(DiskPolicyType::OVERFLOWS);
auto sqLiteProps = Properties::create();
sqLiteProps->insert("PageSize", "65536");
sqLiteProps->insert("MaxPageCount", "1073741823");
std::string sqlite_dir =
"SqLiteRegionData" + std::to_string(boost::this_process::get_id());
sqLiteProps->insert("PersistenceDirectory", sqlite_dir.c_str());
regionAttributesFactory.setPersistenceManager(
"SqLiteImpl", "createSqLiteInstance", sqLiteProps);
auto regionAttributes = regionAttributesFactory.create();
auto cache = getHelper()->cachePtr;
CacheImpl* cacheImpl = CacheRegionHelper::getCacheImpl(cache.get());
std::shared_ptr<Region> regionPtr;
cacheImpl->createRegion(name, regionAttributes, regionPtr);
return regionPtr;
}
std::shared_ptr<Region> createPooledRegion(
const char* name, bool ackMode, const std::string& locators,
const char* poolname, bool clientNotificationEnabled = false,
const std::shared_ptr<CacheListener>& listener = nullptr,
bool caching = true) {
LOG("createPooledRegion() entered.");
std::cout << "Creating region -- " << name << " ackMode is " << ackMode
<< "\n"
<< std::flush;
if (cacheHelper == nullptr) {
cacheHelper = new CacheHelper(true, poolname, locators, nullptr);
}
// ack, caching
auto regPtr = getHelper()->createPooledRegion(
name, ackMode, locators, poolname, caching, clientNotificationEnabled,
std::chrono::seconds(0), std::chrono::seconds(0), std::chrono::seconds(0),
std::chrono::seconds(0), 0, listener);
ASSERT(regPtr != nullptr, "Failed to create region.");
LOG("Region created.");
return regPtr;
}
std::shared_ptr<Pool> findPool(const char* poolName) {
LOG("findPool() entered.");
auto poolPtr = getHelper()->getCache()->getPoolManager().find(poolName);
ASSERT(poolPtr != nullptr, "Failed to find pool.");
return poolPtr;
}
std::shared_ptr<Pool> createPool(
const std::string& poolName, const std::string& locators,
const std::string& serverGroup, int redundancy = 0,
bool clientNotification = false,
std::chrono::milliseconds subscriptionAckInterval =
std::chrono::milliseconds::zero(),
int connections = -1, int loadConditioningInterval = -1) {
LOG("createPool() entered.");
auto poolPtr = getHelper()->createPool(
poolName, locators, serverGroup, redundancy, clientNotification,
subscriptionAckInterval, connections, loadConditioningInterval);
ASSERT(poolPtr != nullptr, "Failed to create pool.");
LOG("Pool created.");
return poolPtr;
}
std::shared_ptr<Pool> createPoolAndDestroy(
const std::string& poolName, const std::string& locators,
const std::string& serverGroup, int redundancy = 0,
bool clientNotification = false,
std::chrono::milliseconds subscriptionAckInterval =
std::chrono::milliseconds::zero(),
int connections = -1) {
LOG("createPoolAndDestroy() entered.");
auto poolPtr = getHelper()->createPool(poolName, locators, serverGroup,
redundancy, clientNotification,
subscriptionAckInterval, connections);
ASSERT(poolPtr != nullptr, "Failed to create pool.");
poolPtr->destroy();
LOG("Pool created and destroyed.");
return poolPtr;
}
// this will create pool even endpoints and locatorhost has been not defined
std::shared_ptr<Pool> createPool2(const std::string& poolName,
const std::string& locators,
const std::string& serverGroup,
const std::string& servers = nullptr,
int redundancy = 0,
bool clientNotification = false) {
LOG("createPool2() entered.");
auto poolPtr = getHelper()->createPool2(
poolName, locators, serverGroup, servers, redundancy, clientNotification);
ASSERT(poolPtr != nullptr, "Failed to create pool.");
LOG("Pool created.");
return poolPtr;
}
std::shared_ptr<Region> createRegionAndAttachPool(
const std::string& name, bool ack, const std::string& poolName = "",
bool caching = true,
const std::chrono::seconds& ettl = std::chrono::seconds::zero(),
const std::chrono::seconds& eit = std::chrono::seconds::zero(),
const std::chrono::seconds& rttl = std::chrono::seconds::zero(),
const std::chrono::seconds& rit = std::chrono::seconds::zero(), int lel = 0,
ExpirationAction action = ExpirationAction::DESTROY) {
LOG("createRegionAndAttachPool() entered.");
auto regPtr = getHelper()->createRegionAndAttachPool(
name, ack, poolName, caching, ettl, eit, rttl, rit, lel, action);
ASSERT(regPtr != nullptr, "Failed to create region.");
LOG("Region created.");
return regPtr;
}
void createEntry(const std::string& name, const char* key, const char* value) {
LOG("createEntry() entered.");
std::cout << "Creating entry -- key: " << key << " value: " << value
<< " in region " << name << "\n"
<< std::flush;
// Create entry, verify entry is correct
auto keyPtr = CacheableKey::create(key);
auto valPtr = CacheableString::create(value);
auto regPtr = getHelper()->getRegion(name);
ASSERT(regPtr != nullptr, "Region not found.");
ASSERT(!regPtr->containsKey(keyPtr),
"Key should not have been found in region.");
ASSERT(!regPtr->containsValueForKey(keyPtr),
"Value should not have been found in region.");
// regPtr->create( keyPtr, valPtr );
regPtr->put(keyPtr, valPtr);
LOG("Created entry.");
verifyEntry(name, key, value);
LOG("Entry created.");
}
void updateEntry(const char* name, const char* key, const char* value,
bool checkVal = true, bool checkKey = true) {
LOG("updateEntry() entered.");
std::cout << "Updating entry -- key: " << key << " value: " << value
<< " in region " << name << "\n"
<< std::flush;
// Update entry, verify entry is correct
auto keyPtr = CacheableKey::create(key);
auto valPtr = CacheableString::create(value);
auto regPtr = getHelper()->getRegion(name);
ASSERT(regPtr != nullptr, "Region not found.");
if (checkKey) {
ASSERT(regPtr->containsKey(keyPtr),
"Key should have been found in region.");
}
if (checkVal) {
ASSERT(regPtr->containsValueForKey(keyPtr),
"Value should have been found in region.");
}
regPtr->put(keyPtr, valPtr);
LOG("Put entry.");
verifyEntry(name, key, value, checkVal);
LOG("Entry updated.");
}
void doNetsearch(const char* name, const char* key, const char* value,
bool checkVal = true) {
LOG("doNetsearch() entered.");
std::cout << "Netsearching for entry -- key: " << key
<< " expecting value: " << value << " in region " << name << "\n"
<< std::flush;
// Get entry created in Process A, verify entry is correct
auto keyPtr = CacheableKey::create(key);
auto regPtr = getHelper()->getRegion(name);
std::cout << "netsearch region " << regPtr->getName() << "\n" << std::flush;
fflush(stdout);
ASSERT(regPtr != nullptr, "Region not found.");
// ASSERT( !regPtr->containsKey( keyPtr ), "Key should not have been found in
// region." );
if (checkVal) {
ASSERT(!regPtr->containsValueForKey(keyPtr),
"Value should not have been found in region.");
}
auto checkPtr = std::dynamic_pointer_cast<CacheableString>(
regPtr->get(keyPtr)); // force a netsearch
if (checkPtr != nullptr) {
LOG("checkPtr is not null");
LOG(std::string("In net search, get returned ") + checkPtr->value() +
" for key " + key);
} else {
LOG("checkPtr is nullptr");
}
verifyEntry(name, key, value);
LOG("Netsearch complete.");
}
void createIntEntry(const char* name, const char* key, const int value,
bool onlyCreate = false) {
LOG("createEntry() entered.");
std::cout << "Creating entry -- key: " << key << " value: " << value
<< " in region " << name << "\n"
<< std::flush;
// Create entry, verify entry is correct
auto keyPtr = CacheableKey::create(key);
auto valPtr = CacheableInt32::create(value);
auto regPtr = getHelper()->getRegion(name);
ASSERT(regPtr != nullptr, "Region not found.");
if (onlyCreate) {
ASSERT(!regPtr->containsKey(keyPtr),
"Key should not have been found in region.");
ASSERT(!regPtr->containsValueForKey(keyPtr),
"Value should not have been found in region.");
}
regPtr->put(keyPtr, valPtr);
LOG("Created entry.");
verifyIntEntry(name, key, value);
LOG("Entry created.");
}
void invalidateEntry(const char* name, const char* key) {
LOG("invalidateEntry() entered.");
std::cout << "Invalidating entry -- key: " << key << " in region " << name << "\n" << std::flush;
// Invalidate entry, verify entry is invalidated
auto keyPtr = CacheableKey::create(key);
auto regPtr = getHelper()->getRegion(name);
ASSERT(regPtr != nullptr, "Region not found.");
ASSERT(regPtr->containsKey(keyPtr), "Key should have been found in region.");
ASSERT(regPtr->containsValueForKey(keyPtr),
"Value should have been found in region.");
regPtr->localInvalidate(keyPtr);
LOG("Invalidate entry.");
verifyInvalid(name, key);
LOG("Entry invalidated.");
}
void destroyEntry(const char* name, const char* key) {
LOG("destroyEntry() entered.");
std::cout << "Destroying entry -- key: " << key << " in region " << name << "\n" << std::flush;
// Destroy entry, verify entry is destroyed
auto keyPtr = CacheableKey::create(key);
auto regPtr = getHelper()->getRegion(name);
ASSERT(regPtr != nullptr, "Region not found.");
ASSERT(regPtr->containsKey(keyPtr), "Key should have been found in region.");
regPtr->destroy(keyPtr);
LOG("Destroy entry.");
verifyDestroyed(name, key);
LOG("Entry destroyed.");
}
void destroyRegion(const std::string& name) {
LOG("destroyRegion() entered.");
auto regPtr = getHelper()->getRegion(name);
regPtr->localDestroyRegion();
LOG("Region destroyed.");
}
class RegionOperations {
public:
explicit RegionOperations(const char* name)
: m_regionPtr(getHelper()->getRegion(name)) {}
void putOp(int keysMax = 1,
const std::shared_ptr<Serializable>& aCallbackArgument = nullptr) {
for (int i = 1; i <= keysMax; i++) {
auto key = std::string("key") + std::to_string(i);
auto value = std::string("value") + std::to_string(i);
auto valPtr = CacheableString::create(value);
m_regionPtr->put(key, valPtr, aCallbackArgument);
}
}
void invalidateOp(
int keysMax = 1,
const std::shared_ptr<Serializable>& aCallbackArgument = nullptr) {
for (int i = 1; i <= keysMax; i++) {
auto key = std::string("key") + std::to_string(i);
std::string value;
auto valPtr = CacheableString::create(value);
m_regionPtr->localInvalidate(key, aCallbackArgument);
}
}
void destroyOp(
int keysMax = 1,
const std::shared_ptr<Serializable>& aCallbackArgument = nullptr) {
for (int i = 1; i <= keysMax; i++) {
auto key = std::string("key") + std::to_string(i);
std::string value;
auto valPtr = CacheableString::create(value);
m_regionPtr->destroy(key, aCallbackArgument);
}
}
void removeOp(
int keysMax = 1,
const std::shared_ptr<Serializable>& aCallbackArgument = nullptr) {
for (int i = 1; i <= keysMax; i++) {
auto key = std::string("key") + std::to_string(i);
auto value = std::string("value") + std::to_string(i);
auto valPtr = CacheableString::create(value);
m_regionPtr->remove(key, valPtr, aCallbackArgument);
}
}
std::shared_ptr<Region> m_regionPtr;
};
} // namespace
#endif // GEODE_INTEGRATION_TEST_THINCLIENTHELPER_H_