xref: /4.0.0/forestdb/src/filemgr.h (revision 17f72b63)
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
25#ifdef _ASYNC_IO
26#if !defined(WIN32) && !defined(_WIN32)
27#include <libaio.h>
28#include <sys/time.h>
29#endif
30#endif
31
32#include "libforestdb/fdb_errors.h"
33
34#include "internal_types.h"
35#include "common.h"
36#include "hash.h"
37#include "partiallock.h"
38#include "atomic.h"
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#define FILEMGR_SYNC 0x01
45#define FILEMGR_READONLY 0x02
46#define FILEMGR_ROLLBACK_IN_PROG 0x04
47#define FILEMGR_CREATE 0x08
48#define FILEMGR_REMOVAL_IN_PROG 0x10
49
50struct filemgr_config {
51    int blocksize;
52    int ncacheblock;
53    int flag;
54    int chunksize;
55    uint8_t options;
56    uint64_t prefetch_duration;
57    uint16_t num_wal_shards;
58    uint16_t num_bcache_shards;
59};
60
61struct async_io_handle {
62#ifdef _ASYNC_IO
63#if !defined(WIN32) && !defined(_WIN32)
64    struct iocb **ioq;
65    struct io_event *events;
66    io_context_t ioctx;
67#endif
68#endif
69    uint8_t *aio_buf;
70    uint64_t *offset_array;
71    size_t queue_depth;
72    size_t block_size;
73    int fd;
74};
75
76struct filemgr_ops {
77    int (*open)(const char *pathname, int flags, mode_t mode);
78    ssize_t (*pwrite)(int fd, void *buf, size_t count, cs_off_t offset);
79    ssize_t (*pread)(int fd, void *buf, size_t count, cs_off_t offset);
80    int (*close)(int fd);
81    cs_off_t (*goto_eof)(int fd);
82    cs_off_t (*file_size)(const char *filename);
83    int (*fdatasync)(int fd);
84    int (*fsync)(int fd);
85    void (*get_errno_str)(char *buf, size_t size);
86
87    // Async I/O operations
88    int (*aio_init)(struct async_io_handle *aio_handle);
89    int (*aio_prep_read)(struct async_io_handle *aio_handle, size_t aio_idx,
90                         size_t read_size, uint64_t offset);
91    int (*aio_submit)(struct async_io_handle *aio_handle, int num_subs);
92    int (*aio_getevents)(struct async_io_handle *aio_handle, int min,
93                         int max, unsigned int timeout);
94    int (*aio_destroy)(struct async_io_handle *aio_handle);
95};
96
97struct filemgr_buffer{
98    void *block;
99    bid_t lastbid;
100};
101
102typedef uint16_t filemgr_header_len_t;
103typedef uint64_t filemgr_magic_t;
104typedef uint64_t filemgr_header_revnum_t;
105
106struct filemgr_header{
107    filemgr_header_len_t size;
108    filemgr_header_revnum_t revnum;
109    volatile fdb_seqnum_t seqnum;
110    atomic_uint64_t bid;
111    atomic_uint64_t dirty_idtree_root; // for wal_flush_before_commit option
112    atomic_uint64_t dirty_seqtree_root; // for wal_flush_before_commit option
113    struct kvs_ops_stat op_stat; // op stats for default KVS
114    struct kvs_stat stat; // stats for the default KVS
115    void *data;
116};
117
118typedef uint8_t filemgr_prefetch_status_t;
119enum {
120    FILEMGR_PREFETCH_IDLE = 0,
121    FILEMGR_PREFETCH_RUNNING = 1,
122    FILEMGR_PREFETCH_ABORT = 2
123};
124
125#define DLOCK_MAX (41) /* a prime number */
126struct wal;
127struct fnamedic_item;
128struct kvs_header;
129
130typedef struct {
131    mutex_t mutex;
132    bool locked;
133} mutex_lock_t;
134
135struct filemgr {
136    char *filename; // Current file name.
137    uint32_t ref_count;
138    uint8_t fflags;
139    uint16_t filename_len;
140    uint32_t blocksize;
141    int fd;
142    atomic_uint64_t pos;
143    atomic_uint64_t last_commit;
144    struct wal *wal;
145    struct filemgr_header header;
146    struct filemgr_ops *ops;
147    struct hash_elem e;
148    atomic_uint8_t status;
149    struct filemgr_config *config;
150    struct filemgr *new_file;
151    char *old_filename; // Old file name before compaction.
152    struct fnamedic_item *bcache;
153    fdb_txn global_txn;
154    bool in_place_compaction;
155    struct kvs_header *kv_header;
156    void (*free_kv_header)(struct filemgr *file); // callback function
157
158    // variables related to prefetching
159    volatile filemgr_prefetch_status_t prefetch_status;
160    thread_t prefetch_tid;
161
162    // spin lock for small region
163    spin_t lock;
164
165    // lock for data consistency
166#ifdef __FILEMGR_DATA_PARTIAL_LOCK
167    struct plock plock;
168#elif defined(__FILEMGR_DATA_MUTEX_LOCK)
169    mutex_t data_mutex[DLOCK_MAX];
170#else
171    spin_t data_spinlock[DLOCK_MAX];
172#endif //__FILEMGR_DATA_PARTIAL_LOCK
173
174    // mutex for synchronization among multiple writers.
175    mutex_lock_t writer_lock;
176};
177
178typedef fdb_status (*register_file_removal_func)(struct filemgr *file,
179                                                 err_log_callback *log_callback);
180typedef bool (*check_file_removal_func)(const char *filename);
181
182typedef struct {
183    struct filemgr *file;
184    int rv;
185} filemgr_open_result;
186
187void filemgr_init(struct filemgr_config *config);
188void filemgr_set_lazy_file_deletion(bool enable,
189                                    register_file_removal_func regis_func,
190                                    check_file_removal_func check_func);
191
192uint64_t filemgr_get_bcache_used_space(void);
193
194size_t filemgr_get_ref_count(struct filemgr *file);
195
196INLINE void filemgr_incr_ref_count(struct filemgr *file) {
197    spin_lock(&file->lock);
198    ++file->ref_count;
199    spin_unlock(&file->lock);
200}
201
202filemgr_open_result filemgr_open(char *filename,
203                                 struct filemgr_ops *ops,
204                                 struct filemgr_config *config,
205                                 err_log_callback *log_callback);
206
207uint64_t filemgr_update_header(struct filemgr *file, void *buf, size_t len);
208filemgr_header_revnum_t filemgr_get_header_revnum(struct filemgr *file);
209
210fdb_seqnum_t filemgr_get_seqnum(struct filemgr *file);
211void filemgr_set_seqnum(struct filemgr *file, fdb_seqnum_t seqnum);
212
213INLINE bid_t filemgr_get_header_bid(struct filemgr *file)
214{
215    return ((file->header.size > 0) ?
216            atomic_get_uint64_t(&file->header.bid) : BLK_NOT_FOUND);
217}
218bid_t _filemgr_get_header_bid(struct filemgr *file);
219void* filemgr_get_header(struct filemgr *file, void *buf, size_t *len,
220                         bid_t *header_bid, fdb_seqnum_t *seqnum,
221                         filemgr_header_revnum_t *header_revnum);
222fdb_status filemgr_fetch_header(struct filemgr *file, uint64_t bid,
223                                void *buf, size_t *len, fdb_seqnum_t *seqnum,
224                                filemgr_header_revnum_t *header_revnum,
225                                err_log_callback *log_callback);
226uint64_t filemgr_fetch_prev_header(struct filemgr *file, uint64_t bid,
227                                   void *buf, size_t *len, fdb_seqnum_t *seqnum,
228                                   err_log_callback *log_callback);
229fdb_status filemgr_close(struct filemgr *file,
230                         bool cleanup_cache_onclose,
231                         const char *orig_file_name,
232                         err_log_callback *log_callback);
233
234void filemgr_remove_all_buffer_blocks(struct filemgr *file);
235void filemgr_free_func(struct hash_elem *h);
236
237INLINE bid_t filemgr_get_next_alloc_block(struct filemgr *file)
238{
239    return atomic_get_uint64_t(&file->pos) / file->blocksize;
240}
241bid_t filemgr_alloc(struct filemgr *file, err_log_callback *log_callback);
242void filemgr_alloc_multiple(struct filemgr *file, int nblock, bid_t *begin,
243                            bid_t *end, err_log_callback *log_callback);
244bid_t filemgr_alloc_multiple_cond(struct filemgr *file, bid_t nextbid, int nblock,
245                                  bid_t *begin, bid_t *end,
246                                  err_log_callback *log_callback);
247
248void filemgr_invalidate_block(struct filemgr *file, bid_t bid);
249
250fdb_status filemgr_read(struct filemgr *file,
251                        bid_t bid, void *buf,
252                        err_log_callback *log_callback,
253                        bool read_on_cache_miss);
254
255fdb_status filemgr_write_offset(struct filemgr *file, bid_t bid, uint64_t offset,
256                          uint64_t len, void *buf, err_log_callback *log_callback);
257fdb_status filemgr_write(struct filemgr *file, bid_t bid, void *buf,
258                   err_log_callback *log_callback);
259INLINE int filemgr_is_writable(struct filemgr *file, bid_t bid)
260{
261    uint64_t pos = bid * file->blocksize;
262    // Note that we don't need to grab file->lock here because
263    // 1) both file->pos and file->last_commit are only incremented.
264    // 2) file->last_commit is updated using the value of file->pos,
265    //    and always equal to or smaller than file->pos.
266    return (pos <  atomic_get_uint64_t(&file->pos) &&
267            pos >= atomic_get_uint64_t(&file->last_commit));
268}
269void filemgr_remove_file(struct filemgr *file);
270
271fdb_status filemgr_commit(struct filemgr *file,
272                          err_log_callback *log_callback);
273fdb_status filemgr_sync(struct filemgr *file,
274                        err_log_callback *log_callback);
275
276fdb_status filemgr_shutdown();
277int filemgr_update_file_status(struct filemgr *file, file_status_t status,
278                                char *old_filename);
279void filemgr_set_compaction_state(struct filemgr *old_file,
280                                  struct filemgr *new_file,
281                                  file_status_t status);
282void filemgr_remove_pending(struct filemgr *old_file, struct filemgr *new_file);
283
284struct kvs_ops_stat *filemgr_migrate_op_stats(struct filemgr *old_file,
285                                              struct filemgr *new_file,
286                                              struct kvs_info *kvs);
287fdb_status filemgr_destroy_file(char *filename,
288                                struct filemgr_config *config,
289                                struct hash *destroy_set);
290
291struct filemgr *filemgr_search_stale_links(struct filemgr *cur_file);
292typedef char *filemgr_redirect_hdr_func(uint8_t *buf, char *new_filename,
293                                       uint16_t new_filename_len);
294char *filemgr_redirect_old_file(struct filemgr *very_old_file,
295                                struct filemgr *new_file,
296                                filemgr_redirect_hdr_func redirect_func);
297INLINE file_status_t filemgr_get_file_status(struct filemgr *file)
298{
299    return atomic_get_uint8_t(&file->status);
300}
301INLINE uint64_t filemgr_get_pos(struct filemgr *file)
302{
303    return atomic_get_uint64_t(&file->pos);
304}
305
306bool filemgr_is_rollback_on(struct filemgr *file);
307void filemgr_set_rollback(struct filemgr *file, uint8_t new_val);
308
309void filemgr_set_in_place_compaction(struct filemgr *file,
310                                     bool in_place_compaction);
311bool filemgr_is_in_place_compaction_set(struct filemgr *file);
312
313void filemgr_mutex_openlock(struct filemgr_config *config);
314void filemgr_mutex_openunlock(void);
315
316void filemgr_mutex_lock(struct filemgr *file);
317bool filemgr_mutex_trylock(struct filemgr *file);
318void filemgr_mutex_unlock(struct filemgr *file);
319
320void filemgr_set_dirty_root(struct filemgr *file,
321                            bid_t dirty_idtree_root,
322                            bid_t dirty_seqtree_root);
323INLINE void filemgr_get_dirty_root(struct filemgr *file,
324                                   bid_t *dirty_idtree_root,
325                                   bid_t *dirty_seqtree_root)
326{
327    *dirty_idtree_root = atomic_get_uint64_t(&file->header.dirty_idtree_root);
328    *dirty_seqtree_root = atomic_get_uint64_t(&file->header.dirty_seqtree_root);
329}
330
331INLINE bool filemgr_dirty_root_exist(struct filemgr *file)
332{
333    return (atomic_get_uint64_t(&file->header.dirty_idtree_root)  != BLK_NOT_FOUND ||
334            atomic_get_uint64_t(&file->header.dirty_seqtree_root) != BLK_NOT_FOUND);
335}
336
337bool filemgr_is_commit_header(void *head_buffer, size_t blocksize);
338
339void _kvs_stat_set(struct filemgr *file,
340                   fdb_kvs_id_t kv_id,
341                   struct kvs_stat stat);
342void _kvs_stat_update_attr(struct filemgr *file,
343                           fdb_kvs_id_t kv_id,
344                           kvs_stat_attr_t attr,
345                           int delta);
346int _kvs_stat_get_kv_header(struct kvs_header *kv_header,
347                            fdb_kvs_id_t kv_id,
348                            struct kvs_stat *stat);
349int _kvs_stat_get(struct filemgr *file,
350                  fdb_kvs_id_t kv_id,
351                  struct kvs_stat *stat);
352uint64_t _kvs_stat_get_sum(struct filemgr *file,
353                           kvs_stat_attr_t attr);
354int _kvs_ops_stat_get_kv_header(struct kvs_header *kv_header,
355                                fdb_kvs_id_t kv_id,
356                                struct kvs_ops_stat *stat);
357int _kvs_ops_stat_get(struct filemgr *file,
358                      fdb_kvs_id_t kv_id,
359                      struct kvs_ops_stat *stat);
360
361void _init_op_stats(struct kvs_ops_stat *stat);
362struct kvs_ops_stat *filemgr_get_ops_stats(struct filemgr *file,
363                                          struct kvs_info *info);
364#ifdef __cplusplus
365}
366#endif
367
368#endif
369