Skip to content
This repository was archived by the owner on Oct 30, 2025. It is now read-only.

Commit 8eb1626

Browse files
committed
Add support for checking cache incompatibility
1 parent be0e00a commit 8eb1626

1 file changed

Lines changed: 61 additions & 1 deletion

File tree

lib/KVStore/KVStore.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "llvm/Support/CommandLine.h"
1818
#include "hiredis.h"
1919

20+
#include <sstream>
21+
2022
using namespace llvm;
2123
using namespace souper;
2224

@@ -26,7 +28,12 @@ static cl::opt<unsigned> RedisPort("souper-redis-port", cl::init(6379),
2628
namespace souper {
2729

2830
class KVStore::KVImpl {
29-
redisContext *Ctx;
31+
redisContext *Ctx = 0;
32+
33+
private:
34+
// checks if current redis database is compatible with current version of souper
35+
bool checkCompatibility();
36+
3037
public:
3138
KVImpl();
3239
~KVImpl();
@@ -46,12 +53,65 @@ KVStore::KVImpl::KVImpl() {
4653
llvm::report_fatal_error((llvm::StringRef)"Redis connection error: " +
4754
Ctx->errstr + "\n");
4855
}
56+
57+
if (!checkCompatibility()) {
58+
llvm::report_fatal_error("Redis database on port %d is incompatible.", RedisPort);
59+
}
4960
}
5061

5162
KVStore::KVImpl::~KVImpl() {
5263
redisFree(Ctx);
5364
}
5465

66+
bool KVStore::KVImpl::checkCompatibility() {
67+
assert(Ctx && "Cannot check compatibility on an uninitialized database.");
68+
69+
redisReply *reply = static_cast<redisReply*>(redisCommand(Ctx, "GET cachetype"));
70+
if (!reply || Ctx->err) {
71+
llvm::report_fatal_error((llvm::StringRef)"Redis error: " + Ctx->errstr);
72+
}
73+
74+
// get all current command line used
75+
StringMap<cl::Option*> &Opts = cl::getRegisteredOptions();
76+
std::vector<std::string> ActiveOptions;
77+
for (auto &K : Opts.keys()) {
78+
if (Opts[K]->getNumOccurrences() && K.find("-debug-level") == StringRef::npos) {
79+
ActiveOptions.emplace_back(K.str());
80+
}
81+
}
82+
std::sort(ActiveOptions.begin(), ActiveOptions.end());
83+
std::ostringstream ActiveOptionsOSS;
84+
const char *delim = ",";
85+
std::copy(ActiveOptions.begin(), ActiveOptions.end(),
86+
std::ostream_iterator<std::string>(ActiveOptionsOSS, delim));
87+
std::string ActiveOptionsStr = ActiveOptionsOSS.str();
88+
89+
bool compat = true;
90+
switch(reply->type) {
91+
case REDIS_REPLY_NIL:
92+
// no version set
93+
freeReplyObject(reply);
94+
reply = static_cast<redisReply*>(redisCommand(Ctx, "SET cachetype %s", ActiveOptionsStr.data()));
95+
// TODO: Factor out all such snippets
96+
if (!reply || Ctx->err) {
97+
llvm::report_fatal_error((llvm::StringRef)"Redis error: " + Ctx->errstr);
98+
}
99+
break;
100+
case REDIS_REPLY_STRING:
101+
{
102+
llvm::StringRef value = reply->str;
103+
if (value != ActiveOptionsStr) {
104+
compat = false;
105+
}
106+
}
107+
break;
108+
default:
109+
compat = false;
110+
}
111+
112+
return compat;
113+
}
114+
55115
void KVStore::KVImpl::hIncrBy(llvm::StringRef Key, llvm::StringRef Field,
56116
int Incr) {
57117
redisReply *reply = (redisReply *)redisCommand(Ctx, "HINCRBY %s %s 1",

0 commit comments

Comments
 (0)