forked from vitalif/vitastor
Rebase children of the "inverse" child when it is removed, change /index/image/%s keys during metadata ops
parent
d5efbbb6b9
commit
74cb3911db
22
src/cli.cpp
22
src/cli.cpp
|
@ -95,25 +95,13 @@ void cli_tool_t::change_parent(inode_t cur, inode_t new_parent)
|
||||||
fprintf(stderr, "Inode 0x%lx disappeared\n", cur);
|
fprintf(stderr, "Inode 0x%lx disappeared\n", cur);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
inode_config_t *cur_cfg = &cur_cfg_it->second;
|
inode_config_t new_cfg = cur_cfg_it->second;
|
||||||
std::string cur_name = cur_cfg->name;
|
std::string cur_name = new_cfg.name;
|
||||||
std::string cur_cfg_key = base64_encode(cli->st_cli.etcd_prefix+
|
std::string cur_cfg_key = base64_encode(cli->st_cli.etcd_prefix+
|
||||||
"/config/inode/"+std::to_string(INODE_POOL(cur))+
|
"/config/inode/"+std::to_string(INODE_POOL(cur))+
|
||||||
"/"+std::to_string(INODE_NO_POOL(cur)));
|
"/"+std::to_string(INODE_NO_POOL(cur)));
|
||||||
json11::Json::object cur_cfg_json = json11::Json::object {
|
new_cfg.parent_id = new_parent;
|
||||||
{ "name", cur_cfg->name },
|
json11::Json::object cur_cfg_json = cli->st_cli.serialize_inode_cfg(&new_cfg);
|
||||||
{ "size", cur_cfg->size },
|
|
||||||
};
|
|
||||||
if (new_parent)
|
|
||||||
{
|
|
||||||
if (INODE_POOL(cur) != INODE_POOL(new_parent))
|
|
||||||
cur_cfg_json["parent_pool"] = (uint64_t)INODE_POOL(new_parent);
|
|
||||||
cur_cfg_json["parent_id"] = (uint64_t)INODE_NO_POOL(new_parent);
|
|
||||||
}
|
|
||||||
if (cur_cfg->readonly)
|
|
||||||
{
|
|
||||||
cur_cfg_json["readonly"] = true;
|
|
||||||
}
|
|
||||||
waiting++;
|
waiting++;
|
||||||
cli->st_cli.etcd_txn(json11::Json::object {
|
cli->st_cli.etcd_txn(json11::Json::object {
|
||||||
{ "compare", json11::Json::array {
|
{ "compare", json11::Json::array {
|
||||||
|
@ -121,7 +109,7 @@ void cli_tool_t::change_parent(inode_t cur, inode_t new_parent)
|
||||||
{ "target", "MOD" },
|
{ "target", "MOD" },
|
||||||
{ "key", cur_cfg_key },
|
{ "key", cur_cfg_key },
|
||||||
{ "result", "LESS" },
|
{ "result", "LESS" },
|
||||||
{ "mod_revision", cur_cfg->mod_revision+1 },
|
{ "mod_revision", new_cfg.mod_revision+1 },
|
||||||
},
|
},
|
||||||
} },
|
} },
|
||||||
{ "success", json11::Json::array {
|
{ "success", json11::Json::array {
|
||||||
|
|
|
@ -138,7 +138,8 @@ resume_5:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cb = NULL;
|
cb = NULL;
|
||||||
// Delete "inverse" child metadata and rename parent over it
|
// Delete "inverse" child metadata, rename parent over it,
|
||||||
|
// and also change parent links of the previous "inverse" child
|
||||||
rename_inverse_parent();
|
rename_inverse_parent();
|
||||||
state = 6;
|
state = 6;
|
||||||
resume_6:
|
resume_6:
|
||||||
|
@ -345,47 +346,76 @@ resume_9:
|
||||||
"/config/inode/"+std::to_string(INODE_POOL(inverse_parent))+
|
"/config/inode/"+std::to_string(INODE_POOL(inverse_parent))+
|
||||||
"/"+std::to_string(INODE_NO_POOL(inverse_parent))
|
"/"+std::to_string(INODE_NO_POOL(inverse_parent))
|
||||||
);
|
);
|
||||||
json11::Json::object new_cfg = json11::Json::object {
|
// Fill new configuration
|
||||||
{ "name", child_cfg->name },
|
inode_config_t new_cfg = *child_cfg;
|
||||||
{ "size", child_cfg->size },
|
new_cfg.num = target_cfg->num;
|
||||||
|
new_cfg.parent_id = new_parent;
|
||||||
|
json11::Json::array cmp = json11::Json::array {
|
||||||
|
json11::Json::object {
|
||||||
|
{ "target", "MOD" },
|
||||||
|
{ "key", child_cfg_key },
|
||||||
|
{ "result", "LESS" },
|
||||||
|
{ "mod_revision", child_cfg->mod_revision+1 },
|
||||||
|
},
|
||||||
|
json11::Json::object {
|
||||||
|
{ "target", "MOD" },
|
||||||
|
{ "key", target_cfg_key },
|
||||||
|
{ "result", "LESS" },
|
||||||
|
{ "mod_revision", target_cfg->mod_revision+1 },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
if (new_parent)
|
json11::Json::array txn = json11::Json::array {
|
||||||
|
json11::Json::object {
|
||||||
|
{ "request_delete_range", json11::Json::object {
|
||||||
|
{ "key", child_cfg_key },
|
||||||
|
} },
|
||||||
|
},
|
||||||
|
json11::Json::object {
|
||||||
|
{ "request_put", json11::Json::object {
|
||||||
|
{ "key", target_cfg_key },
|
||||||
|
{ "value", base64_encode(json11::Json(parent->cli->st_cli.serialize_inode_cfg(&new_cfg)).dump()) },
|
||||||
|
} },
|
||||||
|
},
|
||||||
|
json11::Json::object {
|
||||||
|
{ "request_put", json11::Json::object {
|
||||||
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/index/image/"+child_cfg->name) },
|
||||||
|
{ "value", base64_encode(json11::Json({
|
||||||
|
{ "id", INODE_NO_POOL(inverse_parent) },
|
||||||
|
{ "pool_id", (uint64_t)INODE_POOL(inverse_parent) },
|
||||||
|
}).dump()) },
|
||||||
|
} },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Reparent children of inverse_child
|
||||||
|
for (auto & cp: parent->cli->st_cli.inode_config)
|
||||||
{
|
{
|
||||||
if (INODE_POOL(inverse_parent) != INODE_POOL(new_parent))
|
if (cp.second.parent_id == child_cfg->num)
|
||||||
new_cfg["parent_pool"] = (uint64_t)INODE_POOL(new_parent);
|
{
|
||||||
new_cfg["parent_id"] = (uint64_t)INODE_NO_POOL(new_parent);
|
auto cp_cfg = cp.second;
|
||||||
}
|
cp_cfg.parent_id = inverse_parent;
|
||||||
if (child_cfg->readonly)
|
auto cp_key = base64_encode(
|
||||||
{
|
parent->cli->st_cli.etcd_prefix+
|
||||||
new_cfg["readonly"] = true;
|
"/config/inode/"+std::to_string(INODE_POOL(cp.second.num))+
|
||||||
|
"/"+std::to_string(INODE_NO_POOL(cp.second.num))
|
||||||
|
);
|
||||||
|
cmp.push_back(json11::Json::object {
|
||||||
|
{ "target", "MOD" },
|
||||||
|
{ "key", cp_key },
|
||||||
|
{ "result", "LESS" },
|
||||||
|
{ "mod_revision", cp.second.mod_revision+1 },
|
||||||
|
});
|
||||||
|
txn.push_back(json11::Json::object {
|
||||||
|
{ "request_put", json11::Json::object {
|
||||||
|
{ "key", cp_key },
|
||||||
|
{ "value", base64_encode(json11::Json(parent->cli->st_cli.serialize_inode_cfg(&cp_cfg)).dump()) },
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parent->waiting++;
|
parent->waiting++;
|
||||||
parent->cli->st_cli.etcd_txn(json11::Json::object {
|
parent->cli->st_cli.etcd_txn(json11::Json::object {
|
||||||
{ "compare", json11::Json::array {
|
{ "compare", cmp },
|
||||||
json11::Json::object {
|
{ "success", txn },
|
||||||
{ "target", "MOD" },
|
|
||||||
{ "key", child_cfg_key },
|
|
||||||
{ "result", "LESS" },
|
|
||||||
{ "mod_revision", child_cfg->mod_revision+1 },
|
|
||||||
},
|
|
||||||
json11::Json::object {
|
|
||||||
{ "target", "MOD" },
|
|
||||||
{ "key", target_cfg_key },
|
|
||||||
{ "result", "LESS" },
|
|
||||||
{ "mod_revision", target_cfg->mod_revision+1 },
|
|
||||||
},
|
|
||||||
} },
|
|
||||||
{ "success", json11::Json::array {
|
|
||||||
json11::Json::object {
|
|
||||||
{ "request_delete_range", json11::Json::object {
|
|
||||||
{ "key", child_cfg_key },
|
|
||||||
} },
|
|
||||||
{ "request_put", json11::Json::object {
|
|
||||||
{ "key", target_cfg_key },
|
|
||||||
{ "value", base64_encode(json11::Json(new_cfg).dump()) },
|
|
||||||
} }
|
|
||||||
},
|
|
||||||
} },
|
|
||||||
}, ETCD_SLOW_TIMEOUT, [this, target_name, child_name](std::string err, json11::Json res)
|
}, ETCD_SLOW_TIMEOUT, [this, target_name, child_name](std::string err, json11::Json res)
|
||||||
{
|
{
|
||||||
parent->waiting--;
|
parent->waiting--;
|
||||||
|
@ -396,7 +426,10 @@ resume_9:
|
||||||
}
|
}
|
||||||
if (!res["succeeded"].bool_value())
|
if (!res["succeeded"].bool_value())
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Layer %s or %s configuration was modified during renaming\n", target_name.c_str(), child_name.c_str());
|
fprintf(
|
||||||
|
stderr, "Parent (%s), child (%s), or one of its children"
|
||||||
|
" configuration was modified during rename\n", target_name.c_str(), child_name.c_str()
|
||||||
|
);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
printf("Layer %s renamed to %s\n", target_name.c_str(), child_name.c_str());
|
printf("Layer %s renamed to %s\n", target_name.c_str(), child_name.c_str());
|
||||||
|
@ -414,9 +447,11 @@ resume_9:
|
||||||
}
|
}
|
||||||
inode_config_t *cur_cfg = &cur_cfg_it->second;
|
inode_config_t *cur_cfg = &cur_cfg_it->second;
|
||||||
std::string cur_name = cur_cfg->name;
|
std::string cur_name = cur_cfg->name;
|
||||||
std::string cur_cfg_key = base64_encode(parent->cli->st_cli.etcd_prefix+
|
std::string cur_cfg_key = base64_encode(
|
||||||
|
parent->cli->st_cli.etcd_prefix+
|
||||||
"/config/inode/"+std::to_string(INODE_POOL(cur))+
|
"/config/inode/"+std::to_string(INODE_POOL(cur))+
|
||||||
"/"+std::to_string(INODE_NO_POOL(cur)));
|
"/"+std::to_string(INODE_NO_POOL(cur))
|
||||||
|
);
|
||||||
parent->waiting++;
|
parent->waiting++;
|
||||||
parent->cli->st_cli.etcd_txn(json11::Json::object {
|
parent->cli->st_cli.etcd_txn(json11::Json::object {
|
||||||
{ "compare", json11::Json::array {
|
{ "compare", json11::Json::array {
|
||||||
|
@ -432,6 +467,9 @@ resume_9:
|
||||||
{ "request_delete_range", json11::Json::object {
|
{ "request_delete_range", json11::Json::object {
|
||||||
{ "key", cur_cfg_key },
|
{ "key", cur_cfg_key },
|
||||||
} },
|
} },
|
||||||
|
{ "request_delete_range", json11::Json::object {
|
||||||
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/index/image/"+cur_name) },
|
||||||
|
} },
|
||||||
},
|
},
|
||||||
} },
|
} },
|
||||||
}, ETCD_SLOW_TIMEOUT, [this, cur_name](std::string err, json11::Json res)
|
}, ETCD_SLOW_TIMEOUT, [this, cur_name](std::string err, json11::Json res)
|
||||||
|
|
|
@ -765,3 +765,22 @@ void etcd_state_client_t::close_watch(inode_watch_t* watch)
|
||||||
}
|
}
|
||||||
delete watch;
|
delete watch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json11::Json::object & etcd_state_client_t::serialize_inode_cfg(inode_config_t *cfg)
|
||||||
|
{
|
||||||
|
json11::Json::object new_cfg = json11::Json::object {
|
||||||
|
{ "name", cfg->name },
|
||||||
|
{ "size", cfg->size },
|
||||||
|
};
|
||||||
|
if (cfg->parent_id)
|
||||||
|
{
|
||||||
|
if (INODE_POOL(cfg->num) != INODE_POOL(cfg->parent_id))
|
||||||
|
new_cfg["parent_pool"] = (uint64_t)INODE_POOL(cfg->parent_id);
|
||||||
|
new_cfg["parent_id"] = (uint64_t)INODE_NO_POOL(cfg->parent_id);
|
||||||
|
}
|
||||||
|
if (cfg->readonly)
|
||||||
|
{
|
||||||
|
new_cfg["readonly"] = true;
|
||||||
|
}
|
||||||
|
return new_cfg;
|
||||||
|
}
|
||||||
|
|
|
@ -99,6 +99,7 @@ public:
|
||||||
std::function<void(pool_id_t, pg_num_t)> on_change_pg_history_hook;
|
std::function<void(pool_id_t, pg_num_t)> on_change_pg_history_hook;
|
||||||
std::function<void(osd_num_t)> on_change_osd_state_hook;
|
std::function<void(osd_num_t)> on_change_osd_state_hook;
|
||||||
|
|
||||||
|
json11::Json::object & serialize_inode_cfg(inode_config_t *cfg);
|
||||||
etcd_kv_t parse_etcd_kv(const json11::Json & kv_json);
|
etcd_kv_t parse_etcd_kv(const json11::Json & kv_json);
|
||||||
void etcd_call(std::string api, json11::Json payload, int timeout, std::function<void(std::string, json11::Json)> callback);
|
void etcd_call(std::string api, json11::Json payload, int timeout, std::function<void(std::string, json11::Json)> callback);
|
||||||
void etcd_txn(json11::Json txn, int timeout, std::function<void(std::string, json11::Json)> callback);
|
void etcd_txn(json11::Json txn, int timeout, std::function<void(std::string, json11::Json)> callback);
|
||||||
|
|
Loading…
Reference in New Issue