1 | /* |
2 | * arenax.h |
3 | * |
4 | * Copyright (C) 2012-2014 Aerospike, Inc. |
5 | * |
6 | * Portions may be licensed to Aerospike, Inc. under one or more contributor |
7 | * license agreements. |
8 | * |
9 | * This program is free software: you can redistribute it and/or modify it under |
10 | * the terms of the GNU Affero General Public License as published by the Free |
11 | * Software Foundation, either version 3 of the License, or (at your option) any |
12 | * later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, but WITHOUT |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
16 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
17 | * details. |
18 | * |
19 | * You should have received a copy of the GNU Affero General Public License |
20 | * along with this program. If not, see http://www.gnu.org/licenses/ |
21 | */ |
22 | |
23 | #pragma once |
24 | |
25 | //========================================================== |
26 | // Includes. |
27 | // |
28 | |
29 | #include <stdbool.h> |
30 | #include <stddef.h> |
31 | #include <stdint.h> |
32 | #include <sys/types.h> |
33 | |
34 | #include "cf_mutex.h" |
35 | #include "fault.h" |
36 | #include "xmem.h" |
37 | |
38 | |
39 | //========================================================== |
40 | // Typedefs & constants. |
41 | // |
42 | |
43 | #define CF_ARENAX_BIGLOCK (1 << 0) |
44 | #define CF_ARENAX_CALLOC (1 << 1) |
45 | |
46 | #ifndef CF_ARENAX_MAX_STAGES |
47 | #define CF_ARENAX_MAX_STAGES 256 |
48 | #endif |
49 | |
50 | #define CF_ARENAX_MIN_STAGE_SIZE (128L * 1024L * 1024L) // 128M |
51 | |
52 | #ifndef CF_ARENAX_MAX_STAGE_SIZE |
53 | #define CF_ARENAX_MAX_STAGE_SIZE (1024L * 1024L * 1024L) // 1G |
54 | #endif |
55 | |
56 | typedef uint64_t cf_arenax_handle; |
57 | |
58 | // Must be in-sync with internal array ARENAX_ERR_STRINGS[]: |
59 | typedef enum { |
60 | CF_ARENAX_OK = 0, |
61 | CF_ARENAX_ERR_BAD_PARAM, |
62 | CF_ARENAX_ERR_STAGE_CREATE, |
63 | CF_ARENAX_ERR_STAGE_ATTACH, |
64 | CF_ARENAX_ERR_STAGE_DETACH, |
65 | CF_ARENAX_ERR_UNKNOWN |
66 | } cf_arenax_err; |
67 | |
68 | //------------------------------------------------ |
69 | // For enterprise separation only. |
70 | // |
71 | |
72 | // Element is indexed by 28 bits. |
73 | #define ELEMENT_ID_NUM_BITS 28 |
74 | #define ELEMENT_ID_MASK ((1UL << ELEMENT_ID_NUM_BITS) - 1) // 0xFFFffff |
75 | |
76 | typedef struct cf_arenax_chunk_s { |
77 | uint64_t base_h: 40; |
78 | } __attribute__((packed)) cf_arenax_chunk; |
79 | |
80 | // DO NOT access this member data directly - use the API! |
81 | // Caution - changing this struct could break warm or cool restart. |
82 | typedef struct cf_arenax_s { |
83 | // Configuration (passed in constructors). |
84 | cf_xmem_type xmem_type; |
85 | const void* xmem_type_cfg; |
86 | key_t key_base; |
87 | uint32_t element_size; |
88 | uint32_t stage_capacity; |
89 | uint32_t max_stages; |
90 | uint32_t flags; |
91 | |
92 | // Configuration (derived). |
93 | size_t stage_size; |
94 | |
95 | // Free-element list (non-chunked allocations). |
96 | cf_arenax_handle free_h; |
97 | |
98 | // Where to end-allocate. |
99 | uint32_t at_stage_id; |
100 | uint32_t at_element_id; |
101 | |
102 | // Thread safety. |
103 | cf_mutex lock; |
104 | |
105 | // Pad to maintain warm restart compatibility (lock was pthread mutex). |
106 | uint8_t pad[36]; |
107 | |
108 | // Current stages. |
109 | uint32_t stage_count; |
110 | uint8_t* stages[CF_ARENAX_MAX_STAGES]; |
111 | |
112 | // Flash index related members at end to avoid full warm restart converter. |
113 | |
114 | uint32_t chunk_count; // is 1 for non-flash indexes |
115 | |
116 | // Arena pool (free chunked allocations). |
117 | size_t pool_len; |
118 | cf_arenax_chunk* pool_buf; |
119 | size_t pool_i; |
120 | } cf_arenax; |
121 | |
122 | COMPILER_ASSERT(sizeof(cf_arenax) == 144 + (8 * CF_ARENAX_MAX_STAGES)); |
123 | |
124 | typedef struct free_element_s { |
125 | uint32_t magic; |
126 | cf_arenax_handle next_h; |
127 | } free_element; |
128 | |
129 | #define FREE_MAGIC 0xff1234ff |
130 | |
131 | typedef struct cf_arenax_puddle_s { |
132 | uint64_t free_h: 40; |
133 | } __attribute__((packed)) cf_arenax_puddle; |
134 | |
135 | |
136 | //========================================================== |
137 | // Public API. |
138 | // |
139 | |
140 | size_t cf_arenax_sizeof(); |
141 | const char* cf_arenax_errstr(cf_arenax_err err); |
142 | |
143 | void cf_arenax_init(cf_arenax* arena, cf_xmem_type xmem_type, |
144 | const void* xmem_type_cfg, key_t key_base, uint32_t element_size, |
145 | uint32_t chunk_count, uint32_t stage_capacity, uint32_t max_stages, |
146 | uint32_t flags); |
147 | |
148 | cf_arenax_handle cf_arenax_alloc(cf_arenax* arena, cf_arenax_puddle* puddle); |
149 | void cf_arenax_free(cf_arenax* arena, cf_arenax_handle h, cf_arenax_puddle* puddle); |
150 | |
151 | void* cf_arenax_resolve(cf_arenax* arena, cf_arenax_handle h); |
152 | |
153 | bool cf_arenax_want_prefetch(cf_arenax* arena); |
154 | void cf_arenax_reclaim(cf_arenax* arena, cf_arenax_puddle* puddles, uint32_t n_puddles); |
155 | |
156 | |
157 | //========================================================== |
158 | // Private API - for enterprise separation only. |
159 | // |
160 | |
161 | static inline void |
162 | cf_arenax_set_handle(cf_arenax_handle* h, uint32_t stage_id, |
163 | uint32_t element_id) |
164 | { |
165 | *h = ((uint64_t)stage_id << ELEMENT_ID_NUM_BITS) | element_id; |
166 | } |
167 | |
168 | static inline void |
169 | cf_arenax_expand_handle(uint32_t* stage_id, uint32_t* element_id, |
170 | cf_arenax_handle h) |
171 | { |
172 | *stage_id = h >> ELEMENT_ID_NUM_BITS; |
173 | *element_id = h & ELEMENT_ID_MASK; |
174 | } |
175 | |
176 | cf_arenax_err cf_arenax_add_stage(cf_arenax* arena); |
177 | |
178 | cf_arenax_handle cf_arenax_alloc_chunked(cf_arenax* arena, cf_arenax_puddle* puddle); |
179 | void cf_arenax_free_chunked(cf_arenax* arena, cf_arenax_handle h, cf_arenax_puddle* puddle); |
180 | |