]> git.proxmox.com Git - ceph.git/blame - ceph/src/os/filestore/LFNIndex.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / os / filestore / LFNIndex.h
CommitLineData
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) 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>
7c673cae
FG
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 *
11fdf7f2 44 * Synchronization: Calling code must ensure that there are no object
7c673cae
FG
45 * creations or deletions during the lifetime of a Path object (except
46 * of an object at that path).
47 *
11fdf7f2 48 * Unless otherwise noted, methods which return an int return 0 on success
7c673cae
FG
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(); \
11fdf7f2 59 ceph_assert(r == 0); \
7c673cae
FG
60 } \
61 { x } \
62 out: \
63 complete_inject_failure(); \
64 return r; \
f64942e4 65 } catch (RetryException&) { \
7c673cae
FG
66 failed = true; \
67 } catch (...) { \
68 ceph_abort(); \
69 } \
70 } \
71 return -1; \
72 } \
73
74
75
76class 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.
f67539c2 90 static const std::string FILENAME_COOKIE;
7c673cae 91 /// Name of LFN attribute for storing full name.
f67539c2 92 static const std::string LFN_ATTR;
7c673cae 93 /// Prefix for subdir index attributes.
f67539c2 94 static const std::string PHASH_ATTR_PREFIX;
7c673cae 95 /// Prefix for index subdirectories.
f67539c2 96 static const std::string SUBDIR_PREFIX;
7c673cae
FG
97
98 /// Path to Index base.
f67539c2 99 const std::string base_path;
7c673cae
FG
100
101protected:
102 const uint32_t index_version;
103
104 /// true if retry injection is enabled
f67539c2 105 struct RetryException : public std::exception {};
7c673cae
FG
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
122private:
f67539c2 123 std::string lfn_attribute, lfn_alt_attribute;
7c673cae
FG
124 coll_t collection;
125
126public:
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);
f67539c2
TL
147 lfn_attribute = LFN_ATTR + std::string(buf);
148 lfn_alt_attribute = LFN_ATTR + std::string(buf) + "-alt";
7c673cae
FG
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,
f67539c2 192 std::vector<ghobject_t> *ls,
7c673cae
FG
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;
11fdf7f2
TL
201 virtual int _merge(
202 uint32_t bits, //< [in] bits for target
203 CollectionIndex* dest //< [in] destination index
204 ) = 0;
7c673cae
FG
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
11fdf7f2
TL
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
7c673cae
FG
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
235protected:
236 virtual int _init() = 0;
237
238 /// Will be called upon object creation
239 virtual int _created(
f67539c2 240 const std::vector<std::string> &path, ///< [in] Path to subdir.
7c673cae 241 const ghobject_t &oid, ///< [in] Object created.
f67539c2 242 const std::string &mangled_name ///< [in] Mangled filename.
7c673cae
FG
243 ) = 0;
244
245 /// Will be called to remove an object
246 virtual int _remove(
f67539c2 247 const std::vector<std::string> &path, ///< [in] Path to subdir.
7c673cae 248 const ghobject_t &oid, ///< [in] Object to remove.
f67539c2 249 const std::string &mangled_name ///< [in] Mangled filename.
7c673cae
FG
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.
f67539c2
TL
255 std::vector<std::string> *path, ///< [out] Path to the object.
256 std::string *mangled_name, ///< [out] Mangled filename.
7c673cae
FG
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,
f67539c2 272 std::vector<ghobject_t> *ls,
7c673cae
FG
273 ghobject_t *next
274 ) = 0;
275
276protected:
277
278 /* Non-virtual utility methods */
279
280 /// Sync a subdirectory
281 int fsync_dir(
f67539c2 282 const std::vector<std::string> &path ///< [in] Path to sync
7c673cae
FG
283 ); ///< @return Error Code, 0 on success
284
285 /// Link an object from from into to
286 int link_object(
f67539c2
TL
287 const std::vector<std::string> &from, ///< [in] Source subdirectory.
288 const std::vector<std::string> &to, ///< [in] Dest subdirectory.
7c673cae 289 const ghobject_t &oid, ///< [in] Object to move.
f67539c2 290 const std::string &from_short_name ///< [in] Mangled filename of oid.
7c673cae
FG
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(
f67539c2
TL
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
7c673cae
FG
309 );
310
311
312 /**
313 * Moves contents of from into to.
314 *
11fdf7f2 315 * Invalidates mangled names in to. If interrupted, all objects will be
7c673cae
FG
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(
f67539c2
TL
321 const std::vector<std::string> &from, ///< [in] Source subdirectory.
322 const std::vector<std::string> &to ///< [in] Dest subdirectory.
7c673cae
FG
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(
f67539c2 332 const std::vector<std::string> &from, ///< [in] Directory from which to remove.
7c673cae
FG
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(
f67539c2 344 const std::vector<std::string> &from, ///< [in] Subdirectory
7c673cae 345 const ghobject_t &oid, ///< [in] Object
f67539c2 346 std::string *mangled_name, ///< [out] Filename
7c673cae
FG
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
f67539c2
TL
354 const std::vector<std::string> &path, ///< [in] path containing dir
355 std::string dir ///< [in] dir to move
7c673cae
FG
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
f67539c2
TL
362 const std::vector<std::string> &path, ///< [in] path to split
363 const std::pair<std::string, ghobject_t> &obj ///< [in] obj to move
7c673cae
FG
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(
f67539c2 377 const std::vector<std::string> &to_list,
7c673cae
FG
378 int max_objects,
379 long *handle,
f67539c2 380 std::map<std::string, ghobject_t> *out
7c673cae
FG
381 );
382
383 /// Lists subdirectories.
384 int list_subdirs(
f67539c2
TL
385 const std::vector<std::string> &to_list, ///< [in] Directory to list.
386 std::vector<std::string> *out ///< [out] Subdirectories listed.
7c673cae
FG
387 );
388
389 /// Create subdirectory.
390 int create_path(
f67539c2 391 const std::vector<std::string> &to_create ///< [in] Subdirectory to create.
7c673cae
FG
392 );
393
394 /// Remove subdirectory.
395 int remove_path(
f67539c2 396 const std::vector<std::string> &to_remove ///< [in] Subdirectory to remove.
7c673cae
FG
397 );
398
399 /// Check whether to_check exists.
400 int path_exists(
f67539c2 401 const std::vector<std::string> &to_check, ///< [in] Subdirectory to check.
7c673cae
FG
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(
f67539c2
TL
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.
7c673cae
FG
410 );
411
11fdf7f2 412 /// Read into attr_value attribute attr_name on path.
7c673cae 413 int get_attr_path(
f67539c2
TL
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.
7c673cae
FG
417 );
418
419 /// Remove attr from path
420 int remove_attr_path(
f67539c2
TL
421 const std::vector<std::string> &path, ///< [in] path from which to remove attr
422 const std::string &attr_name ///< [in] attr to remove
7c673cae
FG
423 ); ///< @return Error code, 0 on success
424
425private:
426 /* lfn translation functions */
427
428 /**
429 * Gets the version specific lfn attribute tag
430 */
f67539c2 431 const std::string &get_lfn_attr() const {
7c673cae
FG
432 return lfn_attribute;
433 }
f67539c2 434 const std::string &get_alt_lfn_attr() const {
7c673cae
FG
435 return lfn_alt_attribute;
436 }
437
438 /**
11fdf7f2 439 * Gets the filename corresponding to oid in path.
7c673cae
FG
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(
f67539c2 450 const std::vector<std::string> &path,
7c673cae 451 const ghobject_t &oid,
f67539c2
TL
452 std::string *mangled_name,
453 std::string *full_path,
7c673cae
FG
454 int *hardlink
455 );
456
457 /// Adjusts path contents when oid is created at name mangled_name.
458 int lfn_created(
f67539c2 459 const std::vector<std::string> &path, ///< [in] Path to adjust.
7c673cae 460 const ghobject_t &oid, ///< [in] Object created.
f67539c2 461 const std::string &mangled_name ///< [in] Filename of created object.
7c673cae
FG
462 );
463
464 /// Removes oid from path while adjusting path contents
465 int lfn_unlink(
f67539c2 466 const std::vector<std::string> &path, ///< [in] Path containing oid.
7c673cae 467 const ghobject_t &oid, ///< [in] Object to remove.
f67539c2 468 const std::string &mangled_name ///< [in] Filename of object to remove.
7c673cae
FG
469 );
470
471 ///Transate a file into and ghobject_t.
472 int lfn_translate(
f67539c2
TL
473 const std::vector<std::string> &path, ///< [in] Path containing the file.
474 const std::string &short_name, ///< [in] Filename to translate.
7c673cae
FG
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(
f67539c2 481 const std::string &short_name ///< [in] Filename to check
7c673cae
FG
482 ); ///< True if short_name is an object, false otherwise
483
484 /// Filters subdir filenames
485 bool lfn_is_subdir(
f67539c2
TL
486 const std::string &short_name, ///< [in] Filename to check.
487 std::string *demangled_name ///< [out] Demangled subdir name.
7c673cae
FG
488 ); ///< @return True if short_name is a subdir, false otherwise
489
490 /// Generate object name
f67539c2 491 std::string lfn_generate_object_name_keyless(
7c673cae
FG
492 const ghobject_t &oid ///< [in] Object for which to generate.
493 ); ///< @return Generated object name.
494
495 /// Generate object name
f67539c2 496 std::string lfn_generate_object_name_poolless(
7c673cae
FG
497 const ghobject_t &oid ///< [in] Object for which to generate.
498 ); ///< @return Generated object name.
499
500 /// Generate object name
f67539c2 501 static std::string lfn_generate_object_name_current(
7c673cae
FG
502 const ghobject_t &oid ///< [in] Object for which to generate.
503 ); ///< @return Generated object name.
504
505 /// Generate object name
f67539c2 506 std::string lfn_generate_object_name(
7c673cae
FG
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(
f67539c2 519 const std::string &long_name, ///< [in] Name to parse
7c673cae 520 ghobject_t *out ///< [out] Resulting Object
11fdf7f2 521 ); ///< @return True if successful, False otherwise.
7c673cae
FG
522
523 /// Parse object name
524 int lfn_parse_object_name_poolless(
f67539c2 525 const std::string &long_name, ///< [in] Name to parse
7c673cae 526 ghobject_t *out ///< [out] Resulting Object
11fdf7f2 527 ); ///< @return True if successful, False otherwise.
7c673cae
FG
528
529 /// Parse object name
530 int lfn_parse_object_name(
f67539c2 531 const std::string &long_name, ///< [in] Name to parse
7c673cae 532 ghobject_t *out ///< [out] Resulting Object
11fdf7f2 533 ); ///< @return True if successful, False otherwise.
7c673cae
FG
534
535 /// Checks whether short_name is a hashed filename.
536 bool lfn_is_hashed_filename(
f67539c2 537 const std::string &short_name ///< [in] Name to check.
7c673cae
FG
538 ); ///< @return True if short_name is hashed, False otherwise.
539
540 /// Checks whether long_name must be hashed.
541 bool lfn_must_hash(
f67539c2 542 const std::string &long_name ///< [in] Name to check.
7c673cae
FG
543 ); ///< @return True if long_name must be hashed, False otherwise.
544
545 /// Generate hashed name.
f67539c2 546 std::string lfn_get_short_name(
7c673cae
FG
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
f67539c2 553 const std::string &get_base_path(); ///< @return Index base_path
7c673cae
FG
554
555 /// Get full path the subdir
f67539c2
TL
556 std::string get_full_path_subdir(
557 const std::vector<std::string> &rel ///< [in] The subdir.
7c673cae
FG
558 ); ///< @return Full path to rel.
559
560 /// Get full path to object
f67539c2
TL
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.
7c673cae
FG
564 ); ///< @return Fullpath to object at name in rel.
565
566 /// Get mangled path component
f67539c2
TL
567 std::string mangle_path_component(
568 const std::string &component ///< [in] Component to mangle
7c673cae
FG
569 ); /// @return Mangled component
570
571 /// Demangle component
f67539c2
TL
572 std::string demangle_path_component(
573 const std::string &component ///< [in] Subdir name to demangle
7c673cae
FG
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.
f67539c2 579 std::vector<std::string> *out, ///< [out] Path to object at in.
7c673cae 580 ghobject_t *oid, ///< [out] Object at in.
f67539c2 581 std::string *shortname ///< [out] Filename of object at in.
7c673cae
FG
582 ); ///< @return Error Code, 0 on success.
583
584 /// Mangle attribute name
f67539c2
TL
585 std::string mangle_attr_name(
586 const std::string &attr ///< [in] Attribute to mangle.
7c673cae
FG
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};
612typedef LFNIndex::IndexedPath IndexedPath;
613
614#endif