diff options
author | randomdan <randomdan@localhost> | 2014-03-20 21:07:25 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2014-03-20 21:07:25 +0000 |
commit | 5780e0d6b8fb5c4269d224b865365a1c59afd38b (patch) | |
tree | 2fdef12c4a975d2b412b78d75654db6fab471379 /netfs/fuse | |
parent | Fix slice scanner and split .ice files back into logical blocks (diff) | |
download | netfs-5780e0d6b8fb5c4269d224b865365a1c59afd38b.tar.bz2 netfs-5780e0d6b8fb5c4269d224b865365a1c59afd38b.tar.xz netfs-5780e0d6b8fb5c4269d224b865365a1c59afd38b.zip |
Modularized interfaces for netfs
Diffstat (limited to 'netfs/fuse')
-rw-r--r-- | netfs/fuse/Jamfile.jam | 33 | ||||
-rw-r--r-- | netfs/fuse/fuse.cpp | 148 | ||||
-rw-r--r-- | netfs/fuse/fuse.h | 117 | ||||
-rw-r--r-- | netfs/fuse/fuseConfig.cpp | 29 | ||||
-rw-r--r-- | netfs/fuse/fuseConfig.h | 34 | ||||
-rw-r--r-- | netfs/fuse/fuseDirs.cpp | 103 | ||||
-rw-r--r-- | netfs/fuse/fuseFiles.cpp | 155 | ||||
-rw-r--r-- | netfs/fuse/fuseMisc.cpp | 110 | ||||
-rw-r--r-- | netfs/fuse/fuseSystem.cpp | 16 | ||||
-rw-r--r-- | netfs/fuse/pch.hpp | 13 |
10 files changed, 758 insertions, 0 deletions
diff --git a/netfs/fuse/Jamfile.jam b/netfs/fuse/Jamfile.jam new file mode 100644 index 0000000..873f67c --- /dev/null +++ b/netfs/fuse/Jamfile.jam @@ -0,0 +1,33 @@ +cpp-pch pch : pch.hpp : + <define>_FILE_OFFSET_BITS=64 + <include>../../libmisc + <include>../../libfusepp + <implicit-dependency>../ice//netfsComms + <library>../ice//netfsComms + <library>..//boost_thread + <library>..//fuse + <library>..//Ice + <library>..//libxml2 + ; + + +exe netfs : + pch + [ glob *.cpp ] + [ glob ../../libfusepp/fuse*.cpp ] + : + <define>_FILE_OFFSET_BITS=64 + <include>../../libmisc + <include>../../libfusepp + <implicit-dependency>../ice//netfsComms + <library>../ice//netfsComms + <library>../lib//netfsCommon + <library>..//boost_thread + <library>..//boost_system + <library>..//fuse + <library>..//Ice + <library>..//IceUtil + <library>..//pthread + <library>..//libxml2 + ; + diff --git a/netfs/fuse/fuse.cpp b/netfs/fuse/fuse.cpp new file mode 100644 index 0000000..e221cfd --- /dev/null +++ b/netfs/fuse/fuse.cpp @@ -0,0 +1,148 @@ +#include "pch.hpp" +#include <string.h> +#include <boost/foreach.hpp> +#include "fuse.h" + +NetFS::FuseApp::FuseApp(int & argc, char ** argv) : + _argc(argc), + _argv(argv), + openDirID(0), + openFileID(0) +{ +} + +NetFS::FuseApp::~FuseApp() +{ + volume->disconnect(); + if (ic) { + ic->destroy(); + } +} + +void * +NetFS::FuseApp::init(struct fuse_conn_info *) +{ + ic = Ice::initialize(_argc, _argv); + fc = FuseConfig::Load(configPath); + return NULL; +} + +int +NetFS::FuseApp::opt_parse(void *, const char * arg, int, struct fuse_args *) +{ + if (strncmp(arg, "--Ice.", 6) == 0) { + return 0; + } + else if (arg[0] == '-') { + return 1; + } + else if (exportName.empty()) { + const char * colon = strchr(arg, ':'); + exportName = colon + 1; + configPath.assign(arg, colon); + return 0; + } + else if (mountPoint.empty()) { + mountPoint = arg; + return 1; + } + return 1; +} + +void +NetFS::FuseApp::connectToService() +{ + if (!service) { + LOCK; + FuseConfig::ExportPtr e = fc->exports[exportName]; + const std::string & ep = *e->endpoints.begin(); + + service = NetFS::ServicePrx::checkedCast(ic->stringToProxy("Service:" + ep)); + if (!service) { + throw "Invalid service proxy"; + } + } +} + +void +NetFS::FuseApp::connectToVolume() +{ + if (!volume) { + volume = service->connect(exportName, "bar"); + if (!volume) { + throw "Invalid filesystem proxy"; + } + } +} + +void +NetFS::FuseApp::connectHandles() +{ + BOOST_FOREACH(const OpenFiles::value_type & of, openFiles) { + try { + of.second->remote->ice_ping(); + } + catch (const Ice::ObjectNotExistException &) { + of.second->remote = volume->open(reqEnv(), of.second->path, of.second->flags); + } + } + BOOST_FOREACH(const OpenDirs::value_type & of, openDirs) { + try { + of.second->remote->ice_ping(); + } + catch (const Ice::ObjectNotExistException &) { + of.second->remote = volume->opendir(reqEnv(), of.second->path); + } + } +} + +void +NetFS::FuseApp::verifyConnection() +{ + LOCK; + if (service) { + try { + service->ice_ping(); + } + catch (const Ice::Exception &) { + service = NULL; + } + } + if (volume) { + try { + volume->ice_ping(); + } + catch (const Ice::Exception &) { + volume = NULL; + } + } +} + +int +NetFS::FuseApp::onError(const std::exception & e) throw() +{ + if (dynamic_cast<const Ice::ObjectNotExistException *>(&e)) { + verifyConnection(); + connectToService(); + connectToVolume(); + connectHandles(); + return 0; + } + return FuseAppBase::onError(e); +} + +NetFS::ReqEnv +NetFS::FuseApp::reqEnv() +{ + connectToService(); + connectToVolume(); + struct fuse_context * c = fuse_get_context(); + return { uentries.getName(c->uid), gentries.getName(c->gid) }; +} + +int +main(int argc, char* argv[]) +{ + return FuseAppBase::run(argc, argv, new NetFS::FuseApp(argc, argv)); +} + diff --git a/netfs/fuse/fuse.h b/netfs/fuse/fuse.h new file mode 100644 index 0000000..033d7fa --- /dev/null +++ b/netfs/fuse/fuse.h @@ -0,0 +1,117 @@ +#ifndef FUSE_H +#define FUSE_H + +#include <boost/thread/shared_mutex.hpp> +#include <Ice/Ice.h> +#include <service.h> +#include "fuseapp.h" +#include "fuseConfig.h" +#include "entCache.h" +#include "intrusivePtrBase.h" + +#define LOCK boost::unique_lock<boost::shared_mutex> _lck(_lock) +#define SLOCK boost::shared_lock<boost::shared_mutex> _lck(_lock) + +namespace NetFS { + class FuseApp : public FuseAppBase { + private: + class OpenDir : public IntrusivePtrBase { + public: + OpenDir(DirectoryPrx remote, const std::string & path); + + DirectoryPrx remote; + const std::string path; + }; + typedef boost::intrusive_ptr<OpenDir> OpenDirPtr; + typedef std::map<int, OpenDirPtr> OpenDirs; + + class OpenFile : public IntrusivePtrBase { + public: + OpenFile(FilePrx remote, const std::string & path, int flags); + + FilePrx remote; + const std::string path; + const int flags; + }; + typedef boost::intrusive_ptr<OpenFile> OpenFilePtr; + typedef std::map<int, OpenFilePtr> OpenFiles; + + public: + FuseApp(int & argc, char ** argv); + ~FuseApp(); + + private: + void * init (struct fuse_conn_info * info); + int opt_parse(void *, const char * arg, int key, struct fuse_args *); + + void connectToService(); + void connectToVolume(); + void connectHandles(); + void verifyConnection(); + + public: + // misc + int access(const char * p, int a); + int getattr(const char * p, struct stat * s); + int fgetattr(const char *, struct stat *, struct fuse_file_info *); + int chmod(const char *, mode_t); + int chown(const char *, uid_t, gid_t); + int link(const char *, const char *); + int readlink(const char *, char *, size_t); + int rename(const char *, const char *); + int symlink(const char *, const char *); + int unlink(const char *); + int utimens(const char *, const struct timespec tv[2]); + // dirs + int opendir(const char * p, struct fuse_file_info * fi); + int releasedir(const char *, struct fuse_file_info * fi); + int readdir(const char *, void * buf, fuse_fill_dir_t filler, off_t, struct fuse_file_info * fi); + int mkdir(const char *, mode_t); + int rmdir(const char *); + // files + int open(const char * p, struct fuse_file_info * fi); + int create(const char *, mode_t, struct fuse_file_info *); + int release(const char *, struct fuse_file_info * fi); + int read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi); + int write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi); + int truncate(const char *, off_t); + int ftruncate(const char *, off_t, struct fuse_file_info *); + // fs + int statfs(const char *, struct statvfs *); + // stuff + int onError(const std::exception & err) throw(); + + private: + void setProxy(OpenFilePtr, uint64_t & fh); + OpenFilePtr getFileProxy(uint64_t localID) const; + void clearFileProxy(uint64_t localID); + + void setProxy(OpenDirPtr, uint64_t & fh); + OpenDirPtr getDirProxy(uint64_t localID) const; + void clearDirProxy(uint64_t localID); + + ReqEnv reqEnv(); + + int & _argc; + char ** _argv; + Ice::CommunicatorPtr ic; + FuseConfigPtr fc; + mutable boost::shared_mutex _lock; + + NetFS::VolumePrx volume; + NetFS::ServicePrx service; + + std::string mountPoint; + std::string exportName; + std::string configPath; + + UserEntCache uentries; + GroupEntCache gentries; + OpenDirs openDirs; + int openDirID; + OpenFiles openFiles; + int openFileID; + }; +} + +#endif diff --git a/netfs/fuse/fuseConfig.cpp b/netfs/fuse/fuseConfig.cpp new file mode 100644 index 0000000..168550e --- /dev/null +++ b/netfs/fuse/fuseConfig.cpp @@ -0,0 +1,29 @@ +#include "pch.hpp" +#include "fuseConfig.h" +#include <string.h> + +FuseConfigPtr +FuseConfig::Load(const std::string & path) +{ + xmlDoc * doc = xmlReadFile(path.c_str(), NULL, 0); + FuseConfigPtr dc = new FuseConfig(doc->children); + xmlFreeDoc(doc); + return dc; +} + +FuseConfig::FuseConfig(xmlNodePtr conf) +{ + foreachxml(exp, xmlGetNode(conf, "exports"), "export") { + ExportPtr e = new Export(exp); + exports[e->name] = e; + } +} + +FuseConfig::Export::Export(xmlNodePtr conf) : + name(xmlGetNodeValue(conf, "name")) +{ + foreachxml(ep, xmlGetNode(conf, "endpoints"), "endpoint") { + endpoints.insert(xmlGetNodeValue(ep)); + } +} + diff --git a/netfs/fuse/fuseConfig.h b/netfs/fuse/fuseConfig.h new file mode 100644 index 0000000..f33c8f7 --- /dev/null +++ b/netfs/fuse/fuseConfig.h @@ -0,0 +1,34 @@ +#ifndef FUSECONFIG_H +#define FUSECONFIG_H + +#include <string> +#include <map> +#include <set> +#include <intrusivePtrBase.h> +#include <boost/intrusive_ptr.hpp> +#include "xml.h" + +class FuseConfig : public virtual IntrusivePtrBase { + public: + class Export; + typedef boost::intrusive_ptr<Export> ExportPtr; + typedef std::map<std::string, ExportPtr> ExportMap; + class Export : public virtual IntrusivePtrBase { + public: + typedef std::set<std::string> Endpoints; + Export(xmlNodePtr); + + std::string name; + Endpoints endpoints; + }; + + FuseConfig(xmlNodePtr); + static boost::intrusive_ptr<FuseConfig> Load(const std::string & path); + + ExportMap exports; +}; +typedef boost::intrusive_ptr<FuseConfig> FuseConfigPtr; + +#endif + + diff --git a/netfs/fuse/fuseDirs.cpp b/netfs/fuse/fuseDirs.cpp new file mode 100644 index 0000000..fac70a6 --- /dev/null +++ b/netfs/fuse/fuseDirs.cpp @@ -0,0 +1,103 @@ +#include "pch.hpp" +#include "fuse.h" +#include "misc.h" + +NetFS::FuseApp::OpenDir::OpenDir(DirectoryPrx r, const std::string & p) : + remote(r), + path(p) +{ +} + +void +NetFS::FuseApp::setProxy(OpenDirPtr od, uint64_t & fh) +{ + LOCK; + while (openDirs.find(fh = ++openDirID) != openDirs.end()) ; + openDirs.insert({ fh, od }); +} + +NetFS::FuseApp::OpenDirPtr +NetFS::FuseApp::getDirProxy(uint64_t localID) const +{ + SLOCK; + OpenDirs::const_iterator i = openDirs.find(localID); + if (i != openDirs.end()) { + return i->second; + } + throw NetFS::SystemError(EBADF); +} + +void +NetFS::FuseApp::clearDirProxy(uint64_t localID) +{ + LOCK; + openDirs.erase(localID); +} + +int +NetFS::FuseApp::opendir(const char * p, struct fuse_file_info * fi) +{ + try { + auto remote = volume->opendir(reqEnv(), p); + setProxy(new OpenDir(remote, p), fi->fh); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::releasedir(const char *, struct fuse_file_info * fi) +{ + try { + auto remote = getDirProxy(fi->fh)->remote; + remote->close(); + clearDirProxy(fi->fh); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::readdir(const char *, void * buf, fuse_fill_dir_t filler, off_t, struct fuse_file_info * fi) +{ + try { + auto remote = getDirProxy(fi->fh)->remote; + NetFS::NameList ds = remote->readdir(); + BOOST_FOREACH(const auto & e, ds) { + filler(buf, e.c_str(), NULL, 0); + } + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::mkdir(const char * p, mode_t m) +{ + try { + volume->mkdir(reqEnv(), p, m); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::rmdir(const char * p) +{ + try { + volume->rmdir(reqEnv(), p); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp new file mode 100644 index 0000000..4a96e51 --- /dev/null +++ b/netfs/fuse/fuseFiles.cpp @@ -0,0 +1,155 @@ +#include "pch.hpp" +#include <string.h> +#include <typeConvert.h> +#include "fuse.h" + +NetFS::FuseApp::OpenFile::OpenFile(FilePrx r, const std::string & p, int f) : + remote(r), + path(p), + flags(f) +{ +} + +void +NetFS::FuseApp::setProxy(OpenFilePtr of, uint64_t & fh) +{ + LOCK; + while (openFiles.find(fh = ++openFileID) != openFiles.end()) ; + openFiles.insert({ fh, of }); +} + +NetFS::FuseApp::OpenFilePtr +NetFS::FuseApp::getFileProxy(uint64_t localID) const +{ + SLOCK; + OpenFiles::const_iterator i = openFiles.find(localID); + if (i != openFiles.end()) { + return i->second; + } + throw NetFS::SystemError(EBADF); +} + +void +NetFS::FuseApp::clearFileProxy(uint64_t localID) +{ + LOCK; + openFiles.erase(localID); +} + +int +NetFS::FuseApp::open(const char * p, struct fuse_file_info * fi) +{ + try { + auto remote = volume->open(reqEnv(), p, fi->flags); + setProxy(new OpenFile(remote, p, fi->flags), fi->fh); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::create(const char * p, mode_t m, struct fuse_file_info * fi) +{ + try { + auto remote = volume->create(reqEnv(), p, fi->flags, m); + setProxy(new OpenFile(remote, p, fi->flags), fi->fh); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::release(const char *, struct fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + remote->close(); + clearFileProxy(fi->fh); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + NetFS::Buffer data = remote->read(o, s); + memcpy(buf, &data.front(), data.size()); + return data.size(); + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + remote->write(o, s, NetFS::Buffer(buf, buf + s)); + return s; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::truncate(const char * p, off_t o) +{ + try { + volume->truncate(reqEnv(), p, o); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::ftruncate(const char *, off_t o, fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + remote->ftruncate(reqEnv(), o); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::fgetattr(const char *, struct stat * s, fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + *s << AttrSource { remote->fgetattr(reqEnv()), boost::bind(&UserEntCache::getID, &uentries, _1), boost::bind(&GroupEntCache::getID, &gentries, _1) }; + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::unlink(const char * p) +{ + try { + volume->unlink(reqEnv(), p); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + diff --git a/netfs/fuse/fuseMisc.cpp b/netfs/fuse/fuseMisc.cpp new file mode 100644 index 0000000..568cf52 --- /dev/null +++ b/netfs/fuse/fuseMisc.cpp @@ -0,0 +1,110 @@ +#include "pch.hpp" +#include "fuse.h" +#include <string.h> +#include <typeConvert.h> + +int +NetFS::FuseApp::access(const char * p, int a) +{ + return -volume->access(reqEnv(), p, a); +} + +int +NetFS::FuseApp::getattr(const char * p, struct stat * s) +{ + try { + *s << AttrSource { volume->getattr(reqEnv(), p), boost::bind(&UserEntCache::getID, &uentries, _1), boost::bind(&GroupEntCache::getID, &gentries, _1) }; + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::chmod(const char * p, mode_t m) +{ + try { + volume->chmod(reqEnv(), p, m); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::chown(const char * p, uid_t u, gid_t g) +{ + try { + volume->chown(reqEnv(), p, u, g); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::link(const char * p1, const char * p2) +{ + try { + volume->link(reqEnv(), p1, p2); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::symlink(const char * p1, const char * p2) +{ + try { + volume->symlink(reqEnv(), p1, p2); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::readlink(const char * p, char * p2, size_t s) +{ + try { + std::string l = volume->readlink(reqEnv(), p); + l.copy(p2, s); + p2[l.length()] = '\0'; + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::rename(const char * p1, const char * p2) +{ + try { + volume->rename(reqEnv(), p1, p2); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::utimens(const char * path, const struct timespec times[2]) +{ + try { + volume->utimens(reqEnv(), path, + times[0].tv_sec, times[0].tv_nsec, times[1].tv_sec, times[1].tv_nsec); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + diff --git a/netfs/fuse/fuseSystem.cpp b/netfs/fuse/fuseSystem.cpp new file mode 100644 index 0000000..0b29d86 --- /dev/null +++ b/netfs/fuse/fuseSystem.cpp @@ -0,0 +1,16 @@ +#include "pch.hpp" +#include <typeConvert.h> +#include "fuse.h" + +int +NetFS::FuseApp::statfs(const char * p, struct statvfs * vfs) +{ + try { + *vfs << volume->statfs(reqEnv(), p); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + diff --git a/netfs/fuse/pch.hpp b/netfs/fuse/pch.hpp new file mode 100644 index 0000000..7cb79ed --- /dev/null +++ b/netfs/fuse/pch.hpp @@ -0,0 +1,13 @@ +#ifdef BOOST_BUILD_PCH_ENABLED +#ifndef NETFS_FUSE_PCH +#define NETFS_FUSE_PCH + +#include "../lib/pch.hpp" +#include "../../libfusepp/fuseapp.h" +#include <fuse.h> + +#endif +#endif + + + |