/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2016 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
//------------------------------------------------------------------------------
//! @author Elvin-Alin Sindrilaru
//! @brief Class representing the container metadata
//------------------------------------------------------------------------------
#ifndef EOS_NS_CONTAINER_MD_HH
#define EOS_NS_CONTAINER_MD_HH
#include "namespace/interface/IContainerMD.hh"
#include "namespace/interface/IFileMD.hh"
#include "namespace/ns_quarkdb/flusher/MetadataFlusher.hh"
#include "proto/ContainerMd.pb.h"
#include "common/FutureWrapper.hh"
#include
#include
#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
EOSNSNAMESPACE_BEGIN
class IContainerMDSvc;
class IFileMDSvc;
//------------------------------------------------------------------------------
//! Class holding the metadata information concerning a single container
//------------------------------------------------------------------------------
class QuarkContainerMD : public IContainerMD
{
public:
//----------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------
QuarkContainerMD(IContainerMD::id_t id, IFileMDSvc* file_svc,
IContainerMDSvc* cont_svc);
//----------------------------------------------------------------------------
//! Constructor used for testing and dump command
//----------------------------------------------------------------------------
QuarkContainerMD(): pContSvc(nullptr), pFileSvc(nullptr), pFlusher(nullptr),
pQcl(nullptr), mClock(1) {}
//----------------------------------------------------------------------------
//! Destructor
//----------------------------------------------------------------------------
virtual ~QuarkContainerMD() {};
//----------------------------------------------------------------------------
//! Copy constructor
//----------------------------------------------------------------------------
QuarkContainerMD(const QuarkContainerMD& other);
//----------------------------------------------------------------------------
//! Virtual copy constructor
//----------------------------------------------------------------------------
virtual QuarkContainerMD* clone() const override;
//----------------------------------------------------------------------------
//! Virtual copy constructor
//----------------------------------------------------------------------------
void InheritChildren(const IContainerMD& other) override;
//----------------------------------------------------------------------------
//! Set services
//----------------------------------------------------------------------------
void setServices(IFileMDSvc* file_svc, IContainerMDSvc* cont_svc);
//----------------------------------------------------------------------------
//! Add container
//----------------------------------------------------------------------------
void addContainer(IContainerMD* container) override;
//----------------------------------------------------------------------------
//! Remove container
//----------------------------------------------------------------------------
void removeContainer(const std::string& name) override;
//----------------------------------------------------------------------------
//! Find subcontainer, asynchronous API
//----------------------------------------------------------------------------
folly::Future findContainerFut(const std::string& name)
override;
//----------------------------------------------------------------------------
//! Find subcontainer
//----------------------------------------------------------------------------
std::shared_ptr findContainer(const std::string& name) override;
//----------------------------------------------------------------------------
//! Find sub container and write lock it (returns nullptr in case the container is not found)
//----------------------------------------------------------------------------
IContainerMDWriteLockerPtr
findContainerWriteLocked(const std::string & name) override;
//----------------------------------------------------------------------------
//! Find sub container and read lock it (returns nullptr in case the container is not found)
//----------------------------------------------------------------------------
IContainerMDReadLockerPtr
findContainerReadLocked(const std::string & name) override;
//----------------------------------------------------------------------------
//! Find item
//----------------------------------------------------------------------------
folly::Future findItem(const std::string& name) override;
//----------------------------------------------------------------------------
//! Find item read locked
//----------------------------------------------------------------------------
FileOrContainerMDLocked findItemReadLocked(const std::string &name) override;
//----------------------------------------------------------------------------
//! Find item write locked
//----------------------------------------------------------------------------
FileOrContainerMDLocked findItemWriteLocked(const std::string & name) override;
//----------------------------------------------------------------------------
//! Get number of containers
//----------------------------------------------------------------------------
size_t getNumContainers() override;
//----------------------------------------------------------------------------
//! Add file
//----------------------------------------------------------------------------
void addFile(IFileMD* file) override;
//----------------------------------------------------------------------------
//! Remove file
//----------------------------------------------------------------------------
void removeFile(const std::string& name) override;
//----------------------------------------------------------------------------
//! Find file, asynchronous API.
//----------------------------------------------------------------------------
folly::Future findFileFut(const std::string& name) override;
//----------------------------------------------------------------------------
//! Find file
//----------------------------------------------------------------------------
IFileMDPtr findFile(const std::string& name) override;
//----------------------------------------------------------------------------
//! Find file and read lock it. Returns nullptr in case the file is not found
//----------------------------------------------------------------------------
std::unique_ptr findFileReadLocked(const std::string & name) override;
//----------------------------------------------------------------------------
//! Find file and write lock it. Returns nullptr in case the file is not found
//----------------------------------------------------------------------------
std::unique_ptr findFileWriteLocked(const std::string & name) override;
//----------------------------------------------------------------------------
//! Get number of files
//----------------------------------------------------------------------------
size_t getNumFiles() override;
//----------------------------------------------------------------------------
//! Get container id
//----------------------------------------------------------------------------
inline IContainerMD::id_t getId() const override
{
return runReadOp([this](){
return mCont.id();
});
}
//----------------------------------------------------------------------------
//! Get container identifier
//----------------------------------------------------------------------------
inline identifier_t
getIdentifier() const override
{
return identifier_t(getId());
}
//----------------------------------------------------------------------------
//! Get parent id
//----------------------------------------------------------------------------
inline IContainerMD::id_t
getParentId() const override
{
return runReadOp([this](){
return mCont.parent_id();
});
}
//----------------------------------------------------------------------------
//! Set parent id
//----------------------------------------------------------------------------
void
setParentId(IContainerMD::id_t parentId) override
{
runWriteOp([this,parentId](){
mCont.set_parent_id(parentId);
});
}
//----------------------------------------------------------------------------
//! Get the flags
//----------------------------------------------------------------------------
inline uint16_t
getFlags() const override
{
return runReadOp([this](){
return mCont.flags();
});
}
//----------------------------------------------------------------------------
//! Set flags
//----------------------------------------------------------------------------
virtual void setFlags(uint16_t flags) override
{
runWriteOp([this,flags](){
mCont.set_flags(0x00ff & flags);
});
}
//----------------------------------------------------------------------------
//! Set creation time
//----------------------------------------------------------------------------
void setCTime(ctime_t ctime) override;
//----------------------------------------------------------------------------
//! Set creation time to now
//----------------------------------------------------------------------------
void setCTimeNow() override;
//----------------------------------------------------------------------------
//! Get creation time
//----------------------------------------------------------------------------
void getCTime(ctime_t& ctime) const override;
//----------------------------------------------------------------------------
//! Set creation time
//----------------------------------------------------------------------------
void setMTime(mtime_t mtime) override;
//----------------------------------------------------------------------------
//! Set creation time to now
//----------------------------------------------------------------------------
void setMTimeNow() override;
//----------------------------------------------------------------------------
//! Get modification time
//----------------------------------------------------------------------------
void getMTime(mtime_t& mtime) const override;
//----------------------------------------------------------------------------
//! Set propagated modification time (if newer)
//----------------------------------------------------------------------------
bool setTMTime(tmtime_t tmtime) override;
//----------------------------------------------------------------------------
//! Set propagated modification time to now
//----------------------------------------------------------------------------
void setTMTimeNow() override;
//----------------------------------------------------------------------------
//! Get propagated modification time
//----------------------------------------------------------------------------
void getTMTime(tmtime_t& tmtime) override;
//----------------------------------------------------------------------------
//! Trigger an mtime change event
//----------------------------------------------------------------------------
void notifyMTimeChange(IContainerMDSvc* containerMDSvc) override;
//----------------------------------------------------------------------------
//! Get tree size
//----------------------------------------------------------------------------
inline uint64_t
getTreeSize() const override
{
return runReadOp([this](){
return mCont.tree_size();
});
}
//----------------------------------------------------------------------------
//! Set tree size
//----------------------------------------------------------------------------
inline void
setTreeSize(uint64_t treesize) override
{
runWriteOp([this,treesize](){
mCont.set_tree_size(treesize);
});
}
//----------------------------------------------------------------------------
//! Update to tree size
//----------------------------------------------------------------------------
uint64_t updateTreeSize(int64_t delta) override;
//----------------------------------------------------------------------------
//! Get name
//----------------------------------------------------------------------------
inline const std::string&
getName() const override
{
//Specify the return type of the lambda to be a const string ref otherwise
//we will return a reference to the copy of the string returned by the lambda... (dangling reference when used)
return runReadOp([this]() -> const std::string & {
return mCont.name();
});
}
//----------------------------------------------------------------------------
//! Set name
//----------------------------------------------------------------------------
void setName(const std::string& name) override;
//----------------------------------------------------------------------------
//! Get uid
//----------------------------------------------------------------------------
inline uid_t
getCUid() const override
{
return runReadOp([this](){
return mCont.uid();
});
}
//----------------------------------------------------------------------------
//! Set uid
//----------------------------------------------------------------------------
inline void
setCUid(uid_t uid) override
{
runWriteOp([this,uid](){
mCont.set_uid(uid);
});
}
//----------------------------------------------------------------------------
//! Get gid
//----------------------------------------------------------------------------
inline gid_t
getCGid() const override
{
return runReadOp([this](){
return mCont.gid();
});
}
//----------------------------------------------------------------------------
//! Set gid
//----------------------------------------------------------------------------
inline void
setCGid(gid_t gid) override
{
runWriteOp([this,gid](){
mCont.set_gid(gid);
});
}
//----------------------------------------------------------------------------
//! Get cloneId
//----------------------------------------------------------------------------
inline time_t
getCloneId() const override
{
return runReadOp([this](){
return mCont.cloneid();
});
}
//----------------------------------------------------------------------------
//! Set cloneId
//----------------------------------------------------------------------------
inline void
setCloneId(time_t id) override
{
runWriteOp([this,id](){
mCont.set_cloneid(id);
});
}
//----------------------------------------------------------------------------
//! Get cloneFST
//----------------------------------------------------------------------------
inline const std::string
getCloneFST() const override
{
return runReadOp([this](){
return mCont.clonefst();
});
}
//----------------------------------------------------------------------------
//! Set cloneFST
//----------------------------------------------------------------------------
void setCloneFST(const std::string& data) override
{
runWriteOp([this,data](){
mCont.set_clonefst(data);
});
}
//----------------------------------------------------------------------------
//! Get mode
//----------------------------------------------------------------------------
inline mode_t
getMode() const override
{
return runReadOp([this](){
return mCont.mode();
});
}
//----------------------------------------------------------------------------
//! Set mode
//----------------------------------------------------------------------------
inline void
setMode(mode_t mode) override
{
runWriteOp([this,mode](){
mCont.set_mode(mode);
});
}
//----------------------------------------------------------------------------
//! Add extended attribute
//----------------------------------------------------------------------------
void
setAttribute(const std::string& name, const std::string& value) override
{
runWriteOp([this,name,value](){
(*mCont.mutable_xattrs())[name] = value;
});
}
//----------------------------------------------------------------------------
//! Remove attribute
//----------------------------------------------------------------------------
void removeAttribute(const std::string& name) override;
//----------------------------------------------------------------------------
//! Check if the attribute exist
//----------------------------------------------------------------------------
bool
hasAttribute(const std::string& name) const override
{
return runReadOp([this,name](){
return (mCont.xattrs().find(name) != mCont.xattrs().end());
});
}
//----------------------------------------------------------------------------
//! Return number of attributes
//----------------------------------------------------------------------------
size_t
numAttributes() const override
{
return runReadOp([this](){
return mCont.xattrs().size();
});
}
//----------------------------------------------------------------------------
// Get the attribute
//----------------------------------------------------------------------------
std::string getAttribute(const std::string& name) const override;
//----------------------------------------------------------------------------
//! Get map copy of the extended attributes
//!
//! @return std::map containing all the extended attributes
//----------------------------------------------------------------------------
XAttrMap getAttributes() const override;
//------------------------------------------------------------------------------
//! Check the access permissions
//!
//! @return true if all the requested rights are granted, false otherwise
//------------------------------------------------------------------------------
bool access(uid_t uid, gid_t gid, int flags = 0) override;
//----------------------------------------------------------------------------
//! Serialize the object to a buffer
//----------------------------------------------------------------------------
void serialize(Buffer& buffer) override;
//----------------------------------------------------------------------------
//! Load children of container
//----------------------------------------------------------------------------
void loadChildren();
//----------------------------------------------------------------------------
//! Deserialize the class to a buffer and load its children
//----------------------------------------------------------------------------
void deserialize(Buffer& buffer) override;
//----------------------------------------------------------------------------
//! Initialize, and inject children
//----------------------------------------------------------------------------
void initialize(eos::ns::ContainerMdProto&& proto,
IContainerMD::FileMap&& fileMap, IContainerMD::ContainerMap&& containerMap);
//----------------------------------------------------------------------------
//! Initialize, without loading children
//----------------------------------------------------------------------------
void initializeWithoutChildren(eos::ns::ContainerMdProto&& proto);
//----------------------------------------------------------------------------
//! Get value tracking changes to the metadata object
//----------------------------------------------------------------------------
virtual uint64_t getClock() const override
{
return runReadOp([this](){
return mClock;
});
}
//----------------------------------------------------------------------------
//! Get env representation of the container object
//!
//! @param env string where representation is stored
//! @param escapeAnd if true escape & with #AND# ...
//----------------------------------------------------------------------------
void getEnv(std::string& env, bool escapeAnd = false) override;
//----------------------------------------------------------------------------
//! Get a copy of ContainerMap
//----------------------------------------------------------------------------
IContainerMD::ContainerMap copyContainerMap() const override;
//----------------------------------------------------------------------------
//! Get a copy of FileMap
//----------------------------------------------------------------------------
IContainerMD::FileMap copyFileMap() const override;
private:
FRIEND_TEST(VariousTests, EtagFormattingContainer);
//----------------------------------------------------------------------------
//! Get propagated modification time, no locks
//----------------------------------------------------------------------------
void getTMTimeNoLock(tmtime_t& tmtime);
//----------------------------------------------------------------------------
//! Get creation time, no locks
//----------------------------------------------------------------------------
void getCTimeNoLock(ctime_t& ctime) const;
//----------------------------------------------------------------------------
//! Get modification time, no locks
//----------------------------------------------------------------------------
void getMTimeNoLock(mtime_t& mtime) const;
//----------------------------------------------------------------------------
//! Get iterator to the begining of the subcontainers map
//----------------------------------------------------------------------------
eos::IContainerMD::ContainerMap::const_iterator
subcontainersBegin() override
{
// No lock here, only ContainerMapIterator can call us, which locks the mutex.
return mSubcontainers->begin();
}
//----------------------------------------------------------------------------
//! Get iterator to the end of the subcontainers map
//----------------------------------------------------------------------------
virtual eos::IContainerMD::ContainerMap::const_iterator
subcontainersEnd() override
{
// No lock here, only ContainerMapIterator can call us, which locks the mutex.
return mSubcontainers->end();
}
//----------------------------------------------------------------------------
//! Get generation value to check iterator validity
//----------------------------------------------------------------------------
virtual uint64_t getContainerMapGeneration() override
{
const uint64_t bc = mSubcontainers->bucket_count();
return reinterpret_cast(&*mSubcontainers->end()) ^
((bc << 48) | (bc >> 16));
}
//----------------------------------------------------------------------------
//! Get iterator to the begining of the files map
//----------------------------------------------------------------------------
virtual eos::IContainerMD::FileMap::const_iterator
filesBegin() override
{
// No lock here, only FileMapIterator can call us, which locks the mutex.
return mFiles->begin();
}
//----------------------------------------------------------------------------
//! Get iterator to the end of the files map
//----------------------------------------------------------------------------
virtual eos::IContainerMD::FileMap::const_iterator
filesEnd() override
{
// No lock here, only FileMapIterator can call us, which locks the mutex.
return mFiles->end();
}
//----------------------------------------------------------------------------
//! Get generation value to check iterator validity
//----------------------------------------------------------------------------
virtual uint64_t getFileMapGeneration() override
{
const uint64_t bc = mFiles->bucket_count();
return reinterpret_cast(&*mFiles->end()) ^
((bc << 48) | (bc >> 16));
}
eos::ns::ContainerMdProto mCont; ///< Protobuf container representation
IContainerMDSvc* pContSvc = nullptr; ///< Container metadata service
IFileMDSvc* pFileSvc = nullptr; ///< File metadata service
MetadataFlusher* pFlusher = nullptr; ///< Metadata flusher object
qclient::QClient* pQcl; ///< QClient object
std::string pFilesKey; ///< Map files key
std::string pDirsKey; ///< Map dir key
uint64_t mClock; ///< Value tracking changes
common::FutureWrapper mSubcontainers;
common::FutureWrapper mFiles;
};
EOSNSNAMESPACE_END
#endif // __EOS_NS_CONTAINER_MD_HH__