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

Commit 39435b8

Browse files
committed
Add support for checking cache incompatibility
1 parent be0e00a commit 39435b8

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

lib/KVStore/KVStore.cpp

Lines changed: 55 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,59 @@ 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+
switch(reply->type) {
90+
case REDIS_REPLY_NIL:
91+
// no version set
92+
freeReplyObject(reply);
93+
reply = static_cast<redisReply*>(redisCommand(Ctx, "SET cachetype %s", ActiveOptionsStr.data()));
94+
// TODO: Factor out all such snippets
95+
if (!reply || Ctx->err) {
96+
llvm::report_fatal_error((llvm::StringRef)"Redis error: " + Ctx->errstr);
97+
}
98+
break;
99+
case REDIS_REPLY_STRING:
100+
if (llvm::StringRef value = reply->str; value != ActiveOptionsStr)
101+
return false;
102+
break;
103+
default: return false;
104+
}
105+
106+
return true;
107+
}
108+
55109
void KVStore::KVImpl::hIncrBy(llvm::StringRef Key, llvm::StringRef Field,
56110
int Incr) {
57111
redisReply *reply = (redisReply *)redisCommand(Ctx, "HINCRBY %s %s 1",

0 commit comments

Comments
 (0)