blob: ca9b85d9bc8e980134d6dee828871e5450d04afb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef BFZ_H
#define BFZ_H
#include <postgres.h>
#include "pipe.h"
#define BFZ_MODE_CLOSED 0
#define BFZ_MODE_APPEND 1
#define BFZ_MODE_FREED 2
#define BFZ_MODE_SCAN 3
#define BFZ_BUFFER_SIZE (1<<14)
struct bfz;
struct bfz_freeable_stuff
{
char *buffer_pointer;
char *buffer_end;
/*
* We always call read_ex with size==BFZ_BUFFER_SIZE.
* The checksumming algorithm relies on this to determine the
* boundary of a buffer that a checksum is applied to.
*/
int (*read_ex) (struct bfz * thiz, char *buffer, int size);
/*
* We always call write_ex with size==BFZ_BUFFER_SIZE, except for the
* last write. The checksumming algorithm relies on this to
* determine the boundary of a buffer that a checksum is applied to.
*/
void (*write_ex) (struct bfz * thiz, const char *buffer, int size);
void (*close_ex) (struct bfz * thiz);
char buffer[BFZ_BUFFER_SIZE];
};
typedef struct bfz
{
struct bfz_freeable_stuff *freeable_stuff;
int fd;
char *filename;
unsigned char mode;
unsigned char compression_index;
bool del_on_close;
/* Indicate if this bfz file stores block checksums. */
bool has_checksum;
/*
* The following are used to simulate a torn page.
*
* 'numBlocks' represents total number of blocks this bfz file contains.
* 'blockNo' represents the number for the block that is currently accessed.
* 'chosenBlockNo' represents the number for the block that will become
* a torn page.
*/
int64 numBlocks;
int64 blockNo;
int64 chosenBlockNo;
int64 tot_bytes;
} bfz_t;
/* These functions are internal to bfz. */
extern void bfz_nothing_init(bfz_t * thiz);
extern void bfz_zlib_init(bfz_t * thiz);
extern void bfz_lzop_init(bfz_t * thiz);
extern void bfz_write_ex(bfz_t * thiz, const char *buffer, int size);
extern int bfz_read_ex(bfz_t * thiz, char *buffer, int size);
/* These functions are interface to bfz. */
extern const char *bfz_compression_to_string(int compress);
extern int bfz_string_to_compression(const char *string);
extern bfz_t *bfz_create(const char *filePrefix, bool delOnClose, int compress);
extern bfz_t *bfz_open(const char *fileName, bool delOnClose, int compress);
extern int64 bfz_append_end(bfz_t * thiz);
extern void bfz_scan_begin(bfz_t * thiz);
extern void bfz_close(bfz_t * thiz, bool unreg, bool canReportError);
extern ssize_t readAndRetry(int fd, void *buffer, size_t size);
extern ssize_t writeAndRetry(int fd, const void *buffer, size_t size);
static inline int64
bfz_totalbytes(bfz_t * bfz)
{
return bfz->tot_bytes;
}
static inline void
bfz_append(bfz_t * thiz, const char *buffer, int size)
{
struct bfz_freeable_stuff *fs = thiz->freeable_stuff;
Assert(size >= 0);
Assert(fs != NULL);
Assert(thiz->mode == BFZ_MODE_APPEND);
if (fs->buffer_pointer + size <= fs->buffer_end)
{
memcpy(fs->buffer_pointer, buffer, size);
fs->buffer_pointer += size;
}
else
bfz_write_ex(thiz, buffer, size);
return;
}
/*
* If the data requested is already in the bfz buffer, this function
* returns a pointer to the data in the buffer.
* If more data needs to be read from disk, this function returns NULL and
* the caller must call bfz_scan_next.
*/
static inline void *
bfz_scan_peek(bfz_t * thiz, int size)
{
struct bfz_freeable_stuff *fs = thiz->freeable_stuff;
Assert(size >= 0);
Assert(fs != NULL);
Assert(thiz->mode == BFZ_MODE_SCAN);
if (fs->buffer_pointer + size > fs->buffer_end)
return NULL;
fs->buffer_pointer += size;
return fs->buffer_pointer - size;
}
static inline int
bfz_scan_next(bfz_t * thiz, char *buffer, int size)
{
Assert(size >= 0);
Assert(thiz->mode == BFZ_MODE_SCAN || thiz->mode == BFZ_MODE_FREED);
/* First time we're reading from file, open it for reading */
if (thiz->mode == BFZ_MODE_FREED)
{
bfz_scan_begin(thiz);
}
struct bfz_freeable_stuff *fs = thiz->freeable_stuff;
Assert(fs != NULL);
if (fs->buffer_pointer + size <= fs->buffer_end)
{
memcpy(buffer, fs->buffer_pointer, size);
fs->buffer_pointer += size;
return size;
}
return bfz_read_ex(thiz, buffer, size);
}
#endif /* BFZ_H */