/* * Copyright 2012, The Android Open Source Project * * 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. */ #ifndef BCC_SUPPORT_FILE_BASE_H #define BCC_SUPPORT_FILE_BASE_H #include <fcntl.h> #include <string> #include <llvm/Support/system_error.h> namespace android { class FileMap; } namespace bcc { class FileBase { public: enum OpenModeEnum { kReadMode = 1 << 0, kWriteMode = 1 << 1, kReadWriteMode = (kReadMode | kWriteMode), }; enum FlagEnum { // The openning file is a binary file. kBinary = 1 << 0, // The openning file will be truncated to length 0. kTruncate = 1 << 1, // The openning file will put its file pointer to the end of the file before // each write. kAppend = 1 << 2, }; enum LockModeEnum { // The shared resource behind the Stream locked in ReadLock mode can be // locked by other processes at the same time. kReadLock, // The shared resource behind the Stream locked in WriteLock mode can only // be locked by one process. It's exclusive. That is, the shared resource // cannot have both ReadLock and WriteLock simultaneously. kWriteLock }; // Default configuration to the lock(). enum { kDefaultMaxRetryLock = 4, kDefaultRetryLockInterval = 200000UL, }; protected: // Grant direct access of the internal file descriptor to the sub-class and // error message such that they can implement their own I/O functionality. int mFD; llvm::error_code mError; private: std::string mName; // The 2nd argument to the POSIX open(). unsigned mOpenFlags; // True true if we should call unlock() in destructor. bool mShouldUnlock; // Open mName with flag mOpenFlags (using POSIX open().) bool open(); // Return true if mFD is the corresponded file descriptor to the file named // mName on the filesystem. This check may returns failed, for example, // someone re-create the file with the same name after we openning the file. bool checkFileIntegrity(); inline bool reopen() { // It's a private method, and all its callers are the few that can invoke it. // That is, the pre-condition will be checked by the caller. Therefore, we don't // need to check it again in reopen(). close(); return open(); } private: FileBase(FileBase &); // Do not implement. void operator=(const FileBase &); // Do not implement. protected: // pOpenFlags is the 2nd argument to the POSIX open(). pFlags are the flags to // FileBase. It's a bit set composed by the value defined in // FileBase::FlagEnum. FileBase(const std::string &pFilename, unsigned pOpenFlags, unsigned pFlags); void detectError(); public: // Lock the file descriptor in given pMode. If pNonblocking is true, the lock // request issued will return immediately when the shared resource is locked. // In this case, it retries pMaxRetry times, each wait pRetryInterval (in // usecs) before the previous retry getting done. // // Only file is allowed to use this API. bool lock(enum LockModeEnum pMode, bool pNonblocking = true, unsigned pMaxRetry = kDefaultMaxRetryLock, useconds_t pRetryInterval = kDefaultRetryLockInterval); void unlock(); // Map the file content to the memory. // // One who gets non-null android::FileMap returned from this API is responsible // for destroying it after the use. android::FileMap *createMap(off_t pOffset, size_t pLength, bool pIsReadOnly); size_t getSize(); off_t seek(off_t pOffset); off_t tell(); inline bool hasError() const { return (mError.value() != llvm::errc::success); } inline const llvm::error_code &getError() const { return mError; } // The return value of llvm::error_code::message() is obtained upon the call // and is passed by value (that is, it's not a member of llvm::error_code.) inline std::string getErrorMessage() const { return mError.message(); } inline const std::string &getName() const { return mName; } void close(); virtual ~FileBase(); }; } // end namespace bcc #endif // BCC_SUPPORT_FILE_BASE_H