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
56typedef uint64_t cf_arenax_handle;
57
58// Must be in-sync with internal array ARENAX_ERR_STRINGS[]:
59typedef 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
76typedef 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.
82typedef 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
122COMPILER_ASSERT(sizeof(cf_arenax) == 144 + (8 * CF_ARENAX_MAX_STAGES));
123
124typedef struct free_element_s {
125 uint32_t magic;
126 cf_arenax_handle next_h;
127} free_element;
128
129#define FREE_MAGIC 0xff1234ff
130
131typedef 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
140size_t cf_arenax_sizeof();
141const char* cf_arenax_errstr(cf_arenax_err err);
142
143void 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
148cf_arenax_handle cf_arenax_alloc(cf_arenax* arena, cf_arenax_puddle* puddle);
149void cf_arenax_free(cf_arenax* arena, cf_arenax_handle h, cf_arenax_puddle* puddle);
150
151void* cf_arenax_resolve(cf_arenax* arena, cf_arenax_handle h);
152
153bool cf_arenax_want_prefetch(cf_arenax* arena);
154void 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
161static inline void
162cf_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
168static inline void
169cf_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
176cf_arenax_err cf_arenax_add_stage(cf_arenax* arena);
177
178cf_arenax_handle cf_arenax_alloc_chunked(cf_arenax* arena, cf_arenax_puddle* puddle);
179void cf_arenax_free_chunked(cf_arenax* arena, cf_arenax_handle h, cf_arenax_puddle* puddle);
180