]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2014 Sebastien Ponce <sebastien.ponce@cern.ch> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #ifndef CEPH_LIBRADOSSTRIPER_RADOSSTRIPERIMPL_H | |
16 | #define CEPH_LIBRADOSSTRIPER_RADOSSTRIPERIMPL_H | |
17 | ||
18 | #include <string> | |
19 | ||
f67539c2 TL |
20 | #include <boost/intrusive_ptr.hpp> |
21 | ||
7c673cae FG |
22 | #include "include/rados/librados.h" |
23 | #include "include/rados/librados.hpp" | |
24 | #include "include/radosstriper/libradosstriper.h" | |
25 | #include "include/radosstriper/libradosstriper.hpp" | |
224ce89b | 26 | #include "MultiAioCompletionImpl.h" |
7c673cae FG |
27 | |
28 | #include "librados/IoCtxImpl.h" | |
29 | #include "librados/AioCompletionImpl.h" | |
30 | #include "common/RefCountedObj.h" | |
f67539c2 | 31 | #include "common/ceph_context.h" |
7c673cae | 32 | |
224ce89b | 33 | namespace libradosstriper { |
7c673cae | 34 | |
224ce89b WB |
35 | using MultiAioCompletionImplPtr = |
36 | boost::intrusive_ptr<MultiAioCompletionImpl>; | |
7c673cae | 37 | |
224ce89b | 38 | struct RadosStriperImpl { |
7c673cae FG |
39 | |
40 | /** | |
41 | * exception wrapper around an error code | |
42 | */ | |
43 | struct ErrorCode { | |
44 | ErrorCode(int error) : m_code(error) {}; | |
45 | int m_code; | |
46 | }; | |
47 | ||
48 | /* | |
49 | * Constructor | |
50 | * @param cluster_name name of the cluster, can be NULL | |
51 | * @param client_name has 2 meanings depending on cluster_name | |
52 | * - if cluster_name is null : this is the client id | |
53 | * - else : this is the full client name in format type.id | |
54 | */ | |
55 | RadosStriperImpl(librados::IoCtx& ioctx, librados::IoCtxImpl *ioctx_impl); | |
56 | /// Destructor | |
57 | ~RadosStriperImpl() {}; | |
58 | ||
59 | // configuration | |
60 | int setObjectLayoutStripeUnit(unsigned int stripe_unit); | |
61 | int setObjectLayoutStripeCount(unsigned int stripe_count); | |
62 | int setObjectLayoutObjectSize(unsigned int object_size); | |
63 | ||
64 | // xattrs | |
65 | int getxattr(const object_t& soid, const char *name, bufferlist& bl); | |
66 | int setxattr(const object_t& soid, const char *name, bufferlist& bl); | |
20effc67 | 67 | int getxattrs(const object_t& soid, std::map<std::string, bufferlist>& attrset); |
7c673cae FG |
68 | int rmxattr(const object_t& soid, const char *name); |
69 | ||
70 | // io | |
71 | int write(const std::string& soid, const bufferlist& bl, size_t len, uint64_t off); | |
72 | int append(const std::string& soid, const bufferlist& bl, size_t len); | |
73 | int write_full(const std::string& soid, const bufferlist& bl); | |
74 | int read(const std::string& soid, bufferlist* pbl, size_t len, uint64_t off); | |
75 | ||
76 | // asynchronous io | |
77 | int aio_write(const std::string& soid, librados::AioCompletionImpl *c, | |
78 | const bufferlist& bl, size_t len, uint64_t off); | |
79 | int aio_append(const std::string& soid, librados::AioCompletionImpl *c, | |
80 | const bufferlist& bl, size_t len); | |
81 | int aio_write_full(const std::string& soid, librados::AioCompletionImpl *c, | |
82 | const bufferlist& bl); | |
83 | int aio_read(const std::string& soid, librados::AioCompletionImpl *c, | |
84 | bufferlist* pbl, size_t len, uint64_t off); | |
85 | int aio_read(const std::string& soid, librados::AioCompletionImpl *c, | |
86 | char* buf, size_t len, uint64_t off); | |
87 | int aio_flush(); | |
88 | ||
89 | // stat, deletion and truncation | |
90 | int stat(const std::string& soid, uint64_t *psize, time_t *pmtime); | |
91 | int stat2(const std::string& soid, uint64_t *psize, struct timespec *pts); | |
92 | template<class TimeType> | |
93 | struct StatFunction { | |
94 | typedef int (librados::IoCtxImpl::*Type) (const object_t& oid, | |
95 | librados::AioCompletionImpl *c, | |
96 | uint64_t *psize, TimeType *pmtime); | |
97 | }; | |
98 | template<class TimeType> | |
99 | int aio_generic_stat(const std::string& soid, librados::AioCompletionImpl *c, | |
100 | uint64_t *psize, TimeType *pmtime, | |
101 | typename StatFunction<TimeType>::Type statFunction); | |
102 | int aio_stat(const std::string& soid, librados::AioCompletionImpl *c, | |
103 | uint64_t *psize, time_t *pmtime); | |
104 | int aio_stat2(const std::string& soid, librados::AioCompletionImpl *c, | |
105 | uint64_t *psize, struct timespec *pts); | |
106 | int remove(const std::string& soid, int flags=0); | |
107 | int trunc(const std::string& soid, uint64_t size); | |
108 | ||
109 | // asynchronous remove. Note that the removal is not 100% parallelized : | |
110 | // the removal of the first rados object of the striped object will be | |
111 | // done via a syncrhonous call after the completion of all other removals. | |
112 | // These are done asynchrounously and in parallel | |
113 | int aio_remove(const std::string& soid, librados::AioCompletionImpl *c, int flags=0); | |
114 | ||
115 | // reference counting | |
116 | void get() { | |
9f95a23c | 117 | std::lock_guard l{lock}; |
7c673cae | 118 | m_refCnt ++ ; |
7c673cae FG |
119 | } |
120 | void put() { | |
121 | bool deleteme = false; | |
9f95a23c | 122 | lock.lock(); |
7c673cae FG |
123 | m_refCnt --; |
124 | if (m_refCnt == 0) | |
125 | deleteme = true; | |
9f95a23c TL |
126 | cond.notify_all(); |
127 | lock.unlock(); | |
7c673cae FG |
128 | if (deleteme) |
129 | delete this; | |
130 | } | |
131 | ||
132 | // objectid manipulation | |
133 | std::string getObjectId(const object_t& soid, long long unsigned objectno); | |
134 | ||
135 | // opening and closing of striped objects | |
136 | void unlockObject(const std::string& soid, | |
137 | const std::string& lockCookie); | |
138 | void aio_unlockObject(const std::string& soid, | |
139 | const std::string& lockCookie, | |
140 | librados::AioCompletion *c); | |
141 | ||
142 | // internal versions of IO method | |
143 | int write_in_open_object(const std::string& soid, | |
144 | const ceph_file_layout& layout, | |
145 | const std::string& lockCookie, | |
146 | const bufferlist& bl, | |
147 | size_t len, | |
148 | uint64_t off); | |
149 | int aio_write_in_open_object(const std::string& soid, | |
150 | librados::AioCompletionImpl *c, | |
151 | const ceph_file_layout& layout, | |
152 | const std::string& lockCookie, | |
153 | const bufferlist& bl, | |
154 | size_t len, | |
155 | uint64_t off); | |
156 | int internal_aio_write(const std::string& soid, | |
224ce89b | 157 | MultiAioCompletionImplPtr c, |
7c673cae FG |
158 | const bufferlist& bl, |
159 | size_t len, | |
160 | uint64_t off, | |
161 | const ceph_file_layout& layout); | |
162 | ||
163 | int extract_uint32_attr(std::map<std::string, bufferlist> &attrs, | |
164 | const std::string& key, | |
165 | ceph_le32 *value); | |
166 | ||
167 | int extract_sizet_attr(std::map<std::string, bufferlist> &attrs, | |
168 | const std::string& key, | |
169 | size_t *value); | |
170 | ||
171 | int internal_get_layout_and_size(const std::string& oid, | |
172 | ceph_file_layout *layout, | |
173 | uint64_t *size); | |
174 | ||
175 | int internal_aio_remove(const std::string& soid, | |
224ce89b | 176 | MultiAioCompletionImplPtr multi_completion, |
7c673cae FG |
177 | int flags=0); |
178 | ||
179 | /** | |
180 | * opens an existing striped object and takes a shared lock on it | |
181 | * @return 0 if everything is ok and the lock was taken. -errcode otherwise | |
182 | * In particulae, if the striped object does not exists, -ENOENT is returned | |
183 | * In case the return code in not 0, no lock is taken | |
184 | */ | |
185 | int openStripedObjectForRead(const std::string& soid, | |
186 | ceph_file_layout *layout, | |
187 | uint64_t *size, | |
188 | std::string *lockCookie); | |
189 | ||
190 | /** | |
191 | * opens an existing striped object, takes a shared lock on it | |
192 | * and sets its size to the size it will have after the write. | |
193 | * In case the striped object does not exists, it will create it by | |
194 | * calling createOrOpenStripedObject. | |
195 | * @param layout this is filled with the layout of the file | |
196 | * @param size new size of the file (together with isFileSizeAbsolute) | |
197 | * In case of success, this is filled with the size of the file before the opening | |
198 | * @param isFileSizeAbsolute if false, this means that the given size should | |
199 | * be added to the current file size (append mode) | |
200 | * @return 0 if everything is ok and the lock was taken. -errcode otherwise | |
201 | * In case the return code in not 0, no lock is taken | |
202 | */ | |
203 | int openStripedObjectForWrite(const std::string& soid, | |
204 | ceph_file_layout *layout, | |
205 | uint64_t *size, | |
206 | std::string *lockCookie, | |
207 | bool isFileSizeAbsolute); | |
208 | /** | |
209 | * creates an empty striped object with the given size and opens it calling | |
210 | * openStripedObjectForWrite, which implies taking a shared lock on it | |
211 | * Also deals with the cases where the object was created in the mean time | |
212 | * @param isFileSizeAbsolute if false, this means that the given size should | |
213 | * be added to the current file size (append mode). This of course only makes | |
214 | * sense in case the striped object already exists | |
215 | * @return 0 if everything is ok and the lock was taken. -errcode otherwise | |
216 | * In case the return code in not 0, no lock is taken | |
217 | */ | |
218 | int createAndOpenStripedObject(const std::string& soid, | |
219 | ceph_file_layout *layout, | |
220 | uint64_t size, | |
221 | std::string *lockCookie, | |
222 | bool isFileSizeAbsolute); | |
223 | ||
224 | /** | |
225 | * truncates an object synchronously. Should only be called with size < original_size | |
226 | */ | |
227 | int truncate(const std::string& soid, | |
228 | uint64_t original_size, | |
229 | uint64_t size, | |
230 | ceph_file_layout &layout); | |
231 | ||
232 | /** | |
233 | * truncates an object asynchronously. Should only be called with size < original_size | |
234 | * note that the method is not 100% asynchronous, only the removal of rados objects | |
235 | * is, the (potential) truncation of the rados object residing just at the truncation | |
236 | * point is synchronous for lack of asynchronous truncation in the rados layer | |
237 | */ | |
238 | int aio_truncate(const std::string& soid, | |
224ce89b | 239 | MultiAioCompletionImplPtr c, |
7c673cae FG |
240 | uint64_t original_size, |
241 | uint64_t size, | |
242 | ceph_file_layout &layout); | |
243 | ||
244 | /** | |
245 | * grows an object (adding 0s). Should only be called with size > original_size | |
246 | */ | |
247 | int grow(const std::string& soid, | |
248 | uint64_t original_size, | |
249 | uint64_t size, | |
250 | ceph_file_layout &layout); | |
251 | ||
252 | /** | |
253 | * creates a unique identifier | |
254 | */ | |
255 | static std::string getUUID(); | |
256 | ||
257 | CephContext *cct() { | |
258 | return (CephContext*)m_radosCluster.cct(); | |
259 | } | |
260 | ||
261 | // reference counting | |
9f95a23c | 262 | std::condition_variable cond; |
7c673cae | 263 | int m_refCnt; |
9f95a23c | 264 | std::mutex lock; |
7c673cae FG |
265 | |
266 | ||
267 | // Context | |
268 | librados::Rados m_radosCluster; | |
269 | librados::IoCtx m_ioCtx; | |
270 | librados::IoCtxImpl *m_ioCtxImpl; | |
271 | ||
272 | // Default layout | |
273 | ceph_file_layout m_layout; | |
274 | }; | |
224ce89b | 275 | } |
7c673cae | 276 | #endif |