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