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