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

Commit f0ebbc3

Browse files
committed
Add support for checking cache incompatibility
1 parent e8874c5 commit f0ebbc3

File tree

1 file changed

+99
-1
lines changed

1 file changed

+99
-1
lines changed

lib/KVStore/KVStore.cpp

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

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

2325
static cl::opt<unsigned> RedisPort("souper-redis-port", cl::init(6379),
2426
cl::desc("Redis server port (default=6379)"));
2527

28+
namespace {
29+
30+
std::vector<std::string> getActiveOptions(StringMap<cl::Option*> &Opts) {
31+
std::vector<std::string> ActiveOptions;
32+
33+
for (auto &K : Opts.keys()) {
34+
if (Opts[K]->getNumOccurrences()) {
35+
std::string StrValue;
36+
37+
// cl::opt<unsigned>
38+
if (K == "souper-exhaustive-synthesis-num-instructions") {
39+
auto Val = static_cast<cl::opt<unsigned> *>(Opts[K]);
40+
StrValue = K.str() + "=" + std::to_string(Val->getValue());
41+
}
42+
// cl::opt<bool, true> with default=false
43+
else if (K == "souper-use-alive") {
44+
auto Val = static_cast<cl::opt<bool, true> *>(Opts[K]);
45+
StrValue = K.str() + "=" + (Val->getValue() ? "true" : "false");
46+
}
47+
// cl::opt<bool> with default=false
48+
else if (K == "souper-lsb-pruning" ||
49+
K == "souper-dataflow-pruning" ||
50+
K == "souper-synthesis-const-with-cegis" ||
51+
K == "souper-synthesis-ignore-cost") {
52+
auto Val = static_cast<cl::opt<bool> *>(Opts[K]);
53+
if (Val->getValue())
54+
StrValue = K.str() + "=true";
55+
}
56+
// cl::opt<int>
57+
else if (K == "souper-synthesis-comp-num") {
58+
auto Val = static_cast<cl::opt<int> *>(Opts[K]);
59+
StrValue = K.str() + "=" + std::to_string(Val->getValue());
60+
}
61+
// cl::opt<std::string>
62+
else if (K == "souper-synthesis-comps") {
63+
auto Val = static_cast<cl::opt<std::string> *>(Opts[K]);
64+
StrValue = K.str() + "=" + Val->getValue();
65+
}
66+
67+
if (!StrValue.empty())
68+
ActiveOptions.emplace_back(StrValue);
69+
}
70+
}
71+
72+
return ActiveOptions;
73+
}
74+
75+
} // anon ns
76+
2677
namespace souper {
2778

2879
class KVStore::KVImpl {
29-
redisContext *Ctx;
80+
redisContext *Ctx = 0;
81+
82+
private:
83+
// checks if current redis database is compatible with current version of souper
84+
bool checkCompatibility();
85+
3086
public:
3187
KVImpl();
3288
~KVImpl();
@@ -46,12 +102,54 @@ KVStore::KVImpl::KVImpl() {
46102
llvm::report_fatal_error((llvm::StringRef)"Redis connection error: " +
47103
Ctx->errstr + "\n");
48104
}
105+
106+
if (!checkCompatibility()) {
107+
llvm::report_fatal_error("Redis cache on port " + std::to_string(RedisPort) + " is incompatible.");
108+
}
49109
}
50110

51111
KVStore::KVImpl::~KVImpl() {
52112
redisFree(Ctx);
53113
}
54114

115+
bool KVStore::KVImpl::checkCompatibility() {
116+
assert(Ctx && "Cannot check compatibility on an uninitialized database.");
117+
118+
redisReply *reply = static_cast<redisReply*>(redisCommand(Ctx, "GET cachetype"));
119+
if (!reply || Ctx->err) {
120+
llvm::report_fatal_error((llvm::StringRef)"Redis error: " + Ctx->errstr);
121+
}
122+
123+
// get all current command line used
124+
StringMap<cl::Option*> &Opts = cl::getRegisteredOptions();
125+
std::vector<std::string> ActiveOptions = getActiveOptions(Opts);
126+
std::sort(ActiveOptions.begin(), ActiveOptions.end());
127+
std::ostringstream ActiveOptionsOSS;
128+
const char *delim = ";";
129+
std::copy(ActiveOptions.begin(), ActiveOptions.end(),
130+
std::ostream_iterator<std::string>(ActiveOptionsOSS, delim));
131+
std::string ActiveOptionsStr = ActiveOptionsOSS.str();
132+
133+
switch(reply->type) {
134+
case REDIS_REPLY_NIL:
135+
// no version set
136+
freeReplyObject(reply);
137+
reply = static_cast<redisReply*>(redisCommand(Ctx, "SET cachetype %s", ActiveOptionsStr.data()));
138+
// TODO: Factor out all such snippets
139+
if (!reply || Ctx->err) {
140+
llvm::report_fatal_error((llvm::StringRef)"Redis error: " + Ctx->errstr);
141+
}
142+
break;
143+
case REDIS_REPLY_STRING:
144+
if (llvm::StringRef value = reply->str; value != ActiveOptionsStr)
145+
return false;
146+
break;
147+
default: return false;
148+
}
149+
150+
return true;
151+
}
152+
55153
void KVStore::KVImpl::hIncrBy(llvm::StringRef Key, llvm::StringRef Field,
56154
int Incr) {
57155
redisReply *reply = (redisReply *)redisCommand(Ctx, "HINCRBY %s %s 1",

0 commit comments

Comments
 (0)