uint64_t expected_num_objs ///< [in] expected number of objects this collection has
) { ceph_abort(); return 0; }
- virtual int apply_layout_settings() { ceph_abort(); return 0; }
+ virtual int apply_layout_settings(int target_level) { ceph_abort(); return 0; }
/// Read index-wide settings (should be called after construction)
virtual int read_settings() { return 0; }
return res;
}
-int FileStore::apply_layout_settings(const coll_t &cid)
+int FileStore::apply_layout_settings(const coll_t &cid, int target_level)
{
- dout(20) << __FUNC__ << ": " << cid << dendl;
+ dout(20) << __FUNC__ << ": " << cid << " target level: "
+ << target_level << dendl;
Index index;
int r = get_index(cid, &index);
if (r < 0) {
return r;
}
- return index->apply_layout_settings();
+ return index->apply_layout_settings(target_level);
}
void dump_stop();
void dump_transactions(vector<Transaction>& ls, uint64_t seq, OpSequencer *osr);
- virtual int apply_layout_settings(const coll_t &cid);
+ virtual int apply_layout_settings(const coll_t &cid, int target_level);
private:
void _inject_failure();
&mkdirred);
}
-int HashIndex::split_dirs(const vector<string> &path) {
- dout(20) << __func__ << " " << path << dendl;
+int HashIndex::split_dirs(const vector<string> &path, int target_level) {
+ dout(20) << __func__ << " " << path << " target level: "
+ << target_level << dendl;
subdir_info_s info;
int r = get_info(path, &info);
if (r < 0) {
return r;
}
- if (must_split(info)) {
+ if (must_split(info, target_level)) {
dout(1) << __func__ << " " << path << " has " << info.objs
- << " objects, starting split." << dendl;
+ << " objects, " << info.hash_level
+ << " level, starting split." << dendl;
r = initiate_split(path, info);
if (r < 0) {
dout(10) << "error initiating split on " << path << ": "
it != subdirs.end(); ++it) {
vector<string> subdir_path(path);
subdir_path.push_back(*it);
- r = split_dirs(subdir_path);
+ r = split_dirs(subdir_path, target_level);
if (r < 0) {
return r;
}
return r;
}
-int HashIndex::apply_layout_settings() {
+int HashIndex::apply_layout_settings(int target_level) {
vector<string> path;
dout(10) << __func__ << " split multiple = " << split_multiplier
<< " merge threshold = " << merge_threshold
<< " split rand factor = " << cct->_conf->filestore_split_rand_factor
+ << " target level = " << target_level
<< dendl;
int r = write_settings();
if (r < 0)
return r;
- return split_dirs(path);
+ return split_dirs(path, target_level);
}
int HashIndex::_init() {
info.subdirs == 0);
}
-bool HashIndex::must_split(const subdir_info_s &info) {
+bool HashIndex::must_split(const subdir_info_s &info, int target_level) {
+ // target_level is used for ceph-objectstore-tool to split dirs offline.
+ // if it is set (defalult is 0) and current hash level < target_level,
+ // this dir would be split no matters how many objects it has.
return (info.hash_level < (unsigned)MAX_HASH_LEVEL &&
- info.objs > ((unsigned)(abs(merge_threshold) * split_multiplier + settings.split_rand_factor) * 16));
-
+ ((target_level > 0 && info.hash_level < (unsigned)target_level) ||
+ (info.objs > ((unsigned)(abs(merge_threshold) * split_multiplier + settings.split_rand_factor) * 16))));
}
int HashIndex::initiate_merge(const vector<string> &path, subdir_info_s info) {
) override;
/// @see CollectionIndex
- int apply_layout_settings() override;
+ int apply_layout_settings(int target_level) override;
protected:
int _init() override;
/// Encapsulates logic for when to merge.
bool must_split(
- const subdir_info_s &info ///< [in] Info to check
+ const subdir_info_s &info, ///< [in] Info to check
+ int target_level = 0
); /// @return True if info must be split, False otherwise
/// Initiates merge
int recursive_create_path(vector<string>& path, int level);
/// split each dir below the given path
- int split_dirs(const vector<string> &path);
+ int split_dirs(const vector<string> &path, int target_level = 0);
int write_settings();
};
}
int apply_layout_settings(ObjectStore *os, const OSDSuperblock &superblock,
- const string &pool_name, const spg_t &pgid, bool dry_run)
+ const string &pool_name, const spg_t &pgid, bool dry_run,
+ int target_level)
{
int r = 0;
cerr << "Would apply layout settings to " << coll << std::endl;
} else {
cerr << "Finished " << done << "/" << total << " collections" << "\r";
- r = fs->apply_layout_settings(coll);
+ r = fs->apply_layout_settings(coll, target_level);
if (r < 0) {
cerr << "Error applying layout settings to " << coll << std::endl;
return r;
positional.add_options()
("object", po::value<string>(&object), "'' for pgmeta_oid, object name or ghobject in json")
("objcmd", po::value<string>(&objcmd), "command [(get|set)-bytes, (get|set|rm)-(attr|omap), (get|set)-omaphdr, list-attrs, list-omap, remove]")
- ("arg1", po::value<string>(&arg1), "arg1 based on cmd")
+ ("arg1", po::value<string>(&arg1), "arg1 based on cmd, "
+ "for apply-layout-settings: target hash level split to")
("arg2", po::value<string>(&arg2), "arg2 based on cmd")
;
}
if (op == "apply-layout-settings") {
- ret = apply_layout_settings(fs, superblock, pool, pgid, dry_run);
+ int target_level = 0;
+ if (vm.count("arg1") && isdigit(arg1[0])) {
+ target_level = atoi(arg1.c_str());
+ }
+ ret = apply_layout_settings(fs, superblock, pool, pgid, dry_run, target_level);
goto out;
}