|
| 1 | +/* |
| 2 | +# Licensed Materials - Property of IBM |
| 3 | +# Copyright IBM Corp. 2011, 2020 |
| 4 | +# US Government Users Restricted Rights - Use, duplication or |
| 5 | +# disclosure restricted by GSA ADP Schedule Contract with |
| 6 | +# IBM Corp. |
| 7 | +*/ |
| 8 | +#ifndef REDIS_CLUSTER_PLUS_PLUS_DB_LAYER_H_ |
| 9 | +#define REDIS_CLUSTER_PLUS_PLUS_DB_LAYER_H_ |
| 10 | +/* |
| 11 | +===================================================================== |
| 12 | +Here is the copyright statement for our use of the hiredis APIs: |
| 13 | +
|
| 14 | +Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and |
| 15 | +Pieter Noordhuis (pcnoordhuis at gmail) and is released under the |
| 16 | +BSD license. |
| 17 | +
|
| 18 | +Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com> |
| 19 | +Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com> |
| 20 | +
|
| 21 | +hiredis-cluster-plus-plus include files provide wrappers on top of the hiredis library. |
| 22 | +This wrapper allows us to use the familiar hiredis APIs in the context of |
| 23 | +a Redis cluster (Version 6 and higher) to provide HA facility for automatic |
| 24 | +fail-over when a Redis instance or the entire machine crashes. |
| 25 | +In addition, it provides the TLS/SSL support for the redis-cluster. |
| 26 | +Please note that this hiredis-cluster-plus-plus wrapper supercedes the older |
| 27 | +hiredis-cluster wrapper that we have in the DPS toolkit. If the Redis server |
| 28 | +version is v5 and lower, one may continue to use the older hiredis-cluster in DPS. |
| 29 | +If the Redis server version is v6 and higher, it is recommented to use the |
| 30 | +hiredis-cluster-plus-plus in order to work with both non-TLS and TLS. |
| 31 | +
|
| 32 | +The redis-plus-plus wrapper carries the Apache 2.0 copyright as shown in the following line. |
| 33 | +
|
| 34 | +A permissive license whose main conditions require preservation of copyright and license notices. |
| 35 | +Contributors provide an express grant of patent rights. Licensed works, modifications, and larger |
| 36 | +works may be distributed under different terms and without source code. |
| 37 | +===================================================================== |
| 38 | +*/ |
| 39 | +#include "DBLayer.h" |
| 40 | + |
| 41 | +#include <tr1/memory> |
| 42 | +#include <set> |
| 43 | +#include <vector> |
| 44 | +#include <sw/redis++/redis_cluster.h> |
| 45 | + |
| 46 | +using namespace sw::redis; |
| 47 | + |
| 48 | +namespace com { |
| 49 | +namespace ibm { |
| 50 | +namespace streamsx { |
| 51 | +namespace store { |
| 52 | +namespace distributed |
| 53 | +{ |
| 54 | + class RedisClusterPlusPlusDBLayer; |
| 55 | + |
| 56 | + /// Class that implements the Iterator for Redis cluster |
| 57 | + class RedisClusterPlusPlusDBLayerIterator : public DBLayer::Iterator |
| 58 | + { |
| 59 | + public: |
| 60 | + uint64_t store; |
| 61 | + std::string storeName; |
| 62 | + std::vector<std::string> dataItemKeys; |
| 63 | + uint32_t sizeOfDataItemKeysVector; |
| 64 | + uint32_t currentIndex; |
| 65 | + bool hasData; |
| 66 | + RedisClusterPlusPlusDBLayer *redisClusterPlusPlusDBLayerPtr; |
| 67 | + |
| 68 | + RedisClusterPlusPlusDBLayerIterator(); |
| 69 | + ~RedisClusterPlusPlusDBLayerIterator(); |
| 70 | + bool getNext(uint64_t store, unsigned char * & keyData, uint32_t & keySize, |
| 71 | + unsigned char * & valueData, uint32_t & valueSize, PersistenceError & dbError); |
| 72 | + }; |
| 73 | + |
| 74 | + /// Class that implements the DBLayer for Redis Cluster Plus Plus |
| 75 | + class RedisClusterPlusPlusDBLayer : public DBLayer |
| 76 | + { |
| 77 | + private: |
| 78 | + bool readStoreInformation(std::string const & storeIdString, PersistenceError & dbError, |
| 79 | + uint32_t & dataItemCnt, std::string & storeName, |
| 80 | + std::string & keySplTypeName, std::string & valueSplTypeName); |
| 81 | + bool acquireStoreLock(std::string const & storeIdString); |
| 82 | + void releaseStoreLock(std::string const & storeIdString); |
| 83 | + bool readLockInformation(std::string const & storeIdString, PersistenceError & dbError, uint32_t & lockUsageCnt, |
| 84 | + int32_t & lockExpirationTime, pid_t & lockOwningPid, std::string & lockName); |
| 85 | + bool updateLockInformation(std::string const & lockIdString, PersistenceError & lkError, |
| 86 | + uint32_t const & lockUsageCnt, int32_t const & lockExpirationTime, pid_t const & lockOwningPid); |
| 87 | + bool lockIdExistsOrNot(std::string lockIdString, PersistenceError & lkError); |
| 88 | + bool acquireGeneralPurposeLock(std::string const & entityName); |
| 89 | + void releaseGeneralPurposeLock(std::string const & entityName); |
| 90 | + int32_t getRedisServerPartitionIndex(std::string const & key); |
| 91 | + |
| 92 | + public: |
| 93 | + RedisCluster *redis_cluster = NULL; |
| 94 | + |
| 95 | + /// Constructor |
| 96 | + RedisClusterPlusPlusDBLayer(); |
| 97 | + |
| 98 | + /// Destructor |
| 99 | + ~RedisClusterPlusPlusDBLayer(); |
| 100 | + |
| 101 | + // These are inherited from DBLayer, see DBLayer for descriptions |
| 102 | + void connectToDatabase(std::set<std::string> const & dbServers, PersistenceError & dbError); |
| 103 | + |
| 104 | + uint64_t createStore(std::string const & name, |
| 105 | + std::string const & keySplTypeName, |
| 106 | + std::string const & valueSplTypeName, |
| 107 | + PersistenceError & dbError); |
| 108 | + uint64_t createOrGetStore(std::string const & name, |
| 109 | + std::string const & keySplTypeName, |
| 110 | + std::string const & valueSplTypeName, |
| 111 | + PersistenceError & dbError); |
| 112 | + uint64_t findStore(std::string const & name, |
| 113 | + PersistenceError & dbError); |
| 114 | + bool removeStore(uint64_t store, PersistenceError & dbError); |
| 115 | + |
| 116 | + bool put(uint64_t store, char const * keyData, uint32_t keySize, |
| 117 | + unsigned char const * valueData, uint32_t valueSize, PersistenceError & dbError); |
| 118 | + bool putSafe(uint64_t store, char const * keyData, uint32_t keySize, |
| 119 | + unsigned char const * valueData, uint32_t valueSize, PersistenceError & dbError); |
| 120 | + bool putTTL(char const * keyData, uint32_t keySize, |
| 121 | + unsigned char const * valueData, uint32_t valueSize, uint32_t ttl, PersistenceError & dbError, bool encodeKey=true, bool encodeValue=true); |
| 122 | + bool get(uint64_t store, char const * keyData, uint32_t keySize, |
| 123 | + unsigned char * & valueData, uint32_t & valueSize, |
| 124 | + PersistenceError & dbError); |
| 125 | + bool getSafe(uint64_t store, char const * keyData, uint32_t keySize, |
| 126 | + unsigned char * & valueData, uint32_t & valueSize, |
| 127 | + PersistenceError & dbError); |
| 128 | + bool getTTL(char const * keyData, uint32_t keySize, |
| 129 | + unsigned char * & valueData, uint32_t & valueSize, |
| 130 | + PersistenceError & dbError, bool encodeKey=true); |
| 131 | + bool remove(uint64_t store, char const * keyData, uint32_t keySize, PersistenceError & dbError); |
| 132 | + bool removeTTL(char const * keyData, uint32_t keySize, PersistenceError & dbError, bool encodeKey=true); |
| 133 | + bool has(uint64_t store, char const * keyData, uint32_t keySize, PersistenceError & dbError); |
| 134 | + bool hasTTL(char const * keyData, uint32_t keySize, PersistenceError & dbError, bool encodeKey=true); |
| 135 | + void clear(uint64_t store, PersistenceError & dbError); |
| 136 | + uint64_t size(uint64_t store, PersistenceError & dbError); |
| 137 | + void base64_encode(std::string const & str, std::string & base64); |
| 138 | + void base64_decode(std::string & base64, std::string & result); |
| 139 | + bool isConnected(); |
| 140 | + bool reconnect(std::set<std::string> & dbServers, PersistenceError & dbError); |
| 141 | + |
| 142 | + RedisClusterPlusPlusDBLayerIterator * newIterator(uint64_t store, PersistenceError & dbError); |
| 143 | + void deleteIterator(uint64_t store, Iterator * iter, PersistenceError & dbError); |
| 144 | + bool storeIdExistsOrNot(std::string storeIdString, PersistenceError & dbError); |
| 145 | + bool getDataItemFromStore(std::string const & storeIdString, |
| 146 | + std::string const & keyDataString, bool const & checkOnlyForDataItemExistence, |
| 147 | + bool const & skipDataItemExistenceCheck, unsigned char * & valueData, |
| 148 | + uint32_t & valueSize, PersistenceError & dbError); |
| 149 | + std::string getStoreName(uint64_t store, PersistenceError & dbError); |
| 150 | + std::string getSplTypeNameForKey(uint64_t store, PersistenceError & dbError); |
| 151 | + std::string getSplTypeNameForValue(uint64_t store, PersistenceError & dbError); |
| 152 | + std::string getNoSqlDbProductName(void); |
| 153 | + void getDetailsAboutThisMachine(std::string & machineName, std::string & osVersion, std::string & cpuArchitecture); |
| 154 | + bool runDataStoreCommand(std::string const & cmd, PersistenceError & dbError); |
| 155 | + bool runDataStoreCommand(uint32_t const & cmdType, std::string const & httpVerb, |
| 156 | + std::string const & baseUrl, std::string const & apiEndpoint, std::string const & queryParams, |
| 157 | + std::string const & jsonRequest, std::string & jsonResponse, PersistenceError & dbError); |
| 158 | + bool runDataStoreCommand(std::vector<std::string> const & cmdList, std::string & resultValue, PersistenceError & dbError); |
| 159 | + |
| 160 | + // Lock related methods. |
| 161 | + uint64_t createOrGetLock(std::string const & name, PersistenceError & lkError); |
| 162 | + void releaseLock(uint64_t lock, PersistenceError & lkError); |
| 163 | + bool acquireLock(uint64_t lock, double leaseTime, double maxWaitTimeToAcquireLock, PersistenceError & lkError); |
| 164 | + bool removeLock(uint64_t lock, PersistenceError & lkError); |
| 165 | + uint32_t getPidForLock(std::string const & name, PersistenceError & lkError); |
| 166 | + void persist(PersistenceError & dbError); |
| 167 | + |
| 168 | + }; |
| 169 | +} } } } } |
| 170 | +#endif /* REDIS_CLUSTER_PLUS_PLUS_DB_LAYER_H_ */ |
0 commit comments