xref: /6.6.0/forestdb/src/filemgr.h (revision 56236603)
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2010 Couchbase, Inc
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17
18#ifndef _JSAHN_FILEMGR_H
19#define _JSAHN_FILEMGR_H
20
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <stdint.h>
24#include <errno.h>
25
26#ifdef _ASYNC_IO
27#if !defined(WIN32) && !defined(_WIN32)
28#include <libaio.h>
29#include <sys/time.h>
30#endif
31#endif
32
33#include "libforestdb/fdb_errors.h"
34
35#include "atomic.h"
36#include "internal_types.h"
37#include "common.h"
38#include "hash.h"
39#include "partiallock.h"
40#include "atomic.h"
41#include "checksum.h"
42#include "filemgr_ops.h"
43#include "encryption.h"
44#include "superblock.h"
45
46#ifdef __cplusplus
47extern "C" {
48#endif
49
50#define FILEMGR_SYNC 0x01
51#define FILEMGR_READONLY 0x02
52#define FILEMGR_ROLLBACK_IN_PROG 0x04
53#define FILEMGR_CREATE 0x08
54#define FILEMGR_REMOVAL_IN_PROG 0x10
55#define FILEMGR_CREATE_CRC32 0x20 // Used in testing upgrade path
56#define FILEMGR_CANCEL_COMPACTION 0x40 // Cancel the compaction
57#define FILEMGR_SUCCESSFULLY_COMPACTED 0x80 // Compaction is done
58
59struct filemgr_config {
60
61    filemgr_config& operator=(const filemgr_config& config) {
62        blocksize = config.blocksize;
63        ncacheblock = config.ncacheblock;
64        flag = config.flag;
65        seqtree_opt = config.seqtree_opt;
66        chunksize = config.chunksize;
67        options = config.options;
68        prefetch_duration = config.prefetch_duration;
69        num_wal_shards = config.num_wal_shards;
70        num_bcache_shards = config.num_bcache_shards;
71        encryption_key = config.encryption_key;
72        atomic_store_uint64_t(&block_reusing_threshold,
73                              atomic_get_uint64_t(&config.block_reusing_threshold,
74                                                  std::memory_order_relaxed),
75                              std::memory_order_relaxed);
76        atomic_store_uint64_t(&num_keeping_headers,
77                              atomic_get_uint64_t(&config.num_keeping_headers,
78                                                  std::memory_order_relaxed),
79                              std::memory_order_relaxed);
80        return *this;
81    }
82
83    // TODO: Move these variables to private members as we refactor the code in C++.
84    int blocksize;
85    int ncacheblock;
86    int flag;
87    int chunksize;
88    uint8_t options;
89    uint8_t seqtree_opt;
90    uint64_t prefetch_duration;
91    uint16_t num_wal_shards;
92    uint16_t num_bcache_shards;
93    fdb_encryption_key encryption_key;
94    // Stale block reusing threshold
95    atomic_uint64_t block_reusing_threshold;
96    // Number of the last commit headders whose stale blocks should
97    // be kept for snapshot readers.
98    atomic_uint64_t num_keeping_headers;
99};
100
101#ifndef _LATENCY_STATS
102#define LATENCY_STAT_START()
103#define LATENCY_STAT_END(file, type)
104#else
105#define LATENCY_STAT_START() \
106     uint64_t begin=get_monotonic_ts();
107#define LATENCY_STAT_END(file, type)\
108    do {\
109        uint64_t end = get_monotonic_ts();\
110        filemgr_update_latency_stat(file, type, ts_diff(begin, end));} while(0)
111
112struct latency_stat {
113    atomic_uint32_t lat_min;
114    atomic_uint32_t lat_max;
115    atomic_uint64_t lat_sum;
116    atomic_uint64_t lat_num;
117};
118
119#endif // _LATENCY_STATS
120
121struct async_io_handle {
122#ifdef _ASYNC_IO
123#if !defined(WIN32) && !defined(_WIN32)
124    struct iocb **ioq;
125    struct io_event *events;
126    io_context_t ioctx;
127#endif
128#endif
129    uint8_t *aio_buf;
130    uint64_t *offset_array;
131    size_t queue_depth;
132    size_t block_size;
133    int fd;
134};
135
136typedef int filemgr_fs_type_t;
137enum {
138    FILEMGR_FS_NO_COW = 0x01,
139    FILEMGR_FS_EXT4_WITH_COW = 0x02,
140    FILEMGR_FS_BTRFS = 0x03
141};
142
143struct filemgr_buffer{
144    void *block;
145    bid_t lastbid;
146};
147
148typedef uint16_t filemgr_header_len_t;
149typedef uint64_t filemgr_magic_t;
150typedef uint64_t filemgr_header_revnum_t;
151
152struct filemgr_header{
153    filemgr_header_len_t size;
154    filemgr_header_revnum_t revnum;
155    atomic_uint64_t seqnum;
156    atomic_uint64_t bid;
157    struct kvs_ops_stat op_stat; // op stats for default KVS
158    struct kvs_stat stat; // stats for the default KVS
159    void *data;
160};
161
162typedef uint8_t filemgr_prefetch_status_t;
163enum {
164    FILEMGR_PREFETCH_IDLE = 0,
165    FILEMGR_PREFETCH_RUNNING = 1,
166    FILEMGR_PREFETCH_ABORT = 2
167};
168
169#define DLOCK_MAX (41) /* a prime number */
170struct wal;
171struct fnamedic_item;
172struct kvs_header;
173
174typedef struct {
175    mutex_t mutex;
176    bool locked;
177} mutex_lock_t;
178
179struct filemgr {
180    char *filename; // Current file name.
181    atomic_uint32_t ref_count;
182    uint8_t fflags;
183    uint16_t filename_len;
184    uint32_t blocksize;
185    int fd;
186    atomic_uint64_t pos;
187    atomic_uint64_t last_commit;
188    atomic_uint64_t last_writable_bmp_revnum;
189    atomic_uint64_t num_invalidated_blocks;
190    atomic_uint8_t io_in_prog;
191    struct wal *wal;
192    struct filemgr_header header;
193    struct filemgr_ops *ops;
194    struct hash_elem e;
195    atomic_uint8_t status;
196    struct filemgr_config *config;
197
198    char *old_filename;                 // Old file name before compaction
199    char *new_filename;                 // New file name after compaction
200
201    std::atomic<struct fnamedic_item *> bcache;
202    fdb_txn global_txn;
203    bool in_place_compaction;
204    filemgr_fs_type_t fs_type;
205    struct kvs_header *kv_header;
206    void (*free_kv_header)(struct filemgr *file); // callback function
207    atomic_uint32_t throttling_delay;
208
209    // variables related to prefetching
210    atomic_uint8_t prefetch_status;
211    thread_t prefetch_tid;
212
213    // File format version
214    filemgr_magic_t version;
215
216    // superblock
217    struct superblock *sb;
218
219#ifdef _LATENCY_STATS
220    struct latency_stat lat_stats[FDB_LATENCY_NUM_STATS];
221#endif //_LATENCY_STATS
222
223    // spin lock for small region
224    spin_t lock;
225
226    // lock for data consistency
227#ifdef __FILEMGR_DATA_PARTIAL_LOCK
228    struct plock plock;
229#elif defined(__FILEMGR_DATA_MUTEX_LOCK)
230    mutex_t data_mutex[DLOCK_MAX];
231#else
232    spin_t data_spinlock[DLOCK_MAX];
233#endif //__FILEMGR_DATA_PARTIAL_LOCK
234
235    // mutex for synchronization among multiple writers.
236    mutex_lock_t writer_lock;
237
238    // CRC the file is using.
239    crc_mode_e crc_mode;
240
241    encryptor encryption;
242
243    // temporary in-memory list of stale blocks
244    struct list *stale_list;
245    // in-memory clone of system docs for reusable block info
246    // (they are pointed to by stale-block-tree)
247    struct avl_tree stale_info_tree;
248    // temporary tree for merging stale regions
249    struct avl_tree mergetree;
250    std::atomic<bool> stale_info_tree_loaded;
251
252    // in-memory index for a set of dirty index block updates
253    struct avl_tree dirty_update_idx;
254    // counter for the set of dirty index updates
255    atomic_uint64_t dirty_update_counter;
256    // latest dirty (immutable but not committed yet) update
257    struct filemgr_dirty_update_node *latest_dirty_update;
258    // spin lock for dirty_update_idx
259    spin_t dirty_update_lock;
260
261    /**
262     * Index for fdb_file_handle belonging to the same filemgr handle.
263     */
264    struct avl_tree fhandle_idx;
265    /**
266     * Spin lock for file handle index.
267     */
268    spin_t fhandle_idx_lock;
269};
270
271struct filemgr_dirty_update_node {
272    union {
273        // AVL-tree element
274        struct avl_node avl;
275        // list element
276        struct list_elem le;
277    };
278    // ID from the counter number
279    uint64_t id;
280    // flag indicating if this set of dirty blocks can be accessible.
281    bool immutable;
282    // flag indicating if this set of dirty blocks are already copied to newer node.
283    bool expired;
284    // number of threads (snapshots) accessing this dirty block set.
285    atomic_uint32_t ref_count;
286    // dirty root node BID for ID tree
287    bid_t idtree_root;
288    // dirty root node BID for sequence tree
289    bid_t seqtree_root;
290    // index for dirty blocks
291    struct avl_tree dirty_blocks;
292};
293
294struct filemgr_dirty_update_block {
295    // AVL-tree element
296    struct avl_node avl;
297    // contents of the block
298    void *addr;
299    // Block ID
300    bid_t bid;
301    // flag indicating if this block is immutable
302    bool immutable;
303};
304
305typedef fdb_status (*register_file_removal_func)(struct filemgr *file,
306                                                 err_log_callback *log_callback);
307typedef bool (*check_file_removal_func)(const char *filename);
308
309typedef struct {
310    struct filemgr *file;
311    int rv;
312} filemgr_open_result;
313
314void filemgr_init(struct filemgr_config *config);
315void filemgr_set_lazy_file_deletion(bool enable,
316                                    register_file_removal_func regis_func,
317                                    check_file_removal_func check_func);
318
319/**
320 * Assign superblock operations.
321 *
322 * @param ops Set of superblock operations to be assigned.
323 * @return void.
324 */
325void filemgr_set_sb_operation(struct sb_ops ops);
326
327uint64_t filemgr_get_bcache_used_space(void);
328
329bool filemgr_set_kv_header(struct filemgr *file, struct kvs_header *kv_header,
330                           void (*free_kv_header)(struct filemgr *file));
331
332struct kvs_header* filemgr_get_kv_header(struct filemgr *file);
333
334size_t filemgr_get_ref_count(struct filemgr *file);
335
336INLINE void filemgr_incr_ref_count(struct filemgr *file) {
337    atomic_incr_uint32_t(&file->ref_count);
338}
339
340/**
341 * Get filemgr instance corresponding to the given file name.
342 *
343 * @param filename File name to find.
344 * @return filemgr instance. NULL if not found.
345 */
346struct filemgr* filemgr_get_instance(const char* filename);
347
348filemgr_open_result filemgr_open(char *filename,
349                                 struct filemgr_ops *ops,
350                                 struct filemgr_config *config,
351                                 err_log_callback *log_callback);
352
353uint64_t filemgr_update_header(struct filemgr *file,
354                               void *buf,
355                               size_t len,
356                               bool inc_revnum);
357filemgr_header_revnum_t filemgr_get_header_revnum(struct filemgr *file);
358
359fdb_seqnum_t filemgr_get_seqnum(struct filemgr *file);
360void filemgr_set_seqnum(struct filemgr *file, fdb_seqnum_t seqnum);
361
362INLINE bid_t filemgr_get_header_bid(struct filemgr *file)
363{
364    return ((file->header.size > 0) ?
365            atomic_get_uint64_t(&file->header.bid) : BLK_NOT_FOUND);
366}
367bid_t _filemgr_get_header_bid(struct filemgr *file);
368void* filemgr_get_header(struct filemgr *file, void *buf, size_t *len,
369                         bid_t *header_bid, fdb_seqnum_t *seqnum,
370                         filemgr_header_revnum_t *header_revnum);
371
372/**
373 * Get the current bitmap revision number of superblock.
374 *
375 * @param file Pointer to filemgr handle.
376 * @return Current bitmap revision number.
377 */
378uint64_t filemgr_get_sb_bmp_revnum(struct filemgr *file);
379
380fdb_status filemgr_fetch_header(struct filemgr *file, uint64_t bid,
381                                void *buf, size_t *len, fdb_seqnum_t *seqnum,
382                                filemgr_header_revnum_t *header_revnum,
383                                uint64_t *deltasize, uint64_t *version,
384                                uint64_t *sb_bmp_revnum,
385                                err_log_callback *log_callback);
386uint64_t filemgr_fetch_prev_header(struct filemgr *file, uint64_t bid,
387                                   void *buf, size_t *len, fdb_seqnum_t *seqnum,
388                                   filemgr_header_revnum_t *revnum,
389                                   uint64_t *deltasize, uint64_t *version,
390                                   uint64_t *sb_bmp_revnum,
391                                   err_log_callback *log_callback);
392fdb_status filemgr_close(struct filemgr *file,
393                         bool cleanup_cache_onclose,
394                         const char *orig_file_name,
395                         err_log_callback *log_callback);
396
397void filemgr_remove_all_buffer_blocks(struct filemgr *file);
398void filemgr_free_func(struct hash_elem *h);
399
400INLINE bid_t filemgr_get_next_alloc_block(struct filemgr *file)
401{
402    return atomic_get_uint64_t(&file->pos) / file->blocksize;
403}
404bid_t filemgr_alloc(struct filemgr *file, err_log_callback *log_callback);
405void filemgr_alloc_multiple(struct filemgr *file, int nblock, bid_t *begin,
406                            bid_t *end, err_log_callback *log_callback);
407bid_t filemgr_alloc_multiple_cond(struct filemgr *file, bid_t nextbid, int nblock,
408                                  bid_t *begin, bid_t *end,
409                                  err_log_callback *log_callback);
410
411// Returns true if the block invalidated is from recent uncommited blocks
412bool filemgr_invalidate_block(struct filemgr *file, bid_t bid);
413bool filemgr_is_fully_resident(struct filemgr *file);
414// returns number of immutable blocks that remain in file
415uint64_t filemgr_flush_immutable(struct filemgr *file,
416                                 err_log_callback *log_callback);
417
418fdb_status filemgr_read(struct filemgr *file,
419                        bid_t bid, void *buf,
420                        err_log_callback *log_callback,
421                        bool read_on_cache_miss);
422
423fdb_status filemgr_write_offset(struct filemgr *file, bid_t bid, uint64_t offset,
424                          uint64_t len, void *buf, bool final_write,
425                          err_log_callback *log_callback);
426fdb_status filemgr_write(struct filemgr *file, bid_t bid, void *buf,
427                   err_log_callback *log_callback);
428ssize_t filemgr_write_blocks(struct filemgr *file, void *buf, unsigned num_blocks, bid_t start_bid);
429int filemgr_is_writable(struct filemgr *file, bid_t bid);
430
431void filemgr_remove_file(struct filemgr *file);
432
433INLINE void filemgr_set_io_inprog(struct filemgr *file)
434{
435    atomic_incr_uint8_t(&file->io_in_prog);
436}
437
438INLINE void filemgr_clear_io_inprog(struct filemgr *file)
439{
440    atomic_decr_uint8_t(&file->io_in_prog);
441}
442
443fdb_status filemgr_commit(struct filemgr *file, bool sync,
444                          err_log_callback *log_callback);
445/**
446 * Commit DB file, and write a DB header at the given BID.
447 *
448 * @param file Pointer to filemgr handle.
449 * @param bid ID of the block that DB header will be written. If this value is set to
450 *        BLK_NOT_FOUND, then DB header is appended at the end of the file.
451 * @param bmp_revnum Revision number of superblock's bitmap when this commit is called.
452 * @param sync Flag for calling fsync().
453 * @param log_callback Pointer to log callback function.
454 * @return FDB_RESULT_SUCCESS on success.
455 */
456fdb_status filemgr_commit_bid(struct filemgr *file, bid_t bid,
457                              uint64_t bmp_revnum, bool sync,
458                              err_log_callback *log_callback);
459fdb_status filemgr_sync(struct filemgr *file, bool sync_option,
460                        err_log_callback *log_callback);
461
462fdb_status filemgr_shutdown();
463void filemgr_update_file_status(struct filemgr *file, file_status_t status);
464
465/**
466 * Updates the old_filename and new_filename of the current instance,
467 * with the arguments (non-null) provided.
468 *
469 * Returns false if oldFileName has already been set.
470 */
471bool filemgr_update_file_linkage(struct filemgr *file,
472                                 const char *old_filename,
473                                 const char *new_filename);
474
475void filemgr_set_compaction_state(struct filemgr *old_file,
476                                  struct filemgr *new_file,
477                                  file_status_t status);
478void filemgr_remove_pending(struct filemgr *old_file,
479                            struct filemgr *new_file,
480                            err_log_callback *log_callback);
481
482/**
483 * Return name of the latency stat given its type.
484 * @param stat The type of the latency stat to be named.
485 */
486const char *filemgr_latency_stat_name(fdb_latency_stat_type stat);
487
488#ifdef _LATENCY_STATS
489/**
490 * Initialize a latency stats instance
491 *
492 * @param val Pointer to a latency stats instance to be initialized
493 */
494void filemgr_init_latency_stat(struct latency_stat *val);
495
496/**
497 * Destroy a latency stats instance
498 *
499 * @param val Pointer to a latency stats instance to be destroyed
500 */
501void filemgr_destroy_latency_stat(struct latency_stat *val);
502
503/**
504 * Migrate the latency stats from the source file to the destination file
505 *
506 * @param oldf Pointer to the source file manager
507 * @param newf Pointer to the destination file manager
508 */
509void filemgr_migrate_latency_stats(struct filemgr *src,
510                                   struct filemgr *dest);
511
512/**
513 * Update the latency stats for a given file manager
514 *
515 * @param file Pointer to the file manager whose latency stats need to be updated
516 * @param type Type of a latency stat to be updated
517 * @param val New value of a latency stat
518 */
519void filemgr_update_latency_stat(struct filemgr *file,
520                                 fdb_latency_stat_type type,
521                                 uint32_t val);
522
523/**
524 * Get the latency stats from a given file manager
525 *
526 * @param file Pointer to the file manager
527 * @param type Type of a latency stat to be retrieved
528 * @param stat Pointer to the stats instance to be populated
529 */
530void filemgr_get_latency_stat(struct filemgr *file,
531                              fdb_latency_stat_type type,
532                              fdb_latency_stat *stat);
533
534#ifdef _LATENCY_STATS_DUMP_TO_FILE
535/**
536 * Write all the latency stats for a given file manager to a stat log file
537 *
538 * @param file Pointer to the file manager
539 * @param log_callback Pointer to the log callback function
540 */
541void filemgr_dump_latency_stat(struct filemgr *file,
542                               err_log_callback *log_callback);
543
544#endif // _LATENCY_STATS_DUMP_TO_FILE
545#endif // _LATENCY_STATS
546
547struct kvs_ops_stat *filemgr_migrate_op_stats(struct filemgr *old_file,
548                                              struct filemgr *new_file,
549                                              struct kvs_info *kvs);
550fdb_status filemgr_destroy_file(char *filename,
551                                struct filemgr_config *config,
552                                struct hash *destroy_set);
553
554struct filemgr *filemgr_search_stale_links(struct filemgr *cur_file);
555typedef char *filemgr_redirect_hdr_func(struct filemgr *old_file,uint8_t *buf,
556                                        struct filemgr *new_file);
557
558char *filemgr_redirect_old_file(struct filemgr *very_old_file,
559                                struct filemgr *new_file,
560                                filemgr_redirect_hdr_func redirect_func);
561INLINE file_status_t filemgr_get_file_status(struct filemgr *file)
562{
563    return atomic_get_uint8_t(&file->status);
564}
565INLINE uint64_t filemgr_get_pos(struct filemgr *file)
566{
567    return atomic_get_uint64_t(&file->pos);
568}
569
570fdb_status filemgr_copy_file_range(struct filemgr *src_file,
571                                   struct filemgr *dst_file,
572                                   bid_t src_bid, bid_t dst_bid,
573                                   bid_t clone_len);
574
575bool filemgr_is_rollback_on(struct filemgr *file);
576void filemgr_set_rollback(struct filemgr *file, uint8_t new_val);
577
578/**
579 * Set the file manager's flag to cancel the compaction task that is currently running.
580 *
581 * @param file Pointer to the file manager instance
582 * @param cancel True if the compaction should be cancelled.
583 */
584void filemgr_set_cancel_compaction(struct filemgr *file, bool cancel);
585
586/**
587 * Return true if a compaction cancellation is requested.
588 *
589 * @param file Pointer to the file manager instance
590 * @return True if a compaction cancellation is requested.
591 */
592bool filemgr_is_compaction_cancellation_requested(struct filemgr *file);
593
594void filemgr_set_successfully_compacted(struct filemgr *file);
595bool filemgr_is_successfully_compacted(struct filemgr *file);
596
597void filemgr_set_in_place_compaction(struct filemgr *file,
598                                     bool in_place_compaction);
599bool filemgr_is_in_place_compaction_set(struct filemgr *file);
600
601void filemgr_mutex_openlock(struct filemgr_config *config);
602void filemgr_mutex_openunlock(void);
603
604void filemgr_mutex_lock(struct filemgr *file);
605bool filemgr_mutex_trylock(struct filemgr *file);
606void filemgr_mutex_unlock(struct filemgr *file);
607
608bool filemgr_is_commit_header(void *head_buffer, size_t blocksize);
609
610bool filemgr_is_cow_supported(struct filemgr *src, struct filemgr *dst);
611
612void filemgr_set_throttling_delay(struct filemgr *file, uint64_t delay_us);
613uint32_t filemgr_get_throttling_delay(struct filemgr *file);
614
615INLINE void filemgr_set_stale_list(struct filemgr *file,
616                            struct list *stale_list)
617{
618    file->stale_list = stale_list;
619}
620void filemgr_clear_stale_list(struct filemgr *file);
621void filemgr_clear_stale_info_tree(struct filemgr *file);
622void filemgr_clear_mergetree(struct filemgr *file);
623
624INLINE struct list * filemgr_get_stale_list(struct filemgr *file)
625{
626    return file->stale_list;
627}
628
629/**
630 * Add an item into stale-block list of the given 'file'.
631 *
632 * @param file Pointer to file handle.
633 * @param pos Byte offset to the beginning of the stale region.
634 * @param len Length of the stale region.
635 * @return void.
636 */
637void filemgr_add_stale_block(struct filemgr *file,
638                             bid_t pos,
639                             size_t len);
640
641/**
642 * Calculate the actual space (including block markers) used for the given document
643 * data, and return the list of regions to be marked as stale (if the given document
644 * is not physically consecutive, more than one regions will be returned).
645 *
646 * @param file Pointer to file handle.
647 * @param offset Byte offset to the beginning of the data.
648 * @param length Length of the data.
649 * @return List of stale regions.
650 */
651struct stale_regions filemgr_actual_stale_regions(struct filemgr *file,
652                                                  bid_t offset,
653                                                  size_t length);
654
655/**
656 * Mark the given region (offset, length) as stale.
657 * This function automatically calculates the additional space used for block
658 * markers or block matadata, by internally calling filemgr_actual_stale_regions().
659 *
660 * @param file Pointer to file handle.
661 * @param offset Byte offset to the beginning of the data.
662 * @param length Length of the data.
663 * @return void.
664 */
665void filemgr_mark_stale(struct filemgr *file,
666                        bid_t offset,
667                        size_t length);
668
669/**
670 * The node structure of fhandle index.
671 */
672struct filemgr_fhandle_idx_node {
673    /**
674     * Void pointer to file handle.
675     */
676    void *fhandle;
677    /**
678     * AVL tree element.
679     */
680    struct avl_node avl;
681};
682
683/**
684 * Add a FDB file handle into the superblock's global index.
685 *
686 * @param file Pointer to filemgr handle.
687 * @param fhandle Pointer to FDB file handle.
688 * @return True if successfully added.
689 */
690bool filemgr_fhandle_add(struct filemgr *file, void *fhandle);
691
692/**
693 * Remove a FDB file handle from the superblock's global index.
694 *
695 * @param file Pointer to filemgr handle.
696 * @param fhandle Pointer to FDB file handle.
697 * @return True if successfully removed.
698 */
699bool filemgr_fhandle_remove(struct filemgr *file, void *fhandle);
700
701/**
702 * Initialize global structures for dirty update management.
703 *
704 * @param file Pointer to filemgr handle.
705 * @return void.
706 */
707void filemgr_dirty_update_init(struct filemgr *file);
708
709/**
710 * Free global structures for dirty update management.
711 *
712 * @param file Pointer to filemgr handle.
713 * @return void.
714 */
715void filemgr_dirty_update_free(struct filemgr *file);
716
717/**
718 * Create a new dirty update entry.
719 *
720 * @param file Pointer to filemgr handle.
721 * @return Newly created dirty update entry.
722 */
723struct filemgr_dirty_update_node *filemgr_dirty_update_new_node(struct filemgr *file);
724
725/**
726 * Return the latest complete (i.e., immutable) dirty update entry. Note that a
727 * dirty update that is being updated by a writer thread will not be returned.
728 *
729 * @param file Pointer to filemgr handle.
730 * @return Latest dirty update entry.
731 */
732struct filemgr_dirty_update_node *filemgr_dirty_update_get_latest(struct filemgr *file);
733
734/**
735 * Increase the reference counter for the given dirty update entry.
736 *
737 * @param node Pointer to dirty update entry to increase reference counter.
738 * @return void.
739 */
740void filemgr_dirty_update_inc_ref_count(struct filemgr_dirty_update_node *node);
741
742/**
743 * Commit the latest complete dirty update entry and write back all updated
744 * blocks into DB file. This API will remove all complete (i.e., immutable)
745 * dirty update entries whose reference counter is zero.
746 *
747 * @param file Pointer to filemgr handle.
748 * @param commit_node Pointer to dirty update entry to be flushed.
749 * @param log_callback Pointer to the log callback function.
750 * @return void.
751 */
752void filemgr_dirty_update_commit(struct filemgr *file,
753                                 struct filemgr_dirty_update_node *commit_node,
754                                 err_log_callback *log_callback);
755
756/**
757 * Complete the given dirty update entry and make it immutable. This API will
758 * remove all complete (i.e., immutable) dirty update entries which are prior
759 * than the given dirty update entry and whose reference counter is zero.
760 *
761 * @param file Pointer to filemgr handle.
762 * @param node Pointer to dirty update entry to complete.
763 * @param node Pointer to previous dirty update entry.
764 * @return void.
765 */
766void filemgr_dirty_update_set_immutable(struct filemgr *file,
767                                        struct filemgr_dirty_update_node *prev_node,
768                                        struct filemgr_dirty_update_node *node);
769
770/**
771 * Remove a dirty update entry and discard all dirty blocks from memory.
772 *
773 * @param file Pointer to filemgr handle.
774 * @param node Pointer to dirty update entry to be removed.
775 * @return void.
776 */
777void filemgr_dirty_update_remove_node(struct filemgr *file,
778                                      struct filemgr_dirty_update_node *node);
779
780/**
781 * Close a dirty update entry. This API will remove all complete (i.e., immutable)
782 * dirty update entries except for the last immutable update entry.
783 *
784 * @param file Pointer to filemgr handle.
785 * @param node Pointer to dirty update entry to be closed.
786 * @return void.
787 */
788void filemgr_dirty_update_close_node(struct filemgr *file,
789                                     struct filemgr_dirty_update_node *node);
790
791/**
792 * Set dirty root nodes for the given dirty update entry.
793 *
794 * @param file Pointer to filemgr handle.
795 * @param node Pointer to dirty update entry.
796 * @param dirty_idtree_root BID of ID tree root node.
797 * @param dirty_seqtree_root BID of sequence tree root node.
798 * @return void.
799 */
800INLINE void filemgr_dirty_update_set_root(struct filemgr *file,
801                                          struct filemgr_dirty_update_node *node,
802                                          bid_t dirty_idtree_root,
803                                          bid_t dirty_seqtree_root)
804{
805    if (node) {
806        node->idtree_root = dirty_idtree_root;
807        node->seqtree_root = dirty_seqtree_root;
808    }
809}
810
811/**
812 * Get dirty root nodes for the given dirty update entry.
813 *
814 * @param file Pointer to filemgr handle.
815 * @param node Pointer to dirty update entry.
816 * @param dirty_idtree_root Pointer to the BID of ID tree root node.
817 * @param dirty_seqtree_root Pointer to the BID of sequence tree root node.
818 * @return void.
819 */
820INLINE void filemgr_dirty_update_get_root(struct filemgr *file,
821                                          struct filemgr_dirty_update_node *node,
822                                          bid_t *dirty_idtree_root,
823                                          bid_t *dirty_seqtree_root)
824{
825    if (node) {
826        *dirty_idtree_root = node->idtree_root;
827        *dirty_seqtree_root = node->seqtree_root;
828    } else {
829        *dirty_idtree_root = *dirty_seqtree_root = BLK_NOT_FOUND;
830    }
831}
832
833/**
834 * Write a dirty block into the given dirty update entry.
835 *
836 * @param file Pointer to filemgr handle.
837 * @param bid BID of the block to be written.
838 * @param buf Pointer to the buffer containing the data to be written.
839 * @param node Pointer to the dirty update entry.
840 * @param log_callback Pointer to the log callback function.
841 * @return FDB_RESULT_SUCCESS on success.
842 */
843fdb_status filemgr_write_dirty(struct filemgr *file,
844                               bid_t bid,
845                               void *buf,
846                               struct filemgr_dirty_update_node *node,
847                               err_log_callback *log_callback);
848
849/**
850 * Read a block through the given dirty update entries. It first tries to read
851 * the block from the writer's (which is being updated) dirty update entry,
852 * and then tries to read it from the reader's (which already became immutable)
853 * dirty update entry. If the block doesn't exist in both entries, then it reads
854 * the block from DB file.
855 *
856 * @param file Pointer to filemgr handle.
857 * @param bid BID of the block to be read.
858 * @param buf Pointer to the buffer where the read data will be copied.
859 * @param node_reader Pointer to the immutable dirty update entry.
860 * @param node_writer Pointer to the mutable dirty update entry.
861 * @param log_callback Pointer to the log callback function.
862 * @param read_on_cache_miss True if we want to read the block from file after
863 *        cache miss.
864 * @return FDB_RESULT_SUCCESS on success.
865 */
866fdb_status filemgr_read_dirty(struct filemgr *file,
867                              bid_t bid,
868                              void *buf,
869                              struct filemgr_dirty_update_node *node_reader,
870                              struct filemgr_dirty_update_node *node_writer,
871                              err_log_callback *log_callback,
872                              bool read_on_cache_miss);
873
874void _kvs_stat_set(struct filemgr *file,
875                   fdb_kvs_id_t kv_id,
876                   struct kvs_stat stat);
877void _kvs_stat_update_attr(struct filemgr *file,
878                           fdb_kvs_id_t kv_id,
879                           kvs_stat_attr_t attr,
880                           int delta);
881int _kvs_stat_get_kv_header(struct kvs_header *kv_header,
882                            fdb_kvs_id_t kv_id,
883                            struct kvs_stat *stat);
884int _kvs_stat_get(struct filemgr *file,
885                  fdb_kvs_id_t kv_id,
886                  struct kvs_stat *stat);
887uint64_t _kvs_stat_get_sum(struct filemgr *file,
888                           kvs_stat_attr_t attr);
889int _kvs_ops_stat_get_kv_header(struct kvs_header *kv_header,
890                                fdb_kvs_id_t kv_id,
891                                struct kvs_ops_stat *stat);
892int _kvs_ops_stat_get(struct filemgr *file,
893                      fdb_kvs_id_t kv_id,
894                      struct kvs_ops_stat *stat);
895
896void _init_op_stats(struct kvs_ops_stat *stat);
897struct kvs_ops_stat *filemgr_get_ops_stats(struct filemgr *file,
898                                          struct kvs_info *info);
899
900/**
901 * Convert a given errno value to the corresponding fdb_status value.
902 *
903 * @param errno_value errno value
904 * @param default_status Default fdb_status value to be returned if
905 *        there is no corresponding fdb_status value for a given errno value.
906 * @return fdb_status value that corresponds to a given errno value
907 */
908fdb_status convert_errno_to_fdb_status(int errno_value,
909                                       fdb_status default_status);
910
911fdb_status filemgr_invalidate_dbheader(struct filemgr *file, bid_t bid, err_log_callback *log_callback);
912#ifdef __cplusplus
913}
914#endif
915
916#endif
917