本文共 3212 字,大约阅读时间需要 10 分钟。
filestore的omap中会按照key-value的方式存储对象的属性信息,在ceph中按照key-value存储属性信息有三个版本,分别是levleDB/ROCKSDB/kineticstore/memDB,目前主要用的是rocksDB。这四部分的源码在src/kv中从其makefile中可以看到set(kv_srcs KeyValueDB.cc MemDB.cc RocksDBStore.cc)if (WITH_LEVELDB) list(APPEND kv_srcs LevelDBStore.cc)endif (WITH_LEVELDB)如果要使用levelDB的话,需要打开with_leveldb这个宏那ceph 到底是如何选择用哪个kv呢?在src/common/options.cc 中定义了一个filestore_omap_backend。可以看到默认用的是rocksdb Option("filestore_omap_backend", Option::TYPE_STR, Option::LEVEL_DEV) .set_default("rocksdb") .set_description(""),在filestore.cc 中的FileStore::mkfs() 函数中会有如下赋值 // superblock superblock.omap_backend = cct->_conf->filestore_omap_backend; ret = write_superblock(); if (ret < 0) { derr << __FUNC__ << ": write_superblock() failed: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } 根据superblock.omap_backend 这个值可以在filestore.cc中的int FileStore::mount() 函数中有如下的code。 KeyValueDB * omap_store = KeyValueDB::create(cct, superblock.omap_backend, omap_dir); if (omap_store == NULL) { derr << __FUNC__ << ": Error creating " << superblock.omap_backend << dendl; ret = -1; goto close_current_fd; }在这个create函数中就可以看到用的kv是哪个后端KeyValueDB *KeyValueDB::create(CephContext *cct, const string& type, const string& dir, void *p){#ifdef WITH_LEVELDB if (type == "leveldb") { return new LevelDBStore(cct, dir); }#endif#ifdef HAVE_KINETIC if (type == "kinetic" && cct->check_experimental_feature_enabled("kinetic")) { return new KineticStore(cct); }#endif#ifdef HAVE_LIBROCKSDB if (type == "rocksdb") { return new RocksDBStore(cct, dir, p); }#endif if ((type == "memdb") && cct->check_experimental_feature_enabled("memdb")) { return new MemDB(cct, dir, p); } return NULL;}从这里我们知道当前系统中所有的支持的kv的后端存储和我们当前的选择我们看看DBObjectmap中如何读取属性值int DBObjectMap::get_xattrs(const ghobject_t &oid, const set&to_get, map *out){#首先加锁,说明属性值可以被多个进程同时读取。 MapHeaderLock hl(this, oid); #根据oid找到对应的header,如果没有找到,则根据oid新建一个header Header header = lookup_map_header(hl, oid); if (!header) return -ENOENT; #根据header中的seq得到键值 return db->get(xattr_prefix(header), to_get, out);}其中string DBObjectMap::xattr_prefix(Header header){ return USER_PREFIX + header_key(header->seq) + XATTR_PREFIX;}其中header_key的定义如下:string DBObjectMap::header_key(uint64_t seq){ char buf[100]; snprintf(buf, sizeof(buf), "%.*" PRId64, (int)(2*sizeof(seq)), seq); return string(buf);}可见主要是对seq格式化成字符串输出其中USER_PREFIX 和 XATTR_PREFIX 是两个字符串定义如下:const string DBObjectMap::USER_PREFIX = "_USER_";const string DBObjectMap::XATTR_PREFIX = "_AXATTR_";从这里可以知道kv中的key主要是由seq决定的,而这里的seq是一个我们知道在get_xattrs 中首先会根据oid新建一个header,以header中的seq为key再保存value,所以seq也是在新建header时候赋值的,具体函数如下:DBObjectMap::Header DBObjectMap::_generate_new_header(const ghobject_t &oid, Header parent){#新建一个header Header header = Header(new _Header(), RemoveOnDelete(this)); #从这里可以知道header中的seq是由state赋值的,并且会一直递增 header->seq = state.seq++; if (parent) { header->parent = parent->seq; header->spos = parent->spos; } header->num_children = 1; header->oid = oid; assert(!in_use.count(header->seq)); in_use.insert(header->seq); write_state(); return header;}
转载地址:http://xcnmi.baihongyu.com/