mail-index-data.c revision 742111fa99a5b852c9645080573d5853be3907a7
/* Copyright (C) 2002 Timo Sirainen */
#include "lib.h"
#include "file-set-size.h"
#include "mmap-util.h"
#include "write-full.h"
#include "mail-index.h"
#include "mail-index-data.h"
#include "mail-index-util.h"
#include <stdio.h>
#include <fcntl.h>
/* Never compress the file if it's smaller than this */
/* Compress the file when deleted space reaches n% of total size */
#define COMPRESS_PERCENTAGE 20
/* Initial size for the file */
/* When more space is needed, grow the file n% larger than the previous size */
#define INDEX_DATA_GROW_PERCENTAGE 10
struct mail_index_data {
struct mail_index *index;
int fd;
char *filepath;
void *mmap_base;
struct mail_index_data_header *header;
unsigned int anon_mmap:1;
unsigned int dirty_mmap:1;
unsigned int modified:1;
unsigned int fsynced:1;
};
{
t_push();
t_pop();
return FALSE;
}
const char *function)
{
return FALSE;
}
return FALSE;
}
{
}
}
data->mmap_used_length = 0;
data->mmap_full_length = 0;
}
}
{
int fd;
if (fd == -1)
return TRUE;
}
{
struct mail_index_data_header *hdr;
/* index was just rebuilt. we should have noticed
this before at index->set_lock() though. */
"Warning: Inconsistency - Index "
"%s was rebuilt while we had it open",
return FALSE;
}
/* data file was deleted, reopen it */
if (!data_file_reopen(data))
return FALSE;
/* force mmap refresh */
size = 0;
}
if (size != 0) {
return TRUE;
if (data->mmap_used_length >=
sizeof(struct mail_index_data_header) &&
return TRUE;
/* file size changed, re-mmap() */
}
}
}
data->mmap_used_length = 0;
}
return FALSE;
}
"used_file_size larger than real file size "
return FALSE;
}
return TRUE;
}
{
struct mail_index_data *data;
const char *path;
int fd;
if (fd == -1) {
/* doesn't exist, rebuild the index */
}
}
return FALSE;
}
/* verify that this really is the data file for wanted index */
path);
return FALSE;
}
return TRUE;
}
struct mail_index_data_header *hdr,
{
return FALSE;
}
return FALSE;
}
return TRUE;
}
{
struct mail_index_data_header hdr;
struct mail_index_data *data;
const char *path;
int fd;
/* we'll do anon-mmaping only if initially requested. if we fail
because of out of disk space, we'll just let the main index code
know it and fail. */
if (INDEX_IS_IN_MEMORY(index)) {
fd = -1;
} else {
if (fd == -1) {
return FALSE;
}
return FALSE;
}
}
if (fd == -1) {
i_strdup_printf("(in-memory index data index for %s)",
} else {
}
return FALSE;
}
return TRUE;
}
{
}
{
struct mail_index_data_header hdr;
return TRUE;
}
return mmap_update(data, 0, 0);
}
{
return TRUE;
sizeof(struct mail_index_data_header), MS_SYNC) < 0)
return TRUE;
}
{
}
{
void *base;
if (base == MAP_FAILED) {
return FALSE;
}
return TRUE;
}
if (pos < 0)
/* no need to grow, just update mmap */
if (!mmap_update(data, 0, 0))
return FALSE;
return TRUE;
}
return mmap_update(data, 0, 0);
}
{
return 0;
return 0;
}
return offset;
}
struct mail_index_record *index_rec)
{
struct mail_index_data_record_header *rec_hdr;
return FALSE;
/* just mark it deleted. */
/* clear the record data. not really needed, but better not to keep
deleted information lying around.. */
/* see if we've reached the max. deleted space in file */
100 * COMPRESS_PERCENTAGE;
}
return TRUE;
}
{
*fsync_fd = -1;
return TRUE;
}
}
return TRUE;
}
struct mail_index_data_record_header *
struct mail_index_record *index_rec)
{
if (pos == 0) {
/* data not yet written to record */
return NULL;
}
sizeof(struct mail_index_data_record_header)))
return NULL;
if (pos + sizeof(struct mail_index_data_record_header) >
data->mmap_used_length) {
"Data position of record %u points outside file "
sizeof(struct mail_index_data_record_header),
return NULL;
}
if ((pos % MEM_ALIGN_SIZE) != 0) {
"is not memory aligned for record %u",
return NULL;
}
return (struct mail_index_data_record_header *)
}
struct mail_index_data_record *
struct mail_index_record *index_rec,
enum mail_data_field field)
{
struct mail_index_data_record_header *rec_hdr;
struct mail_index_data_record *rec;
if (index_rec->data_position == 0) {
/* data not yet written to record */
return NULL;
}
return NULL;
return NULL;
"Given data size larger than file size "
return NULL;
}
pos += sizeof(struct mail_index_data_record_header);
do {
rec = (struct mail_index_data_record *)
"Field %d size points outside file "
break;
}
"is not memory aligned for record %u",
break;
}
/* match */
return rec;
/* jump to next record */
} else {
/* the fields are sorted by field type, so it's not
possible the wanted field could come after this. */
break;
}
return NULL;
}
struct mail_index_data_record *
struct mail_index_record *index_rec,
struct mail_index_data_record *rec)
{
struct mail_index_data_record_header *rec_hdr;
return NULL;
rec_hdr = (struct mail_index_data_record_header *)
/* get position to next record */
/* make sure it's within range */
return NULL;
rec = (struct mail_index_data_record *)
return NULL;
}
return rec;
}
struct mail_index_data_record *rec)
{
int i;
/* we already checked that the full_field_size is within file,
so this can happen only if the file really is huge.. */
return FALSE;
}
/* make sure the data actually contains \0 */
/* yes, everything ok */
return TRUE;
}
}
return FALSE;
}
{
if (!mmap_update(data, 0, 0))
return NULL;
}