From 8d1dd7a3dc8e882630f0f6d9be0192f70aa824b1 Mon Sep 17 00:00:00 2001 From: Avi Kivity <avi.kivity@gmail.com> Date: Mon, 31 Dec 2012 16:21:35 +0200 Subject: [PATCH] fs: directory entry cache Store directory entries in a hash table for future lookup. --- fs/bootfs.cc | 2 +- fs/bootfs.hh | 2 +- fs/fs.cc | 25 +++++++++++++++++++++++++ fs/fs.hh | 14 +++++++++++++- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/fs/bootfs.cc b/fs/bootfs.cc index 1b563fc44..8159f8d26 100644 --- a/fs/bootfs.cc +++ b/fs/bootfs.cc @@ -53,7 +53,7 @@ bootfs::dir::dir(bootfs& fs, std::string path) { } -fileref bootfs::dir::open(std::string name) +fileref bootfs::dir::do_open(std::string name) { return _fs.do_open(_path + name); } diff --git a/fs/bootfs.hh b/fs/bootfs.hh index a3d332eb7..63f29cdc8 100644 --- a/fs/bootfs.hh +++ b/fs/bootfs.hh @@ -33,7 +33,7 @@ private: class bootfs::dir : public ::dir { public: dir(bootfs& fs, std::string path); - virtual fileref open(std::string name); + virtual fileref do_open(std::string name); virtual uint64_t size(); virtual void read(void* buffer, uint64_t offset, uint64_t len); private: diff --git a/fs/fs.cc b/fs/fs.cc index 68c2af78c..2dab7d451 100644 --- a/fs/fs.cc +++ b/fs/fs.cc @@ -2,6 +2,18 @@ filesystem* rootfs; +namespace std { + +template <> +struct hash<file::cache_key> { + size_t operator()(file::cache_key k) const { + return reinterpret_cast<uintptr_t>(k.first.get()) + ^ std::hash<std::string>()(k.second); + } +}; + +} + file::file() : _refs(0) { @@ -43,8 +55,21 @@ fileref filesystem::open(std::string name) return d->open(name.substr(s, name.npos)); } +fileref dir::open(std::string name) +{ + cache_key key(this, name); + auto ret = _cache.find(key); + if (ret == _cache.end()) { + auto f = do_open(name); + ret = _cache.insert(cache_type::value_type(key, f)).first; + } + return ret->second; +} + dirref dir::subdir(std::string name) { // trivial implementation, can be overridden return boost::dynamic_pointer_cast<dir>(open(name)); } + +file::cache_type file::_cache; diff --git a/fs/fs.hh b/fs/fs.hh index 85d1ccc77..570f35ac9 100644 --- a/fs/fs.hh +++ b/fs/fs.hh @@ -4,6 +4,7 @@ #include <string> #include <cstdint> #include <boost/intrusive_ptr.hpp> +#include <unordered_map> class file; class dir; @@ -24,12 +25,23 @@ private: unsigned _refs; // FIXME: make atomic friend void intrusive_ptr_add_ref(file* f) { f->ref(); } friend void intrusive_ptr_release(file* f) { f->unref(); } + friend class dir; +private: + typedef std::pair<dirref, std::string> cache_key; + // FIXME: an intrusive container + typedef std::unordered_map<cache_key, fileref> cache_type; + static cache_type _cache; + friend struct std::hash<cache_key>; }; class dir : public file { public: - virtual fileref open(std::string name) = 0; + fileref open(std::string name); + virtual fileref do_open(std::string name) = 0; dirref subdir(std::string name); +private: + dirref _parent; + std::string _name; }; class filesystem { -- GitLab