LogCabin
Storage/SnapshotFile.h
Go to the documentation of this file.
00001 /* Copyright (c) 2013 Stanford University
00002  * Copyright (c) 2015 Diego Ongaro
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 #include <google/protobuf/message.h>
00018 #include <memory>
00019 #include <stdexcept>
00020 #include <string>
00021 
00022 #include "Core/CompatAtomic.h"
00023 #include "Core/ProtoBuf.h"
00024 #include "Storage/FilesystemUtil.h"
00025 
00026 #ifndef LOGCABIN_STORAGE_SNAPSHOTFILE_H
00027 #define LOGCABIN_STORAGE_SNAPSHOTFILE_H
00028 
00029 namespace LogCabin {
00030 namespace Storage {
00031 
00032 class Layout; // forward declaration
00033 
00034 namespace SnapshotFile {
00035 
00036 /**
00037  * Remove any partial snapshots found on disk. This is normally called when the
00038  * server boots up.
00039  */
00040 void discardPartialSnapshots(const Storage::Layout& storageLayout);
00041 
00042 /**
00043  * Assists in reading snapshot files from the local filesystem.
00044  */
00045 class Reader : public Core::ProtoBuf::InputStream {
00046   public:
00047     /**
00048      * Constructor.
00049      * \param storageLayout
00050      *      The directories in which to find the snapshot (in a file called
00051      *      "snapshot" in the snapshotDir).
00052      * \throw std::runtime_error
00053      *      If the file can't be found.
00054      */
00055     explicit Reader(const Storage::Layout& storageLayout);
00056     /// Destructor.
00057     ~Reader();
00058     /// Return the size in bytes for the file.
00059     uint64_t getSizeBytes();
00060     // See Core::ProtoBuf::InputStream.
00061     uint64_t getBytesRead() const;
00062     // See Core::ProtoBuf::InputStream.
00063     std::string readMessage(google::protobuf::Message& message);
00064     // See Core::ProtoBuf::InputStream.
00065     uint64_t readRaw(void* data, uint64_t length);
00066   private:
00067     /// Wraps the raw file descriptor; in charge of closing it when done.
00068     Storage::FilesystemUtil::File file;
00069     /// Maps the file into memory for reading.
00070     std::unique_ptr<Storage::FilesystemUtil::FileContents> contents;
00071     /// The number of bytes read from the file.
00072     uint64_t bytesRead;
00073 };
00074 
00075 /**
00076  * Assists in writing snapshot files to the local filesystem.
00077  */
00078 class Writer : public Core::ProtoBuf::OutputStream {
00079   public:
00080     /**
00081      * Allocates an object that is shared across processes. Uses a shared,
00082      * anonymous mmap region internally.
00083      */
00084     template<typename T>
00085     struct SharedMMap {
00086         SharedMMap();
00087         ~SharedMMap();
00088         T* value; // pointer does not change after construction
00089         // SharedMMap is not copyable
00090         SharedMMap(const SharedMMap& other) = delete;
00091         SharedMMap& operator=(const SharedMMap& other) = delete;
00092     };
00093 
00094     /**
00095      * Constructor.
00096      * \param storageLayout
00097      *      The directories in which to create the snapshot (in a file called
00098      *      "snapshot" in the snapshotDir).
00099      * TODO(ongaro): what if it can't be written?
00100      */
00101     explicit Writer(const Storage::Layout& storageLayout);
00102     /**
00103      * Destructor.
00104      * If the file hasn't been explicitly saved or discarded, prints a warning
00105      * and discards the file.
00106      */
00107     ~Writer();
00108     /**
00109      * Throw away the file.
00110      * If you call this after the file has been closed, it will PANIC.
00111      */
00112     void discard();
00113     /**
00114      * Flush changes just down to the operating system's buffer cache.
00115      * Leave the file open for additional writes.
00116      *
00117      * This is useful when forking child processes to write to the file.
00118      * The correct procedure for that is:
00119      *  0. write stuff
00120      *  1. call flushToOS()
00121      *  2. fork
00122      *  3. child process: write stuff
00123      *  4. child process: call flushToOS()
00124      *  5. child process: call _exit()
00125      *  6. parent process: call seekToEnd()
00126      *  7. parent process: write stuff
00127      *  8. parent process: call save()
00128      */
00129     void flushToOS();
00130     /**
00131      * Seek to the end of the file, in case another process has written to it.
00132      * Subsequent calls to getBytesWritten() will include data written by other
00133      * processes.
00134      */
00135     void seekToEnd();
00136     /**
00137      * Flush changes all the way down to the disk and close the file.
00138      * If you call this after the file has been closed, it will PANIC.
00139      * \return
00140      *      Size in bytes of the file
00141      */
00142     uint64_t save();
00143     // See Core::ProtoBuf::OutputStream.
00144     uint64_t getBytesWritten() const;
00145     // See Core::ProtoBuf::OutputStream.
00146     void writeMessage(const google::protobuf::Message& message);
00147     // See Core::ProtoBuf::OutputStream.
00148     void writeRaw(const void* data, uint64_t length);
00149 
00150   private:
00151     /// A handle to the directory containing the snapshot. Used for renameat on
00152     /// close.
00153     Storage::FilesystemUtil::File parentDir;
00154     /// The temporary name of 'file' before it is closed.
00155     std::string stagingName;
00156     /// Wraps the raw file descriptor; in charge of closing it when done.
00157     Storage::FilesystemUtil::File file;
00158     /// The number of bytes accumulated in the file so far.
00159     uint64_t bytesWritten;
00160   public:
00161     /**
00162      * This value is incremented every time bytes are written to the Writer
00163      * from any process holding this Writer. Used by Server/StateMachine to
00164      * implement a watchdog that checks progress of a snapshotting process.
00165      */
00166     SharedMMap<std::atomic<uint64_t>> sharedBytesWritten;
00167 
00168 };
00169 
00170 } // namespace LogCabin::Storage::SnapshotFile
00171 } // namespace LogCabin::Storage
00172 } // namespace LogCabin
00173 
00174 #endif /* LOGCABIN_STORAGE_SNAPSHOTFILE_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines