⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kfsops.cc

📁 nandflash文件系统源代码
💻 CC
📖 第 1 页 / 共 2 页
字号:
/*! * $Id: kfsops.cc 232 2009-01-01 20:40:09Z lohitvijayarenu $  * * \file kfsops.cc * \brief KFS file system operations. * \author Blake Lewis and Sriram Rao * * Copyright 2008 Quantcast Corp. * Copyright 2006-2008 Kosmix Corp. * * This file is part of Kosmos File System (KFS). * * Licensed under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */#include "kfstypes.h"#include "kfstree.h"#include "util.h"#include "LayoutManager.h"#include <algorithm>#include <functional>#include <boost/lexical_cast.hpp>#include "common/log.h"#include "common/config.h"using std::mem_fun;using std::for_each;using std::find_if;using std::lower_bound;using std::cout;using std::endl;using namespace KFS;const string DUMPSTERDIR("dumpster");/*! * \brief Make a dumpster directory into which we can rename busy * files.  When the file is non-busy, it is nuked from the dumpster. */voidKFS::makeDumpsterDir(){	fid_t dummy = 0;	metatree.mkdir(ROOTFID, DUMPSTERDIR, &dummy);}/*! * \brief Cleanup the dumpster directory on startup.  Also, if * the dumpster doesn't exist, make one. */voidKFS::emptyDumpsterDir(){	makeDumpsterDir();	metatree.cleanupDumpster();}/*! * \brief check file name for legality * * Legal means nonempty and not containing any slashes. * * \param[in]	name to check * \return	true if name is legal */static boollegalname(const string name){	return (!name.empty() && name.find('/', 0) == string::npos);}/*! * \brief see whether path is absolute */static boolabsolute(const string path){	return (path[0] == '/');}/*! * \brief common code for create and mkdir * \param[in] dir	fid of parent directory * \param[in] fname	name of object to be created * \param[in] type	file or directory * \param[in] myID	fid of new object * \param[in] numReplicas desired degree of replication for file * * Create a directory entry and file attributes for the new object. * But don't create attributes for "." and ".." links, since these * share the directory's attributes. */intTree::link(fid_t dir, const string fname, FileType type, fid_t myID,		int16_t numReplicas){	assert(legalname(fname));	MetaDentry *dentry = new MetaDentry(dir, fname, myID);	insert(dentry);	if (fname != "." && fname != "..") {		MetaFattr *fattr = new MetaFattr(type, dentry->id(), numReplicas);		insert(fattr);	}	return 0;}/*! * \brief create a new file * \param[in] dir	file id of the parent directory * \param[in] fname	file name * \param[out] newFid	id of new file * \param[in] numReplicas desired degree of replication for file * \param[in] exclusive  model the O_EXCL flag of open() * * \return		status code (zero on success) */intTree::create(fid_t dir, const string &fname, fid_t *newFid,		int16_t numReplicas, bool exclusive){	if (!legalname(fname)) {		KFS_LOG_VA_WARN("Bad file name %s", fname.c_str());		return -EINVAL;	}	if (numReplicas <= 0) {		KFS_LOG_VA_DEBUG("Bad # of replicas (%d) for %s",				numReplicas, fname.c_str());		return -EINVAL;	}	MetaFattr *fa = lookup(dir, fname);	if (fa != NULL) {		if (fa->type != KFS_FILE)			return -EISDIR;		// Model O_EXECL behavior in create: if the file exists		// and exclusive is specified, fail the create.		if (exclusive)			return -EEXIST;		int status = remove(dir, fname);		if (status == -EBUSY) {			KFS_LOG_VA_INFO("Remove failed as file (%d:%s) is busy", dir, fname.c_str());			return status;		}		assert(status == 0);	}	if (*newFid == 0)		*newFid = fileID.genid();	return link(dir, fname, KFS_FILE, *newFid, numReplicas);}/*! * \brief common code for remove and rmdir * \param[in] dir	fid of parent directory * \param[in] fname	name of item to be removed * \param[in] fa	attributes for removed item * \pamam[in] save_fa	don't delete attributes if true * * save_fa prevents multiple deletions when removing * the "." and ".." links to a directory. */voidTree::unlink(fid_t dir, const string fname, MetaFattr *fa, bool save_fa){	MetaDentry dentry(dir, fname, fa->id());	int UNUSED_ATTR status = del(&dentry);	assert(status == 0);	if (!save_fa) {		status = del(fa);		assert(status == 0);	}}/*! * \brief remove a file * \param[in] dir	file id of the parent directory * \param[in] fname	file name * \return		status code (zero on success) */intTree::remove(fid_t dir, const string &fname){	MetaFattr *fa = lookup(dir, fname);	if (fa == NULL)		return -ENOENT;	if (fa->type != KFS_FILE)		return -EISDIR;	if (fa->chunkcount > 0) {		vector <MetaChunkInfo *> chunkInfo;		getalloc(fa->id(), chunkInfo);		assert(fa->chunkcount == (long long)chunkInfo.size());		if (gLayoutManager.IsValidLeaseIssued(chunkInfo)) {			// put the file into dumpster			int status = moveToDumpster(dir, fname);			KFS_LOG_VA_DEBUG("Moving %s to dumpster", fname.c_str());			return status;		}		// fire-away...		for_each(chunkInfo.begin(), chunkInfo.end(),			 mem_fun(&MetaChunkInfo::DeleteChunk));	}	unlink(dir, fname, fa, false);	return 0;}/*! * \brief create a new directory * \param[in] dir	file id of the parent directory * \param[in] dname	name of new directory * \param[out] newFid	id of new directory * \return		status code (zero on success) */intTree::mkdir(fid_t dir, const string &dname, fid_t *newFid){	if (!legalname(dname) && dir != ROOTFID && dname != "/")		return -EINVAL;	if (lookup(dir, dname) != NULL)		return -EEXIST;	fid_t myID = *newFid;	if (myID == 0)		myID = (dname == "/") ? dir : fileID.genid();	MetaDentry *dentry = new MetaDentry(dir, dname, myID);	MetaFattr *fattr = new MetaFattr(KFS_DIR, dentry->id(), 1);	insert(dentry);	insert(fattr);	int status = link(myID, ".", KFS_DIR, myID, 1);	if (status != 0)		panic("link(.)",false);	status = link(myID, "..", KFS_DIR, dir, 1);	if (status != 0)		panic("link(..)", false);	*newFid = myID;	return 0;}/*! * \brief check whether a directory is empty * \param[in] dir	file ID of the directory */boolTree::emptydir(fid_t dir){	vector <MetaDentry *> v;	readdir(dir, v);	return (v.size() == 2);}/*! * \brief remove a directory * \param[in] dir	file id of the parent directory * \param[in] dname	name of directory * \return		status code (zero on success) */intTree::rmdir(fid_t dir, const string &dname){	MetaFattr *fa = lookup(dir, dname);	if ((dir == ROOTFID) && (dname == DUMPSTERDIR)) {		KFS_LOG_VA_INFO(" Preventing removing dumpster (%s)",					dname.c_str());		return -EPERM;	}	if (fa == NULL)		return -ENOENT;	if (fa->type != KFS_DIR)		return -ENOTDIR;	if (dname == "." || dname == "..")		return -EPERM;	fid_t myID = fa->id();	if (!emptydir(myID))		return -ENOTEMPTY;	unlink(myID, ".", fa, true);	unlink(myID, "..", fa, true);	unlink(dir, dname, fa, false);	return 0;}/*! * \brief return attributes for the specified object * \param[in] fid	the object's file id * \return		pointer to the attributes */MetaFattr *Tree::getFattr(fid_t fid){	const Key fkey(KFS_FATTR, fid);	Node *l = findLeaf(fkey);	return (l == NULL) ? NULL : l->extractMeta<MetaFattr>(fkey);}MetaDentry *Tree::getDentry(fid_t dir, const string &fname){	vector <MetaDentry *> v;	if (readdir(dir, v) != 0)		return NULL;	vector <MetaDentry *>::iterator d;	d = find_if(v.begin(), v.end(), DirMatch(fname));	return (d == v.end()) ? NULL : *d;}/* * Map from file id to its directory entry.  In the current instantation, this is SLOW: * we iterate over the leaves until we find the dentry.  This method is needed * for KFS fsck, where we want to map from a fid -> name to reconstruct the * pathname for the file for which we want to print info (such as, missing * block, has fewer replicas etc. * \param[in] fid	the object's file id * \return		pointer to the attributes */MetaDentry *Tree::getDentry(fid_t fid){	LeafIter li(metatree.firstLeaf(), 0);	Node *p = li.parent();	Meta *m = li.current();	MetaDentry *d = NULL;	while (m != NULL) {		if (m->id() == fid) {			d = dynamic_cast<MetaDentry *>(m);			if (d != NULL)				break;		}		li.next();		p = li.parent();		m = (p == NULL) ? NULL : li.current();	}	return d;}/* * Given a file-id, returns its fully qualified pathname.  This involves * recursively traversing the metatree until the root directory. */stringTree::getPathname(fid_t fid){	MetaDentry *d;	string s = "";	while (1) {		d = getDentry(fid);		if (d == NULL)			return "";		if (s == "")			s = d->getName();		else if (d->id() == ROOTFID) {			return "/" + s;		}		else			s = d->getName() + "/" + s;		fid = d->getDir();	}	return "";}/*! * \brief look up a file name and return its attributes * \param[in] dir	file id of the parent directory * \param[in] fname	file name that we are looking up * \return		file attributes or NULL if not found */MetaFattr *Tree::lookup(fid_t dir, const string &fname){	MetaDentry *d = getDentry(dir, fname);	if (d == NULL)		return NULL;	MetaFattr *fa = getFattr(d->id());	assert(fa != NULL);	return fa;}/*! * \brief repeatedly apply Tree::lookup to an entire path * \param[in] rootdir	file id of starting directory * \param[in] path	the path to look up * \return		attributes of the last component (or NULL) */MetaFattr *Tree::lookupPath(fid_t rootdir, const string &path){	string component;	bool isabs = absolute(path);	fid_t dir = (rootdir == 0 || isabs) ? ROOTFID : rootdir;	string::size_type cstart = isabs ? 1 : 0;	string::size_type slash = path.find('/', cstart);	if (path.size() == cstart)		return lookup(dir, "/");	while (slash != string::npos) {		component.assign(path, cstart, slash - cstart);		MetaFattr *fa = lookup(dir, component);		if (fa == NULL)			return NULL;		dir = fa->id();		cstart = slash + 1;		slash = path.find('/', cstart);	}	component.assign(path, cstart, path.size() - cstart);	return lookup(dir, component);}/*! * \brief read the contents of a directory * \param[in] dir	file id of directory * \param[out] v	vector of directory entries * \return		status code */intTree::readdir(fid_t dir, vector <MetaDentry *> &v){	const Key dkey(KFS_DENTRY, dir);	Node *l = findLeaf(dkey);	if (l == NULL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -