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 <memory>
25 #include <mutex>
26 #include <vector>
27 
28 #include "common/chunk_type_with_address.h"
29 #include "common/slogger.h"
30 
31 struct ChunkLocationInfo {
32 	typedef std::vector<ChunkTypeWithAddress> ChunkLocations;
33 
34 	uint64_t chunkId;
35 	uint32_t version;
36 	uint64_t fileLength;
37 	ChunkLocations locations;
38 
ChunkLocationInfoChunkLocationInfo39 	ChunkLocationInfo()
40 			: chunkId(0),
41 			  version(0),
42 			  fileLength(0) {
43 	}
44 
ChunkLocationInfoChunkLocationInfo45 	ChunkLocationInfo(
46 			const uint64_t chunkId,
47 			const uint32_t version,
48 			const uint64_t fileLength,
49 			const ChunkLocations locations) :
50 		chunkId(chunkId),
51 		version(version),
52 		fileLength(fileLength),
53 		locations(locations) {
54 	}
55 
isEmptyChunkChunkLocationInfo56 	bool isEmptyChunk() const {
57 		return chunkId == 0;
58 	}
59 };
60 
61 // Intended to be instantiated per descriptor.
62 // May cache locations of previously queried chunks.
63 // Thread safe.
64 class ReadChunkLocator {
65 public:
66 	ReadChunkLocator(const ReadChunkLocator&) = delete;
ReadChunkLocator()67 	ReadChunkLocator() {}
68 
69 	std::shared_ptr<const ChunkLocationInfo> locateChunk(uint32_t inode, uint32_t index);
70 	void invalidateCache(uint32_t inode, uint32_t index);
71 
72 private:
73 	uint32_t inode_;
74 	uint32_t index_;
75 
76 	std::shared_ptr<const ChunkLocationInfo> cache_;
77 	std::mutex mutex_;
78 };
79 
80 class WriteChunkLocator {
81 public:
WriteChunkLocator()82 	WriteChunkLocator() : inode_(0), index_(0), lockId_(0) {}
83 
~WriteChunkLocator()84 	virtual ~WriteChunkLocator() {
85 		try {
86 			if (lockId_) {
87 				unlockChunk();
88 			}
89 		} catch (Exception& ex) {
90 			lzfs_pretty_syslog(LOG_WARNING,
91 					"unlocking chunk error, inode: %" PRIu32 ", index: %" PRIu32 " - %s",
92 					inode_, index_, ex.what());
93 		}
94 	}
95 
96 	virtual void locateAndLockChunk(uint32_t inode, uint32_t index);
97 	virtual void unlockChunk();
98 
chunkIndex()99 	uint32_t chunkIndex() {
100 		return index_;
101 	}
102 
updateFileLength(uint64_t fileLength)103 	void updateFileLength(uint64_t fileLength) {
104 		locationInfo_. fileLength = fileLength;
105 	}
106 
locationInfo()107 	const ChunkLocationInfo& locationInfo() const {
108 		return locationInfo_;
109 	}
110 
111 protected:
WriteChunkLocator(uint32_t inode,uint32_t index,uint32_t lockId)112 	WriteChunkLocator(uint32_t inode, uint32_t index, uint32_t lockId)
113 			: inode_(inode),
114 			  index_(index),
115 			  lockId_(lockId) {
116 	}
117 
118 	uint32_t inode_;
119 	uint32_t index_;
120 	uint32_t lockId_;
121 	ChunkLocationInfo locationInfo_;
122 };
123 
124 // Fit for truncating xor chunks down when master, not client, locks a chunk
125 class TruncateWriteChunkLocator : public WriteChunkLocator {
126 public:
127 	// Locator is created for single operation
TruncateWriteChunkLocator(uint32_t inode,uint32_t index,uint32_t lockId)128 	explicit TruncateWriteChunkLocator(uint32_t inode, uint32_t index, uint32_t lockId)
129 		: WriteChunkLocator(inode, index, lockId) {
130 	}
131 
~TruncateWriteChunkLocator()132 	~TruncateWriteChunkLocator() {
133 		// Remove information about the lock to prevent ~WriteChunkLocator from unlocking the chunk
134 		lockId_ = 0;
135 	}
136 
137 	// In this case a chunk is unlocked by master so this locator will be simply destroyed
unlockChunk()138 	void unlockChunk() {}
139 };
140