1 /* 2 Copyright 2013-2015 Skytechnology sp. z o.o. 3 4 This file is part of LizardFS. 5 6 LizardFS is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 3. 9 10 LizardFS is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with LizardFS. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #pragma once 20 21 #include "common/platform.h" 22 23 #include <cstdint> 24 #include <cstdlib> 25 #include <string> 26 #include <sys/types.h> 27 28 #include <condition_variable> 29 #include <thread> 30 31 #include "chunkserver/chunk_format.h" 32 #include "common/chunk_part_type.h" 33 #include "common/disk_info.h" 34 #include "protocol/MFSCommunication.h" 35 36 #define STATSHISTORY (24*60) 37 #define LASTERRSIZE 30 38 39 // Block data and crc summaric size. 40 constexpr uint32_t kHddBlockSize = MFSBLOCKSIZE + 4; 41 42 enum ChunkState { 43 CH_AVAIL, 44 CH_LOCKED, 45 CH_DELETED, 46 CH_TOBEDELETED 47 }; 48 49 class Chunk; 50 51 struct cntcond { 52 std::condition_variable cond; 53 uint32_t wcnt; 54 Chunk *owner; 55 struct cntcond *next; 56 }; 57 58 struct ioerror { 59 uint64_t chunkid; 60 uint32_t timestamp; 61 int errornumber; 62 }; 63 64 struct folder { 65 char *path; 66 #define SCST_SCANNEEDED 0u 67 #define SCST_SCANINPROGRESS 1u 68 #define SCST_SCANTERMINATE 2u 69 #define SCST_SCANFINISHED 3u 70 #define SCST_SENDNEEDED 4u 71 #define SCST_WORKING 5u 72 unsigned int scanstate:3; 73 unsigned int needrefresh:1; 74 unsigned int todel:2; 75 unsigned int damaged:1; 76 unsigned int toremove:2; 77 uint8_t scanprogress; 78 #define MGST_MIGRATEDONE 0u 79 #define MGST_MIGRATEINPROGRESS 1u 80 #define MGST_MIGRATETERMINATE 2u 81 #define MGST_MIGRATEFINISHED 3u 82 uint8_t migratestate; 83 uint64_t leavefree; 84 uint64_t avail; 85 uint64_t total; 86 HddAtomicStatistics cstat; 87 HddStatistics stats[STATSHISTORY]; 88 uint32_t statspos; 89 ioerror lasterrtab[LASTERRSIZE]; 90 uint32_t chunkcount; 91 uint32_t lasterrindx; 92 uint32_t lastrefresh; 93 dev_t devid; 94 ino_t lockinode; 95 int lfd; 96 double carry; 97 std::thread scanthread; 98 std::thread migratethread; 99 Chunk *testhead,**testtail; 100 struct folder *next; 101 }; 102 103 class Chunk { 104 public: 105 static const uint32_t kNumberOfSubfolders = 256; 106 enum { kCurrentDirectoryLayout = 0, kMooseFSDirectoryLayout }; 107 108 Chunk(uint64_t chunkId, ChunkPartType type, ChunkState state); ~Chunk()109 virtual ~Chunk() {}; 110 filename()111 std::string filename() const { 112 return filename_layout_ >= kCurrentDirectoryLayout 113 ? generateFilenameForVersion(version, filename_layout_) 114 : std::string(); 115 }; 116 117 std::string generateFilenameForVersion(uint32_t version, int layout_version = kCurrentDirectoryLayout) const; 118 int renameChunkFile(uint32_t new_version, int new_layout_version = kCurrentDirectoryLayout); setFilenameLayout(int layout_version)119 void setFilenameLayout(int layout_version) { filename_layout_ = layout_version; } 120 121 virtual off_t getBlockOffset(uint16_t blockNumber) const = 0; 122 virtual off_t getFileSizeFromBlockCount(uint32_t blockCount) const = 0; 123 virtual bool isFileSizeValid(off_t fileSize) const = 0; chunkFormat()124 virtual ChunkFormat chunkFormat() const { return ChunkFormat::IMPROPER; }; 125 uint32_t maxBlocksInFile() const; 126 virtual void setBlockCountFromFizeSize(off_t fileSize) = 0; type()127 ChunkPartType type() const { return type_; } 128 static uint32_t getSubfolderNumber(uint64_t chunkId, int layout_version = 0); 129 static std::string getSubfolderNameGivenNumber(uint32_t subfolderNumber, int layout_version = 0); 130 static std::string getSubfolderNameGivenChunkId(uint64_t chunkId, int layout_version = 0); 131 132 Chunk *testnext, **testprev; 133 Chunk *next; 134 cntcond *ccond; 135 struct folder *owner; 136 uint64_t chunkid; 137 uint32_t version; 138 int32_t fd; 139 uint16_t blocks; 140 uint16_t refcount; 141 uint16_t blockExpectedToBeReadNext; 142 143 protected: 144 ChunkPartType type_; 145 int8_t filename_layout_; /*!< <0 - no valid name (empty string) 146 0 - current directory layout 147 >0 - older directory layouts */ 148 public: 149 uint8_t validattr; 150 uint8_t todel; 151 uint8_t state; 152 uint8_t wasChanged; 153 }; 154 155 class MooseFSChunk : public Chunk { 156 public: 157 static const size_t kMaxSignatureBlockSize = 1024; 158 static const size_t kMaxCrcBlockSize = MFSBLOCKSINCHUNK * sizeof(uint32_t); 159 static const size_t kMaxPaddingBlockSize = 4096; 160 static const size_t kMaxHeaderSize = 161 kMaxSignatureBlockSize + kMaxCrcBlockSize + kMaxPaddingBlockSize; 162 static const size_t kDiskBlockSize = 4096; // 4kB 163 164 typedef std::array<uint8_t, kMaxCrcBlockSize> CrcDataContainer; 165 166 MooseFSChunk(uint64_t chunkId, ChunkPartType type, ChunkState state); 167 off_t getBlockOffset(uint16_t blockNumber) const override; 168 off_t getFileSizeFromBlockCount(uint32_t blockCount) const override; 169 bool isFileSizeValid(off_t fileSize) const override; 170 void setBlockCountFromFizeSize(off_t fileSize) override; chunkFormat()171 ChunkFormat chunkFormat() const override { return ChunkFormat::MOOSEFS; }; 172 off_t getSignatureOffset() const; 173 void readaheadHeader() const; 174 size_t getHeaderSize() const; 175 off_t getCrcOffset() const; 176 size_t getCrcBlockSize() const; 177 }; 178 179 class InterleavedChunk : public Chunk { 180 public: 181 InterleavedChunk(uint64_t chunkId, ChunkPartType type, ChunkState state); 182 off_t getBlockOffset(uint16_t blockNumber) const override; 183 off_t getFileSizeFromBlockCount(uint32_t blockCount) const override; 184 bool isFileSizeValid(off_t fileSize) const override; 185 void setBlockCountFromFizeSize(off_t fileSize) override; chunkFormat()186 ChunkFormat chunkFormat() const override { return ChunkFormat::INTERLEAVED; }; 187 }; 188 189 #define IF_MOOSEFS_CHUNK(mc, chunk) \ 190 if (MooseFSChunk *mc = dynamic_cast<MooseFSChunk *>(chunk)) 191 192 #define IF_INTERLEAVED_CHUNK(lc, chunk) \ 193 if (InterleavedChunk *lc = dynamic_cast<InterleavedChunk *>(chunk)) 194