110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @file db_manage.c
310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * Management of a DB file
410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @remark Copyright 2002 OProfile authors
610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @remark Read the file COPYING
710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @author Philippe Elie
910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
1010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define _GNU_SOURCE
1210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <stdlib.h>
145a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng#ifdef ANDROID
1510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <fcntl.h>
165a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng#else
175a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng#include <sys/fcntl.h>
1810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#endif
1910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <sys/mman.h>
2010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <sys/types.h>
2110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <sys/stat.h>
2210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <unistd.h>
2310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <errno.h>
2410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <string.h>
2510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <stdio.h>
2610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "odb.h"
2810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "op_string.h"
2910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "op_libiberty.h"
3010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic __inline odb_descr_t * odb_to_descr(odb_data_t * data)
3310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
3410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return (odb_descr_t *)(((char*)data->base_memory) + data->sizeof_header);
3510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
3610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic __inline odb_node_t * odb_to_node_base(odb_data_t * data)
3910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
4010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return (odb_node_t *)(((char *)data->base_memory) + data->offset_node);
4110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
4210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
4310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
4410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic __inline odb_index_t * odb_to_hash_base(odb_data_t * data)
4510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
4610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return (odb_index_t *)(((char *)data->base_memory) +
4710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				data->offset_node +
4810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				(data->descr->size * sizeof(odb_node_t)));
4910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
5010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
5310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * return the number of bytes used by hash table, node table and header.
5410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
5510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic unsigned int tables_size(odb_data_t const * data, odb_node_nr_t node_nr)
5610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
5710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t size;
5810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size = node_nr * (sizeof(odb_index_t) * BUCKET_FACTOR);
6010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size += node_nr * sizeof(odb_node_t);
6110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size += data->offset_node;
6210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
6310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return size;
6410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
6510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
6610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
6710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectint odb_grow_hashtable(odb_data_t * data)
6810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
6910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	unsigned int old_file_size;
7010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	unsigned int new_file_size;
7110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	unsigned int pos;
7210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	void * new_map;
7310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	old_file_size = tables_size(data, data->descr->size);
7510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	new_file_size = tables_size(data, data->descr->size * 2);
7610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (ftruncate(data->fd, new_file_size))
7810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return 1;
7910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
80b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown#ifdef MISSING_MREMAP
81b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown	new_map = mmap(0, new_file_size, PROT_READ | PROT_WRITE,
82b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown		MAP_SHARED, data->fd, 0);
83b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown#else
8410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	new_map = mremap(data->base_memory,
8510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			 old_file_size, new_file_size, MREMAP_MAYMOVE);
86b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown#endif
8710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (new_map == MAP_FAILED)
8910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return 1;
9010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
91b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown#ifdef MISSING_MREMAP
92b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown	munmap(data->base_memory, old_file_size);
93b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown#endif
94b415faba7482dd7ee3335f0f1518333554e3da0dJeff Brown
9510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->base_memory = new_map;
9610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->descr = odb_to_descr(data);
9710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->descr->size *= 2;
9810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->node_base = odb_to_node_base(data);
9910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->hash_base = odb_to_hash_base(data);
10010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->hash_mask = (data->descr->size * BUCKET_FACTOR) - 1;
10110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
10210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* rebuild the hash table, node zero is never used. This works
10310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * because layout of file is node table then hash table,
10410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * sizeof(node) > sizeof(bucket) and when we grow table we
10510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * double size ==> old hash table and new hash table can't
10610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * overlap so on the new hash table is entirely in the new
10710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * memory area (the grown part) and we know the new hash
10810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * hash table is zeroed. That's why we don't need to zero init
10910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * the new table */
11010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* OK: the above is not exact
11110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * if BUCKET_FACTOR < sizeof(bd_node_t) / sizeof(bd_node_nr_t)
11210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * all things are fine and we don't need to init the hash
11310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * table because in this case the new hash table is completely
11410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * inside the new growed part. Avoiding to touch this memory is
11510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * useful.
11610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 */
11710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#if 0
11810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (pos = 0 ; pos < data->descr->size*BUCKET_FACTOR ; ++pos)
11910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		data->hash_base[pos] = 0;
12010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#endif
12110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
12210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (pos = 1; pos < data->descr->current_size; ++pos) {
12310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		odb_node_t * node = &data->node_base[pos];
12410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		size_t index = odb_do_hash(data, node->key);
12510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		node->next = data->hash_base[index];
12610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		data->hash_base[index] = pos;
12710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
12810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
12910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return 0;
13010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
13110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid odb_init(odb_t * odb)
13410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
13510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	odb->data = NULL;
13610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
13710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/* the default number of page, calculated to fit in 4096 bytes */
14010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define DEFAULT_NODE_NR(offset_node)	128
14110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define FILES_HASH_SIZE                 512
14210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic struct list_head files_hash[FILES_HASH_SIZE];
14410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void init_hash()
14710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
14810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t i;
14910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < FILES_HASH_SIZE; ++i)
15010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		list_init(&files_hash[i]);
15110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
15210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
15310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
15410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic odb_data_t *
15510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectfind_samples_data(size_t hash, char const * filename)
15610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
15710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct list_head * pos;
15810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
15910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* FIXME: maybe an initial init routine ? */
16010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (files_hash[0].next == NULL) {
16110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		init_hash();
16210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return NULL;
16310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
16410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	list_for_each(pos, &files_hash[hash]) {
16610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		odb_data_t * entry = list_entry(pos, odb_data_t, list);
16710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (strcmp(entry->filename, filename) == 0)
16810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			return entry;
16910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
17010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
17110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return NULL;
17210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
17310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
17410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
17510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectint odb_open(odb_t * odb, char const * filename, enum odb_rw rw,
17610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	     size_t sizeof_header)
17710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
17810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct stat stat_buf;
17910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	odb_node_nr_t nr_node;
18010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	odb_data_t * data;
18110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t hash;
18210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int err = 0;
18310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
18410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int flags = (rw == ODB_RDWR) ? (O_CREAT | O_RDWR) : O_RDONLY;
18510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int mmflags = (rw == ODB_RDWR) ? (PROT_READ | PROT_WRITE) : PROT_READ;
18610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
18710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	hash = op_hash_string(filename) % FILES_HASH_SIZE;
18810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data = find_samples_data(hash, filename);
18910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (data) {
19010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		odb->data = data;
19110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		data->ref_count++;
19210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return 0;
19310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
19410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
19510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data = xmalloc(sizeof(odb_data_t));
19610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	memset(data, '\0', sizeof(odb_data_t));
19710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	list_init(&data->list);
19810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->offset_node = sizeof_header + sizeof(odb_descr_t);
19910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->sizeof_header = sizeof_header;
20010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->ref_count = 1;
20110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->filename = xstrdup(filename);
20210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
20310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->fd = open(filename, flags, 0644);
20410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (data->fd < 0) {
20510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		err = errno;
20610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		goto out;
20710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
20810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
20910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (fstat(data->fd, &stat_buf)) {
21010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		err = errno;
21110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		goto fail;
21210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
21310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
21410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (stat_buf.st_size == 0) {
21510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		size_t file_size;
21610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
21710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (rw == ODB_RDONLY) {
21810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			err = EIO;
21910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			goto fail;
22010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
22110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
22210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		nr_node = DEFAULT_NODE_NR(data->offset_node);
22310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
22410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		file_size = tables_size(data, nr_node);
22510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (ftruncate(data->fd, file_size)) {
22610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			err = errno;
22710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			goto fail;
22810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
22910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	} else {
23010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		/* Calculate nr node allowing a sanity check later */
23110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		nr_node = (stat_buf.st_size - data->offset_node) /
23210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			((sizeof(odb_index_t) * BUCKET_FACTOR) + sizeof(odb_node_t));
23310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
23410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
23510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->base_memory = mmap(0, tables_size(data, nr_node), mmflags,
23610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				MAP_SHARED, data->fd, 0);
23710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
23810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (data->base_memory == MAP_FAILED) {
23910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		err = errno;
24010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		goto fail;
24110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
24210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
24310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->descr = odb_to_descr(data);
24410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
24510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (stat_buf.st_size == 0) {
24610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		data->descr->size = nr_node;
24710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		/* page zero is not used */
24810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		data->descr->current_size = 1;
24910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	} else {
25010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		/* file already exist, sanity check nr node */
25110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (nr_node != data->descr->size) {
25210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			err = EINVAL;
25310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			goto fail_unmap;
25410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
25510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
25610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
25710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->hash_base = odb_to_hash_base(data);
25810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->node_base = odb_to_node_base(data);
25910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	data->hash_mask = (data->descr->size * BUCKET_FACTOR) - 1;
26010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
26110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	list_add(&data->list, &files_hash[hash]);
26210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	odb->data = data;
26310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectout:
26410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return err;
26510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectfail_unmap:
26610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	munmap(data->base_memory, tables_size(data, nr_node));
26710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectfail:
26810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	close(data->fd);
26910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	free(data->filename);
27010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	free(data);
27110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	odb->data = NULL;
27210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	goto out;
27310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
27410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
27510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
27610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid odb_close(odb_t * odb)
27710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
27810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	odb_data_t * data = odb->data;
27910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
28010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (data) {
28110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		data->ref_count--;
28210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (data->ref_count == 0) {
28310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			size_t size = tables_size(data, data->descr->size);
28410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			list_del(&data->list);
28510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			munmap(data->base_memory, size);
28610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			if (data->fd >= 0)
28710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				close(data->fd);
28810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			free(data->filename);
28910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			free(data);
29010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			odb->data = NULL;
29110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
29210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
29310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
29410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
29510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
29610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectint odb_open_count(odb_t const * odb)
29710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
29810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!odb->data)
29910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return 0;
30010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return odb->data->ref_count;
30110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
30210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
30310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
30410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid * odb_get_data(odb_t * odb)
30510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
30610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return odb->data->base_memory;
30710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
30810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
30910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
31010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid odb_sync(odb_t const * odb)
31110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
31210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	odb_data_t * data = odb->data;
31310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t size;
31410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
31510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!data)
31610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
31710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
31810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size = tables_size(data, data->descr->size);
31910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	msync(data->base_memory, size, MS_ASYNC);
32010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
321