NVMLib  very early alpha
A library to optimally use a Hybrid RAM setup.
pool.c
Go to the documentation of this file.
1 #include "globals.h"
2 #include "pool.h"
3 #include "metadata.h"
4 #include <libpmemobj.h>
5 #include <libpmem.h>
6 #include "hashmap.h"
7 #include "types.h"
8 #include "free_slot_list.h"
9 #include "log.h"
10 
11 //extern const char *program_invocation_short_name;
12 
13 static int compare_kv(pool_kv* left, pool_kv* right) {
14  if (left->key == right->key) return 0;
15  return 1;
16 }
17 
19  if (left->key == right->key) return 0;
20  return 1;
21 }
22 
23 int get_hash_kv(pool_kv *val){
24  return val->key;
25 }
26 
28  return val->key;
29 }
30 
32 
33 HASH_MAP(pool_kv) *pool_map;
34 
36 
37 HASH_MAP(pool_free_slot_val) *pool_free_slot_map;
38 
39 int initialize_pool() {
40  pool_map = HASH_MAP_CREATE(pool_kv)();
41  pool_free_slot_map = HASH_MAP_CREATE(pool_free_slot_val)();
43 #ifdef DEBUG
44  printf("initialize pool num_pools= %d\n", num_pools);
45 #endif
46  for (int idx = 1; idx <= num_pools; idx++) {
47  char pool_file_name[50];
48  char pool_free_slot_file_name[50];
49  char pool_number_str[4];
50  strcpy(pool_file_name, program_invocation_short_name);
51  strcpy(pool_free_slot_file_name, program_invocation_short_name);
52  strcat(pool_file_name, "_poolfile_");
53  strcat(pool_free_slot_file_name, "_free_slot_");
54  sprintf(pool_number_str, "%3d", idx);
55  strcat(pool_file_name, pool_number_str);
56  strcat(pool_free_slot_file_name, pool_number_str);
57  uintptr_t pool_ptr = (uintptr_t)pmem_map_file(pool_file_name, 0, 0,
58  0666, NULL, NULL);
59  pool_kv* init_pool_kv = malloc(sizeof(pool_kv));
60  pool_free_slot_val* free_slots = malloc(sizeof(pool_free_slot_val));
61 
62  PMEMobjpool* free_slot_pool = pmemobj_open(pool_free_slot_file_name, POBJ_LAYOUT_NAME(free_slot_layout));
63 
64  free_slots->key = idx;
65  free_slots->pool = free_slot_pool;
66  free_slots->head = &(D_RO(POBJ_ROOT(free_slot_pool, struct pool_free_slots_root))->head);
67 
68  int ret = HASH_MAP_INSERT(pool_free_slot_val)(pool_free_slot_map, &free_slots, HMDR_FIND);
69  #ifdef DEBUG
70  printf("pool free slot insert return %d\n", ret);
71  #endif
72  init_pool_kv->key = idx;
73  init_pool_kv->pool_ptr = pool_ptr;
74  HASH_MAP_INSERT(pool_kv)(pool_map, &init_pool_kv, HMDR_FIND);
75  }
76  return 0;
77 }
78 
80  pool_kv temp;
81  pool_kv* temp_ptr = &temp;
82  temp.key = pool_id;
83  temp.pool_ptr = (uintptr_t)NULL;
84  if (HASH_MAP_FIND(pool_kv)(pool_map, &temp_ptr)) {
85  return (uintptr_t)temp_ptr->pool_ptr;
86  }
87  return NULL;
88 }
89 
91  return num_pools;
92 }
93 
94 void create_new_pool(size_t size) {
95  num_pools++;
96  pool_kv* new_entry = (pool_kv*)malloc(sizeof(pool_kv));
97  pool_free_slot_val* new_free_slots = malloc(sizeof(pool_free_slot_val));
98 
99  new_entry->key = num_pools;
100  new_free_slots->key = num_pools;
101 
102  char pool_file_name[50];
103  char pool_free_slot_file_name[50];
104  char pool_number_str[4];
105  strcpy(pool_file_name, program_invocation_short_name);
106  strcpy(pool_free_slot_file_name, program_invocation_short_name);
107  strcat(pool_file_name, "_poolfile_");
108  strcat(pool_free_slot_file_name, "_free_slot_");
109  sprintf(pool_number_str, "%3d", num_pools);
110  strcat(pool_file_name, pool_number_str);
111  strcat(pool_free_slot_file_name, pool_number_str);
112  // Need to corrected with proper pathss
113  size_t allot_size = (size_t)ceil((double)size/POOL_SIZE)*POOL_SIZE;
114  uintptr_t pmemaddr = (uintptr_t)pmem_map_file(pool_file_name, allot_size, PMEM_FILE_CREATE,
115  0666, NULL, NULL);
116  PMEMobjpool* free_slot_pool = pmemobj_create(pool_free_slot_file_name, POBJ_LAYOUT_NAME(free_slot_layout),
117  PMEMOBJ_MIN_POOL, 0666);
118  TOID(struct pool_free_slots_root) pool_root = POBJ_ROOT(free_slot_pool, struct pool_free_slots_root);
119  TX_BEGIN (free_slot_pool) {
120  TOID(struct pool_free_slot) new_slot = TX_NEW(struct pool_free_slot);
121  POBJ_TAILQ_INSERT_HEAD(&(D_RW(pool_root)->head), new_slot, fnd);
122  } TX_END
123 
124  new_entry->pool_ptr = pmemaddr;
125  new_free_slots->pool = free_slot_pool;
126  new_free_slots->head = &(D_RO(pool_root)->head);
127 #ifdef DEBUG
128  printf("new_entry %p new_free_slots %p\n", new_entry, new_free_slots);
129  printf("new_entry->pool_ptr %ld pmemaddr %ld\n", new_entry->pool_ptr, pmemaddr);
130  printf("new_free_slots->pool %ld free_slot_pool %ld\n", new_free_slots->pool, free_slot_pool);
131 #endif
133  HASH_MAP_INSERT(pool_kv)(pool_map, &new_entry, HMDR_FIND);
134  HASH_MAP_INSERT(pool_free_slot_val)(pool_free_slot_map, &new_free_slots, HMDR_FIND);
135 }
136 
137 void nvm_free(uint64_t pool_id, uint64_t offset, size_t size) {
138  // memset the freed location since its NVRAM
139  memset(get_memobj_direct((MEMoid){.pool_id=pool_id, .offset=offset}), 0, size);
140 
141  pool_free_slot_val temp;
142  pool_free_slot_val* temp_ptr = &temp;
143  temp.key = pool_id;
144  HASH_MAP_FIND(pool_free_slot_val)(pool_free_slot_map, &temp_ptr);
145  pool_free_slot_head* f_head = temp_ptr->head;
146  TOID(struct pool_free_slot) node;
147  TOID(struct pool_free_slot) next_node;
148  TOID(struct pool_free_slot) to_remove_node;
149  TOID(struct pool_free_slot) to_insert_node;
150 
155  int flag = 0;
156 
157  node = POBJ_TAILQ_FIRST(f_head);
158  if (offset < D_RO(node)->start_b) {
159  // its in the very first location
160  if (offset + size - 1 == D_RO(node)->start_b - 1) {
161  TX_BEGIN(temp_ptr->pool) {
162  D_RW(node)->start_b = offset;
163  flag = -2;
164  } TX_END
165  } else {
166  TX_BEGIN(temp_ptr->pool) {
167  to_insert_node = TX_NEW(struct pool_free_slot);
168  // POBJ_TAILQ_INSERT_AFTER(f_head, node, to_insert_node, fnd);
169 
170  D_RW(to_insert_node)->start_b = offset;
171  D_RW(to_insert_node)->end_b = offset + size - 1;
172 
173  flag = -3;
174  } TX_END
175  }
176  goto end;
177  }
178 
179  POBJ_TAILQ_FOREACH (node, f_head, fnd) {
180  if (offset == D_RO(node)->end_b + 1) {
181  TX_BEGIN(temp_ptr->pool) {
182  D_RW(node)->end_b = D_RO(node)->end_b + size;
183  next_node = POBJ_TAILQ_NEXT(node, fnd);
184  if (!TOID_IS_NULL(next_node)) {
185  if (offset + size - 1 == D_RO(next_node)->start_b - 1) {
186  D_RW(node)->end_b = D_RO(next_node)->end_b;
187  // POBJ_TAILQ_REMOVE_FREE(f_head, next_node, fnd);
188 
189  // can't modify the datastructure within a loop
190  to_remove_node = next_node;
191  flag = 1;
192  }
193  }
194  } TX_END
195  break;
196  } else if (offset > D_RO(node)->end_b + 1) {
197  next_node = POBJ_TAILQ_NEXT(node, fnd);
198  if (!TOID_IS_NULL(next_node)) {
199  if (offset + size - 1 == D_RO(next_node)->start_b - 1) {
200  TX_BEGIN(temp_ptr->pool) {
201  D_RW(next_node)->start_b = offset;
202  flag = 2;
203  } TX_END
204  break;
205  } else {
206  TX_BEGIN(temp_ptr->pool) {
207  to_insert_node = TX_NEW(struct pool_free_slot);
208  // POBJ_TAILQ_INSERT_AFTER(f_head, node, to_insert_node, fnd);
209 
210  D_RW(to_insert_node)->start_b = offset;
211  D_RW(to_insert_node)->end_b = offset + size - 1;
212 
213  flag = 3;
214  } TX_END
215 
216  break;
217  }
218  }
219  }
220  }
221 
222 end:
223 #ifdef DEBUG
224  printf("nvm_free: f_head %p\n", f_head);
225  printf("nvm free: flag %d\n", flag);
226  printf("nvm_free: node->end_b %p\n", D_RO(node)->end_b);
227 #endif
228 
229 
230  if (flag == 1) {
231  #ifdef DEBUG
232  printf("nvm_free: to_remove->end_b %p\n", D_RO(to_remove_node)->end_b);
233  #endif
234  TX_BEGIN(temp_ptr->pool) {
235  POBJ_TAILQ_REMOVE_FREE(f_head, to_remove_node, fnd);
236  } TX_END
237  return;
238  }
239 
240  if(flag == 3) {
241  #ifdef DEBUG
242  printf("nvm_free: to_insert_node->end_b %p, to_insert_node->start_b %p\n", D_RO(to_insert_node)->end_b, D_RO(to_insert_node)->start_b);
243  #endif
244  TX_BEGIN(temp_ptr->pool) {
245  POBJ_TAILQ_INSERT_AFTER(f_head, node, to_insert_node, fnd);
246  } TX_END
247  return;
248  }
249 
250  if (flag == -3) {
251  #ifdef DEBUG
252  printf("nvm_free: to_insert_node->end_b %p, to_insert_node->start_b %p\n", D_RO(to_insert_node)->end_b, D_RO(to_insert_node)->start_b);
253  #endif
254  TX_BEGIN(temp_ptr->pool) {
255  POBJ_TAILQ_INSERT_HEAD(f_head, to_insert_node, fnd);
256  } TX_END
257  return;
258  }
259 
260  LOG_INFO("NVM freeing value pool_id = %ld, offset = %ld size = %ld\n", pool_id, offset, size);
261 }
get_memobj_direct
void * get_memobj_direct(MEMoid oid)
The function to return the actual memptr for a given MEMoid object.
Definition: malloc.c:316
POBJ_TAILQ_REMOVE_FREE
#define POBJ_TAILQ_REMOVE_FREE(head, elm, field)
Definition: free_slot_list.h:288
pool_kv_st
Definition: pool.h:32
pool_free_slot_val_st::head
pool_free_slot_head * head
Definition: pool.h:40
HASH_MAP
HASH_MAP(pool_kv)
Definition: pool.c:33
types.h
get_pool_from_poolid
uintptr_t get_pool_from_poolid(uint64_t pool_id)
Definition: pool.c:79
update_num_pools
void update_num_pools(int num_pools)
Definition: metadata.c:34
compare_kv
static int compare_kv(pool_kv *left, pool_kv *right)
Definition: pool.c:13
POBJ_TAILQ_INSERT_HEAD
#define POBJ_TAILQ_INSERT_HEAD(head, elm, field)
Definition: free_slot_list.h:183
pool_kv_st::pool_ptr
uintptr_t pool_ptr
Definition: pool.h:34
LOG_INFO
#define LOG_INFO(message, args...)
Definition: log.h:54
MEMoid_st
The struct that stores the memptr for the object.
Definition: malloc.h:29
POBJ_TAILQ_FIRST
#define POBJ_TAILQ_FIRST(head)
Definition: free_slot_list.h:138
HMDR_FIND
@ HMDR_FIND
Definition: hashmap.h:40
get_hash_kv
int get_hash_kv(pool_kv *val)
Definition: pool.c:23
POBJ_TAILQ_NEXT
#define POBJ_TAILQ_NEXT(elm, field)
Definition: free_slot_list.h:142
pool_free_slots_root
Definition: pool.h:28
hashmap.h
POOL_SIZE
#define POOL_SIZE
Definition: pool.h:11
compare_free_slot
static int compare_free_slot(pool_free_slot_val *left, pool_free_slot_val *right)
Definition: pool.c:18
pool_free_slot_val_st
Definition: pool.h:37
globals.h
pool.h
uint64_t
__uint64_t uint64_t
Definition: globals.h:51
POBJ_TAILQ_INSERT_AFTER
#define POBJ_TAILQ_INSERT_AFTER(head, listelm, elm, field)
Definition: free_slot_list.h:223
get_hash_free_slot
int get_hash_free_slot(pool_free_slot_val *val)
Definition: pool.c:27
HASH_MAP_INSERT
#define HASH_MAP_INSERT(VALUE_TYPE)
Definition: hashmap.h:32
pool_free_slot_val_st::pool
PMEMobjpool * pool
Definition: pool.h:39
pool_free_slot_head
struct pool_free_slot_head pool_free_slot_head
Definition: pool.h:26
create_new_pool
void create_new_pool(size_t size)
Definition: pool.c:94
pool_free_slot
Definition: pool.h:20
TOID
TOID(struct hashmap_tx)
Definition: types.c:11
get_current_poolid
uint64_t get_current_poolid()
Definition: pool.c:90
log.h
NULL
#define NULL
Definition: list.h:13
initialize_pool
int initialize_pool()
retrieve_num_pools
int retrieve_num_pools()
Definition: metadata.c:51
pool_kv_st::key
uint16_t key
Definition: pool.h:33
uintptr_t
unsigned long int uintptr_t
Definition: globals.h:56
free_slot_list.h
metadata.h
HASH_MAP_CREATE
#define HASH_MAP_CREATE(VALUE_TYPE)
Definition: hashmap.h:34
POBJ_TAILQ_FOREACH
#define POBJ_TAILQ_FOREACH(var, head, field)
Definition: free_slot_list.h:166
DEFINE_HASHMAP
#define DEFINE_HASHMAP(VALUE_TYPE, CMP, GET_HASH, FREE, REALLOC)
Definition of the declared HashMap.
Definition: hashmap.h:126
HASH_MAP_FIND
#define HASH_MAP_FIND(VALUE_TYPE)
Definition: hashmap.h:33
nvm_free
void nvm_free(uint64_t pool_id, uint64_t offset, size_t size)
Definition: pool.c:137
num_pools
uint32_t num_pools
Definition: pool.h:13
program_invocation_short_name
char * program_invocation_short_name
The predefined pools.
pool_free_slot_val_st::key
uint16_t key
Definition: pool.h:38