aboutsummaryrefslogtreecommitdiff
path: root/src/memfile_defs.h
blob: e614cae7caeb6f763cf40ed638559f7f0f7c6a8c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#ifndef NEOVIM_MEMFILE_DEFS_H
#define NEOVIM_MEMFILE_DEFS_H

typedef struct block_hdr bhdr_T;
typedef long blocknr_T;

/*
 * mf_hashtab_T is a chained hashtable with blocknr_T key and arbitrary
 * structures as items.  This is an intrusive data structure: we require
 * that items begin with mf_hashitem_T which contains the key and linked
 * list pointers.  List of items in each bucket is doubly-linked.
 */

typedef struct mf_hashitem_S mf_hashitem_T;

struct mf_hashitem_S {
  mf_hashitem_T   *mhi_next;
  mf_hashitem_T   *mhi_prev;
  blocknr_T mhi_key;
};

#define MHT_INIT_SIZE   64

typedef struct mf_hashtab_S {
  long_u mht_mask;                  /* mask used for hash value (nr of items
                                     * in array is "mht_mask" + 1) */
  long_u mht_count;                 /* nr of items inserted into hashtable */
  mf_hashitem_T   **mht_buckets;    /* points to mht_small_buckets or
                                     *dynamically allocated array */
  mf_hashitem_T   *mht_small_buckets[MHT_INIT_SIZE];     /* initial buckets */
  char mht_fixed;                   /* non-zero value forbids growth */
} mf_hashtab_T;

/*
 * for each (previously) used block in the memfile there is one block header.
 *
 * The block may be linked in the used list OR in the free list.
 * The used blocks are also kept in hash lists.
 *
 * The used list is a doubly linked list, most recently used block first.
 *	The blocks in the used list have a block of memory allocated.
 *	mf_used_count is the number of pages in the used list.
 * The hash lists are used to quickly find a block in the used list.
 * The free list is a single linked list, not sorted.
 *	The blocks in the free list have no block of memory allocated and
 *	the contents of the block in the file (if any) is irrelevant.
 */

struct block_hdr {
  mf_hashitem_T bh_hashitem;        /* header for hash table and key */
#define bh_bnum bh_hashitem.mhi_key /* block number, part of bh_hashitem */

  bhdr_T      *bh_next;             /* next block_hdr in free or used list */
  bhdr_T      *bh_prev;             /* previous block_hdr in used list */
  char_u      *bh_data;             /* pointer to memory (for used block) */
  int bh_page_count;                /* number of pages in this block */

#define BH_DIRTY    1
#define BH_LOCKED   2
  char bh_flags;                    /* BH_DIRTY or BH_LOCKED */
};

/*
 * when a block with a negative number is flushed to the file, it gets
 * a positive number. Because the reference to the block is still the negative
 * number, we remember the translation to the new positive number in the
 * double linked trans lists. The structure is the same as the hash lists.
 */
typedef struct nr_trans NR_TRANS;

struct nr_trans {
  mf_hashitem_T nt_hashitem;            /* header for hash table and key */
#define nt_old_bnum nt_hashitem.mhi_key /* old, negative, number */

  blocknr_T nt_new_bnum;                /* new, positive, number */
};

#define MF_SEED_LEN     8

struct memfile {
  char_u      *mf_fname;                /* name of the file */
  char_u      *mf_ffname;               /* idem, full path */
  int mf_fd;                            /* file descriptor */
  bhdr_T      *mf_free_first;           /* first block_hdr in free list */
  bhdr_T      *mf_used_first;           /* mru block_hdr in used list */
  bhdr_T      *mf_used_last;            /* lru block_hdr in used list */
  unsigned mf_used_count;               /* number of pages in used list */
  unsigned mf_used_count_max;           /* maximum number of pages in memory */
  mf_hashtab_T mf_hash;                 /* hash lists */
  mf_hashtab_T mf_trans;                /* trans lists */
  blocknr_T mf_blocknr_max;             /* highest positive block number + 1*/
  blocknr_T mf_blocknr_min;             /* lowest negative block number - 1 */
  blocknr_T mf_neg_count;               /* number of negative blocks numbers */
  blocknr_T mf_infile_count;            /* number of pages in the file */
  unsigned mf_page_size;                /* number of bytes in a page */
  int mf_dirty;                         /* TRUE if there are dirty blocks */
  buf_T       *mf_buffer;               /* bufer this memfile is for */
  char_u mf_seed[MF_SEED_LEN];          /* seed for encryption */

  /* Values for key, method and seed used for reading data blocks when
   * updating for a newly set key or method. Only when mf_old_key != NULL. */
  char_u      *mf_old_key;
  int mf_old_cm;
  char_u mf_old_seed[MF_SEED_LEN];
};

#endif // NEOVIM_MEMFILE_DEFS_H