mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 23:04:20 +01:00
1f796663cd
This was a tricky merge. In the 1332a directory I did: {{{ svn merge https://svn.tokutek.com/tokudb/toku/tokudb.1032b+1332@8415 https://svn.tokutek.com/tokudb/toku/tokudb.1032b+1332@8416 }}} Then I was able to resolve the conflicts. Then in the main line I did: {{{ svn merge -r9042:9046 https://svn.tokutek.com/tokudb/toku/tokudb.1332a }}} Fixes #1332. git-svn-id: file:///svn/toku/tokudb@9047 c7de825b-a66e-492c-adef-691d508d4ae1
76 lines
2.6 KiB
C
76 lines
2.6 KiB
C
/* Buffered read. */
|
|
|
|
#include "includes.h"
|
|
|
|
struct bread {
|
|
int64_t fileoff; // The byte before this offset is the next byte we will read (since we are reading backward)
|
|
int fd;
|
|
int bufoff; // The current offset in the buf. The next byte we will read is buf[bufoff-1] (assuming that bufoff>0).
|
|
char *buf; // A buffer with at least bufoff bytes in it.
|
|
};
|
|
|
|
BREAD create_bread_from_fd_initialize_at(int fd) {
|
|
BREAD XMALLOC(result);
|
|
int r = toku_os_get_file_size(fd, &result->fileoff);
|
|
assert(r==0);
|
|
result->fd=fd;
|
|
result->bufoff=0;
|
|
result->buf = 0;
|
|
return result;
|
|
}
|
|
|
|
int close_bread_without_closing_fd(BREAD br) {
|
|
toku_free(br->buf);
|
|
toku_free(br);
|
|
return 0;
|
|
}
|
|
|
|
|
|
ssize_t bread_backwards(BREAD br, void *vbuf, size_t nbytes) {
|
|
char *buf=vbuf;
|
|
ssize_t result=0;
|
|
const int i4 = sizeof(u_int32_t);
|
|
while (nbytes > 0) {
|
|
// read whatever we can out of the buffer.
|
|
if (br->bufoff>0) {
|
|
size_t to_copy = ((size_t)br->bufoff >= nbytes) ? nbytes : (size_t)br->bufoff;
|
|
memcpy(buf+nbytes-to_copy, &br->buf[br->bufoff-to_copy], to_copy);
|
|
nbytes -= to_copy;
|
|
result += to_copy;
|
|
br->bufoff -= to_copy;
|
|
}
|
|
if (nbytes>0) {
|
|
assert(br->bufoff==0);
|
|
u_int32_t compressed_length_n, uncompressed_length_n;
|
|
assert(br->fileoff>=i4); // there better be the three lengths plus the compressed data.
|
|
{ ssize_t r = pread(br->fd, &compressed_length_n, i4, br->fileoff- i4); assert(r==i4); }
|
|
u_int32_t compressed_length = ntohl(compressed_length_n);
|
|
assert(br->fileoff >= compressed_length + 3*i4);
|
|
{ ssize_t r = pread(br->fd, &uncompressed_length_n, i4, br->fileoff-2*i4); assert(r==i4); }
|
|
u_int32_t uncompressed_length = ntohl(uncompressed_length_n);
|
|
char *XMALLOC_N(compressed_length, zbuf);
|
|
{
|
|
ssize_t r = pread(br->fd, zbuf, compressed_length, br->fileoff- compressed_length -2*i4);
|
|
assert(r==(ssize_t)compressed_length);
|
|
}
|
|
{
|
|
u_int32_t compressed_length_n_again;
|
|
ssize_t r = pread(br->fd, &compressed_length_n_again, i4, br->fileoff-compressed_length-3*i4); assert(r==i4);
|
|
assert(compressed_length_n_again == compressed_length_n);
|
|
}
|
|
uLongf destlen = uncompressed_length;
|
|
XREALLOC_N(uncompressed_length, br->buf);
|
|
uncompress((Bytef*)br->buf, &destlen, (Bytef*)zbuf, compressed_length);
|
|
assert(destlen==uncompressed_length);
|
|
toku_free(zbuf);
|
|
|
|
br->bufoff = uncompressed_length;
|
|
br->fileoff -= (compressed_length + 3*i4);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int bread_has_more(BREAD br) {
|
|
return (br->fileoff>0) || (br->bufoff>0);
|
|
}
|