using namespace std;
-namespace {
-bool get_json_format(const std::string& s, json_spirit::mObject *o) {
- json_spirit::mValue json_root;
- if (!json_spirit::read(s.c_str(), json_root)) {
- return false;
- } else {
- auto cache_state_root = json_root.get_obj()["persistent_cache"];
- *o = cache_state_root.get_obj();
- }
- return true;
-}
-} // namespace
-
template <typename I>
-ImageCacheState<I>::ImageCacheState(I *image_ctx, plugin::Api<I>& plugin_api) :
- m_image_ctx(image_ctx), m_plugin_api(plugin_api) {
- ldout(image_ctx->cct, 20) << "Initialize RWL cache state with config data. "
- << dendl;
-
- ConfigProxy &config = image_ctx->config;
+void ImageCacheState<I>::init_from_config() {
+ ldout(m_image_ctx->cct, 20) << dendl;
+
+ present = false;
+ empty = true;
+ clean = true;
+ host = "";
+ path = "";
+ ConfigProxy &config = m_image_ctx->config;
mode = config.get_val<std::string>("rbd_persistent_cache_mode");
+ size = 0;
}
template <typename I>
-ImageCacheState<I>::ImageCacheState(
- I *image_ctx, json_spirit::mObject &o, plugin::Api<I>& plugin_api) :
- m_image_ctx(image_ctx), m_plugin_api(plugin_api) {
- ldout(image_ctx->cct, 20) << "Initialize RWL cache state with data from "
- << "server side"<< dendl;
+bool ImageCacheState<I>::init_from_metadata(json_spirit::mValue& json_root) {
+ ldout(m_image_ctx->cct, 20) << dendl;
try {
+ auto& o = json_root.get_obj();
present = o["present"].get_bool();
empty = o["empty"].get_bool();
clean = o["clean"].get_bool();
mode = o["mode"].get_str();
size = o["size"].get_uint64();
} catch (std::runtime_error& e) {
- lderr(image_ctx->cct) << "failed to parse cache state: " << e.what()
- << dendl;
+ lderr(m_image_ctx->cct) << "failed to parse cache state: " << e.what()
+ << dendl;
+ return false;
}
+
+ return true;
}
template <typename I>
o["misses"] = misses;
o["hit_bytes"] = hit_bytes;
o["miss_bytes"] = miss_bytes;
- json_spirit::mObject cache_state_obj;
- cache_state_obj["persistent_cache"] = o;
- stringstream json_string;
- json_spirit::write(cache_state_obj, json_string);
- std::string image_state_json = json_string.str();
+ std::string image_state_json = json_spirit::write(o);
ldout(m_image_ctx->cct, 20) << __func__ << " Store state: "
<< image_state_json << dendl;
r = -EINVAL;
}else if ((!dirty_cache || cache_state_str.empty()) && cache_desired) {
cache_state = new ImageCacheState<I>(image_ctx, plugin_api);
+ cache_state->init_from_config();
} else {
ceph_assert(!cache_state_str.empty());
- json_spirit::mObject o;
- bool success = get_json_format(cache_state_str, &o);
- if (!success) {
- lderr(image_ctx->cct) << "failed to parse cache state: "
- << cache_state_str << dendl;
+ json_spirit::mValue json_root;
+ if (!json_spirit::read(cache_state_str.c_str(), json_root)) {
+ lderr(image_ctx->cct) << "failed to parse cache state" << dendl;
r = -EINVAL;
return nullptr;
}
-
- bool cache_exists = o["present"].get_bool();
- if (!cache_exists) {
- cache_state = new ImageCacheState<I>(image_ctx, plugin_api);
- } else {
- cache_state = new ImageCacheState<I>(image_ctx, o, plugin_api);
+ cache_state = new ImageCacheState<I>(image_ctx, plugin_api);
+ if (!cache_state->init_from_metadata(json_root)) {
+ delete cache_state;
+ r = -EINVAL;
+ return nullptr;
+ }
+ if (!cache_state->present) {
+ cache_state->init_from_config();
}
}
return cache_state;
cls_client::metadata_get(&image_ctx->md_ctx, image_ctx->header_oid,
IMAGE_CACHE_STATE, &cache_state_str);
if (!cache_state_str.empty()) {
- json_spirit::mObject o;
- bool success = get_json_format(cache_state_str, &o);
- if (!success) {
+ // ignore errors, best effort
+ cache_state = new ImageCacheState<I>(image_ctx, plugin_api);
+ json_spirit::mValue json_root;
+ if (!json_spirit::read(cache_state_str.c_str(), json_root)) {
lderr(image_ctx->cct) << "failed to parse cache state" << dendl;
- cache_state = new ImageCacheState<I>(image_ctx, plugin_api);
} else {
- cache_state = new ImageCacheState<I>(image_ctx, o, plugin_api);
+ cache_state->init_from_metadata(json_root);
}
}
return cache_state;
ASSERT_EQ(0, finish_ctx.wait());
}
-static void get_jf(const string& s, json_spirit::mObject *f)
-{
- json_spirit::mValue json_root;
- bool result = json_spirit::read(s.c_str(), json_root);
- if (!result) {
- cout << "failed to parse: '" << s << "'" << std::endl;
- } else {
- auto cache_state_root = json_root.get_obj()["persistent_cache"];
- *f = cache_state_root.get_obj();
- }
- ASSERT_EQ(true, result);
-}
-
TEST_F(TestMockCacheReplicatedWriteLog, init_state_json_write) {
librbd::ImageCtx *ictx;
ASSERT_EQ(0, open_image(m_image_name, &ictx));
MockImageCtx mock_image_ctx(*ictx);
-
- json_spirit::mObject f;
- string strf = "{ \"present\": \"1\", \"empty\": \"0\", \"clean\": \"0\", \
- \"pwl_host\": \"testhost\", \
- \"pwl_path\": \"/tmp\", \
- \"pwl_size\": \"1024\" }";
- get_jf(strf, &f);
MockApi mock_api;
- MockImageCacheStateRWL image_cache_state(&mock_image_ctx, f, mock_api);
+ MockImageCacheStateRWL image_cache_state(&mock_image_ctx, mock_api);
+ string strf = "{ \"present\": true, \"empty\": false, \"clean\": false, \
+ \"host\": \"testhost\", \
+ \"path\": \"/tmp\", \
+ \"mode\": \"rwl\", \
+ \"size\": 1024 }";
+ json_spirit::mValue json_root;
+ ASSERT_TRUE(json_spirit::read(strf.c_str(), json_root));
+ ASSERT_TRUE(image_cache_state.init_from_metadata(json_root));
validate_cache_state(ictx, image_cache_state, true, false, false,
"testhost", "/tmp", 1024);
ASSERT_EQ(0, finish_ctx.wait());
}
-static void get_jf(const string& s, json_spirit::mObject *f)
-{
- json_spirit::mValue json_root;
- bool result = json_spirit::read(s.c_str(), json_root);
- if (!result) {
- cout << "failed to parse: '" << s << "'" << std::endl;
- } else {
- auto cache_state_root = json_root.get_obj()["persistent_cache"];
- *f = cache_state_root.get_obj();
- }
- ASSERT_EQ(true, result);
-}
-
TEST_F(TestMockCacheSSDWriteLog, init_state_json_write) {
librbd::ImageCtx *ictx;
ASSERT_EQ(0, open_image(m_image_name, &ictx));
MockImageCtx mock_image_ctx(*ictx);
-
- json_spirit::mObject f;
- string strf = "{ \"present\": \"1\", \"empty\": \"0\", \"clean\": \"0\", \
- \"pwl_host\": \"testhost\", \
- \"pwl_path\": \"/tmp\", \
- \"pwl_size\": \"1024\" }";
- get_jf(strf, &f);
MockApi mock_api;
- MockImageCacheStateSSD image_cache_state(&mock_image_ctx, f, mock_api);
+ MockImageCacheStateSSD image_cache_state(&mock_image_ctx, mock_api);
+ string strf = "{ \"present\": true, \"empty\": false, \"clean\": false, \
+ \"host\": \"testhost\", \
+ \"path\": \"/tmp\", \
+ \"mode\": \"ssd\", \
+ \"size\": 1024 }";
+ json_spirit::mValue json_root;
+ ASSERT_TRUE(json_spirit::read(strf.c_str(), json_root));
+ ASSERT_TRUE(image_cache_state.init_from_metadata(json_root));
validate_cache_state(ictx, image_cache_state, true, false, false,
"testhost", "/tmp", 1024);