jens@0: /*
jens@0:  *  File.h
jens@0:  *  Ottoman
jens@0:  *
jens@0:  *  Created by Jens Alfke on 8/20/09.
jens@0:  *  Copyright 2009 Jens Alfke. All rights reserved.
jens@0:  *  BSD-Licensed: See the file "LICENSE.txt" for details.
jens@0:  */
jens@0: 
jens@0: #ifndef _MOOSEYARD_FILE_
jens@0: #define _MOOSEYARD_FILE_
jens@0: #include "Base.h"
jens@0: 
jens@0: namespace Mooseyard {
jens@0: 
jens@0: struct Blob;
jens@0: class MemoryMap;
jens@0: 
jens@0: /** An open file on disk; a thin wrapper around a Unix file descriptor. */
jens@0: class File {
jens@0: public:
jens@0:     
jens@0:     struct Error {
jens@0:         const int code;
jens@0:         const char* const message;
jens@0:         
jens@0:         Error(int c, const char *m)                                 :code(c), message(m) { }
jens@0:         Error(const char *m);
jens@0:     };
jens@0:     static const int kEOF = 10001;
jens@0:     
jens@0:     
jens@0:     File (const char *filename, bool writeable =false, bool create =false)  throw(Error);
jens@0:     File (const char *filename, int oflag)  throw(Error);
jens@0:     ~File();
jens@0:     
jens@0:     off_t length() const  throw(Error);
jens@0:     void setLength (off_t)  throw(Error);
jens@0: 
jens@0:     off_t position() const  throw(Error);
jens@0:     void setPosition (off_t)  throw(Error);
jens@0:     off_t setPositionToEnd (off_t bytesBefore =0)  throw(Error);
jens@0:     
jens@0:     void read (void *dst, size_t)  throw(Error);
jens@0:     size_t write (const void *src, size_t)  throw(Error);
jens@0: 
jens@0:     void readFrom (off_t where, void *dst, size_t)  throw(Error);
jens@0:     void writeTo (off_t where, const void *src, size_t)  throw(Error);
jens@0:     
jens@0:     size_t writeMultiple (Blob blobs[], int count)  throw(Error);
jens@0:     size_t writePadding (int alignment);  // alignment should be a power of 2
jens@0:     
jens@0:     MemoryMap* map();
jens@0:     const MemoryMap* map() const                            {return const_cast<File*>(this)->map();}
jens@0:     void mapRegion (off_t position, size_t length);
jens@0:     const void* mappedPosition (off_t position) const;
jens@0:     
jens@0:     void flush()  throw(Error);             // Regular fsync call
jens@0:     void flushDisk()  throw(Error);         // Expensive F_FULLFSYNC call
jens@0:     
jens@0:     template <typename T>
jens@0:     void read (T& t)  throw(Error)                              {read(&t,sizeof(t));}
jens@0:     template <typename T>
jens@0:     size_t write (const T& t)  throw(Error)                     {return write(&t,sizeof(t));}
jens@0:     template <typename T>
jens@0:     void readFrom (off_t where, T &t)  throw(Error)             {readFrom(where,&t,sizeof(t));}
jens@0:     template <typename T>
jens@0:     void writeTo (off_t where, const T &t)  throw(Error)        {writeTo(where,&t,sizeof(t));}
jens@0:     
jens@0:     bool hasPath (const char *path) const  throw(Error);
jens@0: 
jens@0:     static void unlink (const char *filename)  throw(Error);
jens@0:     static void rename (const char *srcFilename, const char *dstFilename)  throw(Error);
jens@0:     
jens@0:     
jens@0:     class Lock {
jens@0:     public:
jens@0:         Lock (File*, bool block =true)  throw(Error);
jens@0:         ~Lock();
jens@0:         bool isLocked() const                   {return _locked;}
jens@0:         operator bool() const                   {return _locked;}
jens@0:         bool retry();
jens@0:     private:
jens@0:         UNCOPYABLE(Lock);
jens@0:         File *_file;
jens@0:         int _mode;
jens@0:         bool _locked;
jens@0:     };
jens@0:     
jens@0: private:
jens@0:     static int _open (const char *filename, int posixMode)  throw(Error);
jens@2:     static ssize_t _check (ssize_t result)  throw(Error)    {_check((int)result); return result;}
jens@2:     static off_t _check (off_t result)  throw(Error)    {_check((int)result); return result;}
jens@0:     static int _check (int result)  throw(Error);
jens@0:     static void _checkRead (ssize_t result, size_t expectedSize)  throw(Error);
jens@0:     bool _lock (bool block);
jens@0:     void _unlock();
jens@0:     UNCOPYABLE(File);
jens@0:     
jens@0:     const int _fd;
jens@0:     mutable MemoryMap *_memoryMap;
jens@0:     int _locked;
jens@0:     friend class Lock;
jens@0:     friend class MemoryMap;
jens@0: };
jens@0: 
jens@0: }
jens@0: 
jens@0: #endif _MOOSEYARD_FILE_