]> git.proxmox.com Git - ceph.git/blob - ceph/src/os/filestore/LFNIndex.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / os / filestore / LFNIndex.h
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) 2004-2006 Sage Weil <sage@newdream.net>
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
16 #ifndef OS_LFNINDEX_H
17 #define OS_LFNINDEX_H
18
19 #include <string>
20 #include <map>
21 #include <set>
22 #include <vector>
23 #include <exception>
24
25 #include "osd/osd_types.h"
26 #include "include/object.h"
27 #include "common/ceph_crypto.h"
28
29 #include "CollectionIndex.h"
30
31 /**
32 * LFNIndex also encapsulates logic for manipulating
33 * subdirectories of a collection as well as the long filename
34 * logic.
35 *
36 * The protected methods provide machinery for derived classes to
37 * manipulate subdirectories and objects.
38 *
39 * The virtual methods are to be overridden to provide the actual
40 * hashed layout.
41 *
42 * User must call created when an object is created.
43 *
44 * Synchronization: Calling code must ensure that there are no object
45 * creations or deletions during the lifetime of a Path object (except
46 * of an object at that path).
47 *
48 * Unless otherwise noted, methods which return an int return 0 on success
49 * and a negative error code on failure.
50 */
51 #define WRAP_RETRY(x) { \
52 bool failed = false; \
53 int r = 0; \
54 init_inject_failure(); \
55 while (1) { \
56 try { \
57 if (failed) { \
58 r = cleanup(); \
59 ceph_assert(r == 0); \
60 } \
61 { x } \
62 out: \
63 complete_inject_failure(); \
64 return r; \
65 } catch (RetryException&) { \
66 failed = true; \
67 } catch (...) { \
68 ceph_abort(); \
69 } \
70 } \
71 return -1; \
72 } \
73
74
75
76 class LFNIndex : public CollectionIndex {
77 /// Hash digest output size.
78 static const int FILENAME_LFN_DIGEST_SIZE = CEPH_CRYPTO_SHA1_DIGESTSIZE;
79 /// Length of filename hash.
80 static const int FILENAME_HASH_LEN = FILENAME_LFN_DIGEST_SIZE;
81 /// Max filename size.
82 static const int FILENAME_MAX_LEN = 4096;
83 /// Length of hashed filename.
84 static const int FILENAME_SHORT_LEN = 255;
85 /// Length of hashed filename prefix.
86 static const int FILENAME_PREFIX_LEN;
87 /// Length of hashed filename cookie.
88 static const int FILENAME_EXTRA = 4;
89 /// Lfn cookie value.
90 static const std::string FILENAME_COOKIE;
91 /// Name of LFN attribute for storing full name.
92 static const std::string LFN_ATTR;
93 /// Prefix for subdir index attributes.
94 static const std::string PHASH_ATTR_PREFIX;
95 /// Prefix for index subdirectories.
96 static const std::string SUBDIR_PREFIX;
97
98 /// Path to Index base.
99 const std::string base_path;
100
101 protected:
102 const uint32_t index_version;
103
104 /// true if retry injection is enabled
105 struct RetryException : public std::exception {};
106 bool error_injection_enabled;
107 bool error_injection_on;
108 double error_injection_probability;
109 uint64_t last_failure;
110 uint64_t current_failure;
111 void init_inject_failure() {
112 if (error_injection_on) {
113 error_injection_enabled = true;
114 last_failure = current_failure = 0;
115 }
116 }
117 void maybe_inject_failure();
118 void complete_inject_failure() {
119 error_injection_enabled = false;
120 }
121
122 private:
123 std::string lfn_attribute, lfn_alt_attribute;
124 coll_t collection;
125
126 public:
127 /// Constructor
128 LFNIndex(
129 CephContext* cct,
130 coll_t collection,
131 const char *base_path, ///< [in] path to Index root
132 uint32_t index_version,
133 double _error_injection_probability=0)
134 : CollectionIndex(cct, collection),
135 base_path(base_path),
136 index_version(index_version),
137 error_injection_enabled(false),
138 error_injection_on(_error_injection_probability != 0),
139 error_injection_probability(_error_injection_probability),
140 last_failure(0), current_failure(0),
141 collection(collection) {
142 if (index_version == HASH_INDEX_TAG) {
143 lfn_attribute = LFN_ATTR;
144 } else {
145 char buf[100];
146 snprintf(buf, sizeof(buf), "%d", index_version);
147 lfn_attribute = LFN_ATTR + std::string(buf);
148 lfn_alt_attribute = LFN_ATTR + std::string(buf) + "-alt";
149 }
150 }
151
152 coll_t coll() const override { return collection; }
153
154 /// Virtual destructor
155 ~LFNIndex() override {}
156
157 /// @see CollectionIndex
158 int init() override;
159
160 /// @see CollectionIndex
161 int cleanup() override = 0;
162
163 /// @see CollectionIndex
164 int created(
165 const ghobject_t &oid,
166 const char *path
167 ) override;
168
169 /// @see CollectionIndex
170 int unlink(
171 const ghobject_t &oid
172 ) override;
173
174 /// @see CollectionIndex
175 int lookup(
176 const ghobject_t &oid,
177 IndexedPath *path,
178 int *hardlink
179 ) override;
180
181 /// @see CollectionIndex;
182 int pre_hash_collection(
183 uint32_t pg_num,
184 uint64_t expected_num_objs
185 ) override;
186
187 /// @see CollectionIndex
188 int collection_list_partial(
189 const ghobject_t &start,
190 const ghobject_t &end,
191 int max_count,
192 std::vector<ghobject_t> *ls,
193 ghobject_t *next
194 ) override;
195
196 virtual int _split(
197 uint32_t match, //< [in] value to match
198 uint32_t bits, //< [in] bits to check
199 CollectionIndex* dest //< [in] destination index
200 ) = 0;
201 virtual int _merge(
202 uint32_t bits, //< [in] bits for target
203 CollectionIndex* dest //< [in] destination index
204 ) = 0;
205
206 /// @see CollectionIndex
207 int split(
208 uint32_t match,
209 uint32_t bits,
210 CollectionIndex* dest
211 ) override {
212 WRAP_RETRY(
213 r = _split(match, bits, dest);
214 goto out;
215 );
216 }
217
218 /// @see CollectionIndex
219 int merge(
220 uint32_t bits,
221 CollectionIndex* dest
222 ) override {
223 WRAP_RETRY(
224 r = _merge(bits, dest);
225 goto out;
226 );
227 }
228
229 /**
230 * Returns the length of the longest escaped name which could result
231 * from any clone, shard, or rollback object of this object
232 */
233 static uint64_t get_max_escaped_name_len(const hobject_t &obj);
234
235 protected:
236 virtual int _init() = 0;
237
238 /// Will be called upon object creation
239 virtual int _created(
240 const std::vector<std::string> &path, ///< [in] Path to subdir.
241 const ghobject_t &oid, ///< [in] Object created.
242 const std::string &mangled_name ///< [in] Mangled filename.
243 ) = 0;
244
245 /// Will be called to remove an object
246 virtual int _remove(
247 const std::vector<std::string> &path, ///< [in] Path to subdir.
248 const ghobject_t &oid, ///< [in] Object to remove.
249 const std::string &mangled_name ///< [in] Mangled filename.
250 ) = 0;
251
252 /// Return the path and mangled_name for oid.
253 virtual int _lookup(
254 const ghobject_t &oid,///< [in] Object for lookup.
255 std::vector<std::string> *path, ///< [out] Path to the object.
256 std::string *mangled_name, ///< [out] Mangled filename.
257 int *exists ///< [out] True if the object exists.
258 ) = 0;
259
260 /// Pre-hash the collection with the given pg number and
261 /// expected number of objects in the collection.
262 virtual int _pre_hash_collection(
263 uint32_t pg_num,
264 uint64_t expected_num_objs
265 ) = 0;
266
267 /// @see CollectionIndex
268 virtual int _collection_list_partial(
269 const ghobject_t &start,
270 const ghobject_t &end,
271 int max_count,
272 std::vector<ghobject_t> *ls,
273 ghobject_t *next
274 ) = 0;
275
276 protected:
277
278 /* Non-virtual utility methods */
279
280 /// Sync a subdirectory
281 int fsync_dir(
282 const std::vector<std::string> &path ///< [in] Path to sync
283 ); ///< @return Error Code, 0 on success
284
285 /// Link an object from from into to
286 int link_object(
287 const std::vector<std::string> &from, ///< [in] Source subdirectory.
288 const std::vector<std::string> &to, ///< [in] Dest subdirectory.
289 const ghobject_t &oid, ///< [in] Object to move.
290 const std::string &from_short_name ///< [in] Mangled filename of oid.
291 ); ///< @return Error Code, 0 on success
292
293 /**
294 * Efficiently remove objects from a subdirectory
295 *
296 * remove_object invalidates mangled names in the directory requiring
297 * the mangled name of each additional object to be looked up a second
298 * time. remove_objects removes the need for additional lookups
299 *
300 * @param [in] dir Directory from which to remove.
301 * @param [in] map of objects to remove to mangle names
302 * @param [in,out] map of filenames to objects
303 * @return Error Code, 0 on success.
304 */
305 int remove_objects(
306 const std::vector<std::string> &dir,
307 const std::map<std::string, ghobject_t> &to_remove,
308 std::map<std::string, ghobject_t> *remaining
309 );
310
311
312 /**
313 * Moves contents of from into to.
314 *
315 * Invalidates mangled names in to. If interrupted, all objects will be
316 * present in to before objects are removed from from. Ignores EEXIST
317 * while linking into to.
318 * @return Error Code, 0 on success
319 */
320 int move_objects(
321 const std::vector<std::string> &from, ///< [in] Source subdirectory.
322 const std::vector<std::string> &to ///< [in] Dest subdirectory.
323 );
324
325 /**
326 * Remove an object from from.
327 *
328 * Invalidates mangled names in from.
329 * @return Error Code, 0 on success
330 */
331 int remove_object(
332 const std::vector<std::string> &from, ///< [in] Directory from which to remove.
333 const ghobject_t &to_remove ///< [in] Object to remove.
334 );
335
336 /**
337 * Gets the filename corresponding to oid in from.
338 *
339 * The filename may differ between subdirectories. Furthermore,
340 * file creations ore removals in from may invalidate the name.
341 * @return Error code on failure, 0 on success
342 */
343 int get_mangled_name(
344 const std::vector<std::string> &from, ///< [in] Subdirectory
345 const ghobject_t &oid, ///< [in] Object
346 std::string *mangled_name, ///< [out] Filename
347 int *hardlink ///< [out] hardlink for this file, hardlink=0 mean no-exist
348 );
349
350 /// do move subdir from from to dest
351 static int move_subdir(
352 LFNIndex &from, ///< [in] from index
353 LFNIndex &dest, ///< [in] to index
354 const std::vector<std::string> &path, ///< [in] path containing dir
355 std::string dir ///< [in] dir to move
356 );
357
358 /// do move object from from to dest
359 static int move_object(
360 LFNIndex &from, ///< [in] from index
361 LFNIndex &dest, ///< [in] to index
362 const std::vector<std::string> &path, ///< [in] path to split
363 const std::pair<std::string, ghobject_t> &obj ///< [in] obj to move
364 );
365
366 /**
367 * Lists objects in to_list.
368 *
369 * @param [in] to_list Directory to list.
370 * @param [in] max_objects Max number to list.
371 * @param [in,out] handle Cookie for continuing the listing.
372 * Initialize to zero to start at the beginning of the directory.
373 * @param [out] out Mapping of listed object filenames to objects.
374 * @return Error code on failure, 0 on success
375 */
376 int list_objects(
377 const std::vector<std::string> &to_list,
378 int max_objects,
379 long *handle,
380 std::map<std::string, ghobject_t> *out
381 );
382
383 /// Lists subdirectories.
384 int list_subdirs(
385 const std::vector<std::string> &to_list, ///< [in] Directory to list.
386 std::vector<std::string> *out ///< [out] Subdirectories listed.
387 );
388
389 /// Create subdirectory.
390 int create_path(
391 const std::vector<std::string> &to_create ///< [in] Subdirectory to create.
392 );
393
394 /// Remove subdirectory.
395 int remove_path(
396 const std::vector<std::string> &to_remove ///< [in] Subdirectory to remove.
397 );
398
399 /// Check whether to_check exists.
400 int path_exists(
401 const std::vector<std::string> &to_check, ///< [in] Subdirectory to check.
402 int *exists ///< [out] 1 if it exists, 0 else
403 );
404
405 /// Save attr_value to attr_name attribute on path.
406 int add_attr_path(
407 const std::vector<std::string> &path, ///< [in] Path to modify.
408 const std::string &attr_name, ///< [in] Name of attribute.
409 ceph::buffer::list &attr_value ///< [in] Value to save.
410 );
411
412 /// Read into attr_value attribute attr_name on path.
413 int get_attr_path(
414 const std::vector<std::string> &path, ///< [in] Path to read.
415 const std::string &attr_name, ///< [in] Attribute to read.
416 ceph::buffer::list &attr_value ///< [out] Attribute value read.
417 );
418
419 /// Remove attr from path
420 int remove_attr_path(
421 const std::vector<std::string> &path, ///< [in] path from which to remove attr
422 const std::string &attr_name ///< [in] attr to remove
423 ); ///< @return Error code, 0 on success
424
425 private:
426 /* lfn translation functions */
427
428 /**
429 * Gets the version specific lfn attribute tag
430 */
431 const std::string &get_lfn_attr() const {
432 return lfn_attribute;
433 }
434 const std::string &get_alt_lfn_attr() const {
435 return lfn_alt_attribute;
436 }
437
438 /**
439 * Gets the filename corresponding to oid in path.
440 *
441 * @param [in] path Path in which to get filename for oid.
442 * @param [in] oid Object for which to get filename.
443 * @param [out] mangled_name Filename for oid, pass NULL if not needed.
444 * @param [out] full_path Fullpath for oid, pass NULL if not needed.
445 * @param [out] hardlink of this file, 0 mean no-exist, pass NULL if
446 * not needed
447 * @return Error Code, 0 on success.
448 */
449 int lfn_get_name(
450 const std::vector<std::string> &path,
451 const ghobject_t &oid,
452 std::string *mangled_name,
453 std::string *full_path,
454 int *hardlink
455 );
456
457 /// Adjusts path contents when oid is created at name mangled_name.
458 int lfn_created(
459 const std::vector<std::string> &path, ///< [in] Path to adjust.
460 const ghobject_t &oid, ///< [in] Object created.
461 const std::string &mangled_name ///< [in] Filename of created object.
462 );
463
464 /// Removes oid from path while adjusting path contents
465 int lfn_unlink(
466 const std::vector<std::string> &path, ///< [in] Path containing oid.
467 const ghobject_t &oid, ///< [in] Object to remove.
468 const std::string &mangled_name ///< [in] Filename of object to remove.
469 );
470
471 ///Transate a file into and ghobject_t.
472 int lfn_translate(
473 const std::vector<std::string> &path, ///< [in] Path containing the file.
474 const std::string &short_name, ///< [in] Filename to translate.
475 ghobject_t *out ///< [out] Object found.
476 ); ///< @return Negative error code on error, 0 if not an object, 1 else
477
478 /* manglers/demanglers */
479 /// Filters object filenames
480 bool lfn_is_object(
481 const std::string &short_name ///< [in] Filename to check
482 ); ///< True if short_name is an object, false otherwise
483
484 /// Filters subdir filenames
485 bool lfn_is_subdir(
486 const std::string &short_name, ///< [in] Filename to check.
487 std::string *demangled_name ///< [out] Demangled subdir name.
488 ); ///< @return True if short_name is a subdir, false otherwise
489
490 /// Generate object name
491 std::string lfn_generate_object_name_keyless(
492 const ghobject_t &oid ///< [in] Object for which to generate.
493 ); ///< @return Generated object name.
494
495 /// Generate object name
496 std::string lfn_generate_object_name_poolless(
497 const ghobject_t &oid ///< [in] Object for which to generate.
498 ); ///< @return Generated object name.
499
500 /// Generate object name
501 static std::string lfn_generate_object_name_current(
502 const ghobject_t &oid ///< [in] Object for which to generate.
503 ); ///< @return Generated object name.
504
505 /// Generate object name
506 std::string lfn_generate_object_name(
507 const ghobject_t &oid ///< [in] Object for which to generate.
508 ) {
509 if (index_version == HASH_INDEX_TAG)
510 return lfn_generate_object_name_keyless(oid);
511 if (index_version == HASH_INDEX_TAG_2)
512 return lfn_generate_object_name_poolless(oid);
513 else
514 return lfn_generate_object_name_current(oid);
515 } ///< @return Generated object name.
516
517 /// Parse object name
518 int lfn_parse_object_name_keyless(
519 const std::string &long_name, ///< [in] Name to parse
520 ghobject_t *out ///< [out] Resulting Object
521 ); ///< @return True if successful, False otherwise.
522
523 /// Parse object name
524 int lfn_parse_object_name_poolless(
525 const std::string &long_name, ///< [in] Name to parse
526 ghobject_t *out ///< [out] Resulting Object
527 ); ///< @return True if successful, False otherwise.
528
529 /// Parse object name
530 int lfn_parse_object_name(
531 const std::string &long_name, ///< [in] Name to parse
532 ghobject_t *out ///< [out] Resulting Object
533 ); ///< @return True if successful, False otherwise.
534
535 /// Checks whether short_name is a hashed filename.
536 bool lfn_is_hashed_filename(
537 const std::string &short_name ///< [in] Name to check.
538 ); ///< @return True if short_name is hashed, False otherwise.
539
540 /// Checks whether long_name must be hashed.
541 bool lfn_must_hash(
542 const std::string &long_name ///< [in] Name to check.
543 ); ///< @return True if long_name must be hashed, False otherwise.
544
545 /// Generate hashed name.
546 std::string lfn_get_short_name(
547 const ghobject_t &oid, ///< [in] Object for which to generate.
548 int i ///< [in] Index of hashed name to generate.
549 ); ///< @return Hashed filename.
550
551 /* other common methods */
552 /// Gets the base path
553 const std::string &get_base_path(); ///< @return Index base_path
554
555 /// Get full path the subdir
556 std::string get_full_path_subdir(
557 const std::vector<std::string> &rel ///< [in] The subdir.
558 ); ///< @return Full path to rel.
559
560 /// Get full path to object
561 std::string get_full_path(
562 const std::vector<std::string> &rel, ///< [in] Path to object.
563 const std::string &name ///< [in] Filename of object.
564 ); ///< @return Fullpath to object at name in rel.
565
566 /// Get mangled path component
567 std::string mangle_path_component(
568 const std::string &component ///< [in] Component to mangle
569 ); /// @return Mangled component
570
571 /// Demangle component
572 std::string demangle_path_component(
573 const std::string &component ///< [in] Subdir name to demangle
574 ); ///< @return Demangled path component.
575
576 /// Decompose full path into object name and filename.
577 int decompose_full_path(
578 const char *in, ///< [in] Full path to object.
579 std::vector<std::string> *out, ///< [out] Path to object at in.
580 ghobject_t *oid, ///< [out] Object at in.
581 std::string *shortname ///< [out] Filename of object at in.
582 ); ///< @return Error Code, 0 on success.
583
584 /// Mangle attribute name
585 std::string mangle_attr_name(
586 const std::string &attr ///< [in] Attribute to mangle.
587 ); ///< @return Mangled attribute name.
588
589 /// checks whether long_name could hash to short_name
590 bool short_name_matches(
591 const char *short_name, ///< [in] name to check against
592 const char *cand_long_name ///< [in] candidate long name
593 );
594
595 /// Builds hashed filename
596 void build_filename(
597 const char *old_filename, ///< [in] Filename to convert.
598 int i, ///< [in] Index of hash.
599 char *filename, ///< [out] Resulting filename.
600 int len ///< [in] Size of buffer for filename
601 ); ///< @return Error Code, 0 on success
602
603 /// Get hash of filename
604 int hash_filename(
605 const char *filename, ///< [in] Filename to hash.
606 char *hash, ///< [out] Hash of filename.
607 int len ///< [in] Size of hash buffer.
608 ); ///< @return Error Code, 0 on success.
609
610 friend class TestWrapLFNIndex;
611 };
612 typedef LFNIndex::IndexedPath IndexedPath;
613
614 #endif