/* * Copyright (c) 2013 by Felix Hupfeld. * * Licensed under the BSD License, see LICENSE file for details. * */ #ifndef CPP_INCLUDE_LIBXTREEMFS_OBJECT_CACHE_H_ #define CPP_INCLUDE_LIBXTREEMFS_OBJECT_CACHE_H_ #include #include #include #include #include #include #include "util/annotations.h" namespace boost { class condition_variable; } namespace xtreemfs { /** These are injected functions that provide object read and write * functionality for complete objects. */ typedef boost::function ObjectReaderFunction; typedef boost::function ObjectWriterFunction; class CachedObject { public: /** Create the object in ReadPending state. */ CachedObject(int object_no, int object_size); ~CachedObject(); /** Flush data and free memory. */ void FlushAndErase(const ObjectWriterFunction& writer) LOCKS_EXCLUDED(mutex_); /** Free memory without flushing to storage. */ void Drop() LOCKS_EXCLUDED(mutex_); int Read(int offset_in_object, char* buffer, int bytes_to_read, const ObjectReaderFunction& reader) LOCKS_EXCLUDED(mutex_); void Write(int offset_in_object, const char* buffer, int bytes_to_write, const ObjectReaderFunction& reader) LOCKS_EXCLUDED(mutex_); void Flush(const ObjectWriterFunction& writer) LOCKS_EXCLUDED(mutex_); void Truncate(int new_object_size) LOCKS_EXCLUDED(mutex_); uint64_t last_access() LOCKS_EXCLUDED(mutex_); bool is_dirty() LOCKS_EXCLUDED(mutex_); bool has_data() LOCKS_EXCLUDED(mutex_); private: /** Caller must hold mutex_ */ void DropLocked() EXCLUSIVE_LOCKS_REQUIRED(mutex_); void ReadInternal(boost::unique_lock& lock, const ObjectReaderFunction& reader) EXCLUSIVE_LOCKS_REQUIRED(mutex_); void WriteObjectToOSD(const ObjectWriterFunction& writer) EXCLUSIVE_LOCKS_REQUIRED(mutex_); /** Mutex that protects all non const data member. */ boost::mutex mutex_; std::deque read_queue_ GUARDED_BY(mutex_); const int object_no_; const int object_size_; /** Our buffer, always object_size_ large. */ boost::scoped_array data_ GUARDED_BY(mutex_); /** The last object has fewer bytes than object_size_. If data has not been fetched from the OSD yet, actual_size is -1. */ int actual_size_ GUARDED_BY(mutex_); /** Data is dirty and must be written back. */ bool is_dirty_ GUARDED_BY(mutex_); /** Timestamp of last access, for LRU expunge policy. */ uint64_t last_access_ GUARDED_BY(mutex_); /** Reading the data has failed */ bool read_has_failed_ GUARDED_BY(mutex_); }; class ObjectCache { public: ObjectCache(size_t max_objects, int object_size); ~ObjectCache(); /** Read within a specific object */ int Read(int object_no, int offset_in_object, char* buffer, int bytes_to_read, const ObjectReaderFunction& reader, const ObjectWriterFunction& writer) LOCKS_EXCLUDED(mutex_); /** Write within a specific object */ void Write(int object_no, int offset_in_object, const char* buffer, int bytes_to_write, const ObjectReaderFunction& reader, const ObjectWriterFunction& writer) LOCKS_EXCLUDED(mutex_); void Flush(const ObjectWriterFunction& writer) LOCKS_EXCLUDED(mutex_); void Truncate(int64_t new_size) LOCKS_EXCLUDED(mutex_); int object_size() const; private: CachedObject* LookupObject(int object_no, const ObjectWriterFunction& writer) LOCKS_EXCLUDED(mutex_); void EvictObjects(const ObjectWriterFunction& writer) EXCLUSIVE_LOCKS_REQUIRED(mutex_); /** Protects all non-const members of this class. */ boost::mutex mutex_; /** Map of object number to cached object. */ typedef std::map Cache; Cache cache_ GUARDED_BY(mutex_); /** Maximum number of objects to cache. */ const size_t max_objects_; const int object_size_; }; } // namespace xtreemfs #endif // CPP_INCLUDE_LIBXTREEMFS_OBJECT_CACHE_H_