LogCabin
|
00001 /* Copyright (c) 2012-2014 Stanford University 00002 * 00003 * Permission to use, copy, modify, and distribute this software for any 00004 * purpose with or without fee is hereby granted, provided that the above 00005 * copyright notice and this permission notice appear in all copies. 00006 * 00007 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00008 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00009 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00010 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00011 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00012 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00013 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00014 */ 00015 00016 #include <algorithm> 00017 #include <fcntl.h> 00018 #include <sys/stat.h> 00019 #include <unistd.h> 00020 00021 #include "build/Protocol/Raft.pb.h" 00022 #include "Core/Buffer.h" 00023 #include "Core/Debug.h" 00024 #include "Core/ProtoBuf.h" 00025 #include "Core/StringUtil.h" 00026 #include "Storage/MemoryLog.h" 00027 00028 namespace LogCabin { 00029 namespace Storage { 00030 00031 ////////// MemoryLog ////////// 00032 00033 MemoryLog::MemoryLog() 00034 : startIndex(1) 00035 , entries() 00036 , currentSync(new Sync(0)) 00037 { 00038 } 00039 00040 MemoryLog::~MemoryLog() 00041 { 00042 currentSync->completed = true; 00043 } 00044 00045 std::pair<uint64_t, uint64_t> 00046 MemoryLog::append(const std::vector<const Entry*>& newEntries) 00047 { 00048 uint64_t firstIndex = startIndex + entries.size(); 00049 uint64_t lastIndex = firstIndex + newEntries.size() - 1; 00050 for (auto it = newEntries.begin(); it != newEntries.end(); ++it) 00051 entries.push_back(**it); 00052 currentSync->lastIndex = lastIndex; 00053 return {firstIndex, lastIndex}; 00054 } 00055 00056 const Log::Entry& 00057 MemoryLog::getEntry(uint64_t index) const 00058 { 00059 uint64_t offset = index - startIndex; 00060 return entries.at(offset); 00061 } 00062 00063 uint64_t 00064 MemoryLog::getLogStartIndex() const 00065 { 00066 return startIndex; 00067 } 00068 00069 00070 uint64_t 00071 MemoryLog::getLastLogIndex() const 00072 { 00073 return startIndex + entries.size() - 1; 00074 } 00075 00076 std::string 00077 MemoryLog::getName() const 00078 { 00079 return "Memory"; 00080 } 00081 00082 uint64_t 00083 MemoryLog::getSizeBytes() const 00084 { 00085 // TODO(ongaro): keep this pre-calculated for efficiency 00086 uint64_t size = 0; 00087 for (auto it = entries.begin(); it < entries.end(); ++it) 00088 size += uint64_t(it->ByteSize()); 00089 return size; 00090 } 00091 00092 std::unique_ptr<Log::Sync> 00093 MemoryLog::takeSync() 00094 { 00095 std::unique_ptr<Sync> other(new Sync(getLastLogIndex())); 00096 std::swap(other, currentSync); 00097 return other; 00098 } 00099 00100 void 00101 MemoryLog::truncatePrefix(uint64_t firstIndex) 00102 { 00103 if (firstIndex > startIndex) { 00104 // Erase log entries in range [startIndex, firstIndex), so deque 00105 // offsets in range [0, firstIndex - startIndex). Be careful not to 00106 // erase past the end of the deque (STL doesn't check for this). 00107 entries.erase(entries.begin(), 00108 entries.begin() + 00109 int64_t(std::min(firstIndex - startIndex, 00110 entries.size()))); 00111 startIndex = firstIndex; 00112 } 00113 } 00114 00115 void 00116 MemoryLog::truncateSuffix(uint64_t lastIndex) 00117 { 00118 if (lastIndex < startIndex) 00119 entries.clear(); 00120 else if (lastIndex < startIndex - 1 + entries.size()) 00121 entries.resize(lastIndex - startIndex + 1); 00122 } 00123 00124 void 00125 MemoryLog::updateMetadata() 00126 { 00127 } 00128 00129 } // namespace LogCabin::Storage 00130 } // namespace LogCabin