mirror of
https://github.com/MariaDB/server.git
synced 2026-04-19 06:45:32 +02:00
MDEV-13023 mariabackup does not preserve holes for page compressed tables.
Changed "local" datasink logic to detect page compressed Innodb tables. Whenever such table is detected, holes in the copied files are created by skipping over binary zeros at the end of each compressed page.
This commit is contained in:
parent
ca291015bc
commit
af86422f08
11 changed files with 281 additions and 166 deletions
|
|
@ -61,7 +61,7 @@ MYSQL_ADD_EXECUTABLE(mariabackup
|
|||
datasink.c
|
||||
ds_buffer.c
|
||||
ds_compress.c
|
||||
ds_local.c
|
||||
ds_local.cc
|
||||
ds_stdout.c
|
||||
ds_tmpfile.c
|
||||
ds_xbstream.c
|
||||
|
|
@ -98,7 +98,7 @@ ENDIF()
|
|||
########################################################################
|
||||
MYSQL_ADD_EXECUTABLE(mbstream
|
||||
ds_buffer.c
|
||||
ds_local.c
|
||||
ds_local.cc
|
||||
ds_stdout.c
|
||||
datasink.c
|
||||
xbstream.c
|
||||
|
|
@ -112,6 +112,7 @@ TARGET_LINK_LIBRARIES(mbstream
|
|||
mysys
|
||||
crc
|
||||
)
|
||||
ADD_DEPENDENCIES(mbstream GenError)
|
||||
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(mbstream PROPERTIES LINK_FLAGS setargv.obj)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ Write to a datasink file.
|
|||
int
|
||||
ds_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
return file->datasink->write(file, buf, len);
|
||||
return file->datasink->write(file, (const uchar *)buf, len);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ typedef struct {
|
|||
struct datasink_struct {
|
||||
ds_ctxt_t *(*init)(const char *root);
|
||||
ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
|
||||
int (*write)(ds_file_t *file, const void *buf, size_t len);
|
||||
int (*write)(ds_file_t *file, const unsigned char *buf, size_t len);
|
||||
int (*close)(ds_file_t *file);
|
||||
void (*deinit)(ds_ctxt_t *ctxt);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ typedef struct {
|
|||
static ds_ctxt_t *buffer_init(const char *root);
|
||||
static ds_file_t *buffer_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int buffer_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int buffer_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int buffer_close(ds_file_t *file);
|
||||
static void buffer_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ buffer_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
|||
}
|
||||
|
||||
static int
|
||||
buffer_write(ds_file_t *file, const void *buf, size_t len)
|
||||
buffer_write(ds_file_t *file, const uchar *buf, size_t len)
|
||||
{
|
||||
ds_buffer_file_t *buffer_file;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ extern ulonglong xtrabackup_compress_chunk_size;
|
|||
static ds_ctxt_t *compress_init(const char *root);
|
||||
static ds_file_t *compress_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int compress_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int compress_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int compress_close(ds_file_t *file);
|
||||
static void compress_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ err:
|
|||
|
||||
static
|
||||
int
|
||||
compress_write(ds_file_t *file, const void *buf, size_t len)
|
||||
compress_write(ds_file_t *file, const uchar *buf, size_t len)
|
||||
{
|
||||
ds_compress_file_t *comp_file;
|
||||
ds_compress_ctxt_t *comp_ctxt;
|
||||
|
|
|
|||
|
|
@ -1,151 +0,0 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Local datasink implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include <mysys_err.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
|
||||
typedef struct {
|
||||
File fd;
|
||||
} ds_local_file_t;
|
||||
|
||||
static ds_ctxt_t *local_init(const char *root);
|
||||
static ds_file_t *local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int local_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int local_close(ds_file_t *file);
|
||||
static void local_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_local = {
|
||||
&local_init,
|
||||
&local_open,
|
||||
&local_write,
|
||||
&local_close,
|
||||
&local_deinit
|
||||
};
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
local_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
|
||||
if (my_mkdir(root, 0777, MYF(0)) < 0
|
||||
&& my_errno != EEXIST && my_errno != EISDIR)
|
||||
{
|
||||
char errbuf[MYSYS_STRERROR_SIZE];
|
||||
my_strerror(errbuf, sizeof(errbuf),my_errno);
|
||||
my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG),
|
||||
root, my_errno,errbuf, my_errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt = my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));
|
||||
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat __attribute__((unused)))
|
||||
{
|
||||
char fullpath[FN_REFLEN];
|
||||
char dirpath[FN_REFLEN];
|
||||
size_t dirpath_len;
|
||||
size_t path_len;
|
||||
ds_local_file_t *local_file;
|
||||
ds_file_t *file;
|
||||
File fd;
|
||||
|
||||
fn_format(fullpath, path, ctxt->root, "", MYF(MY_RELATIVE_PATH));
|
||||
|
||||
/* Create the directory if needed */
|
||||
dirname_part(dirpath, fullpath, &dirpath_len);
|
||||
if (my_mkdir(dirpath, 0777, MYF(0)) < 0 && my_errno != EEXIST) {
|
||||
char errbuf[MYSYS_STRERROR_SIZE];
|
||||
my_strerror(errbuf, sizeof(errbuf), my_errno);
|
||||
my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG),
|
||||
dirpath, my_errno, errbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = my_create(fullpath, 0, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
|
||||
MYF(MY_WME));
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_len = strlen(fullpath) + 1; /* terminating '\0' */
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_local_file_t) +
|
||||
path_len,
|
||||
MYF(MY_FAE));
|
||||
local_file = (ds_local_file_t *) (file + 1);
|
||||
|
||||
local_file->fd = fd;
|
||||
|
||||
file->path = (char *) local_file + sizeof(ds_local_file_t);
|
||||
memcpy(file->path, fullpath, path_len);
|
||||
|
||||
file->ptr = local_file;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
local_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
File fd = ((ds_local_file_t *) file->ptr)->fd;
|
||||
|
||||
if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
local_close(ds_file_t *file)
|
||||
{
|
||||
File fd = ((ds_local_file_t *) file->ptr)->fd;
|
||||
|
||||
my_free(file);
|
||||
|
||||
my_sync(fd, MYF(MY_WME));
|
||||
|
||||
return my_close(fd, MYF(MY_WME));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
local_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
||||
259
extra/mariabackup/ds_local.cc
Normal file
259
extra/mariabackup/ds_local.cc
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Local datasink implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <my_config.h>
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include <mysys_err.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
#include "univ.i"
|
||||
#include "fsp0fsp.h"
|
||||
#ifdef _WIN32
|
||||
#include <winioctl.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
File fd;
|
||||
my_bool init_ibd_done;
|
||||
my_bool is_ibd;
|
||||
my_bool compressed;
|
||||
size_t pagesize;
|
||||
} ds_local_file_t;
|
||||
|
||||
static ds_ctxt_t *local_init(const char *root);
|
||||
static ds_file_t *local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int local_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int local_close(ds_file_t *file);
|
||||
static void local_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
extern "C" {
|
||||
datasink_t datasink_local = {
|
||||
&local_init,
|
||||
&local_open,
|
||||
&local_write,
|
||||
&local_close,
|
||||
&local_deinit
|
||||
};
|
||||
}
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
local_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
|
||||
if (my_mkdir(root, 0777, MYF(0)) < 0
|
||||
&& my_errno != EEXIST && my_errno != EISDIR)
|
||||
{
|
||||
char errbuf[MYSYS_STRERROR_SIZE];
|
||||
my_strerror(errbuf, sizeof(errbuf),my_errno);
|
||||
my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG),
|
||||
root, my_errno,errbuf, my_errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt = (ds_ctxt_t *)my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));
|
||||
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat __attribute__((unused)))
|
||||
{
|
||||
char fullpath[FN_REFLEN];
|
||||
char dirpath[FN_REFLEN];
|
||||
size_t dirpath_len;
|
||||
size_t path_len;
|
||||
ds_local_file_t *local_file;
|
||||
ds_file_t *file;
|
||||
File fd;
|
||||
|
||||
fn_format(fullpath, path, ctxt->root, "", MYF(MY_RELATIVE_PATH));
|
||||
|
||||
/* Create the directory if needed */
|
||||
dirname_part(dirpath, fullpath, &dirpath_len);
|
||||
if (my_mkdir(dirpath, 0777, MYF(0)) < 0 && my_errno != EEXIST) {
|
||||
char errbuf[MYSYS_STRERROR_SIZE];
|
||||
my_strerror(errbuf, sizeof(errbuf), my_errno);
|
||||
my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG),
|
||||
dirpath, my_errno, errbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = my_create(fullpath, 0, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
|
||||
MYF(MY_WME));
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_len = strlen(fullpath) + 1; /* terminating '\0' */
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_local_file_t) +
|
||||
path_len,
|
||||
MYF(MY_FAE));
|
||||
local_file = (ds_local_file_t *) (file + 1);
|
||||
|
||||
local_file->fd = fd;
|
||||
local_file->init_ibd_done = 0;
|
||||
local_file->is_ibd = (path_len > 5) && !strcmp(fullpath + path_len - 5, ".ibd");
|
||||
local_file->compressed = 0;
|
||||
local_file->pagesize = 0;
|
||||
file->path = (char *) local_file + sizeof(ds_local_file_t);
|
||||
memcpy(file->path, fullpath, path_len);
|
||||
|
||||
file->ptr = local_file;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/* Calculate size of data without trailing zero bytes. */
|
||||
static size_t trim_binary_zeros(uchar *buf, size_t pagesize)
|
||||
{
|
||||
size_t i;
|
||||
for (i = pagesize; (i > 0) && (buf[i - 1] == 0); i--) {};
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* Write data to the output file, and punch "holes" if needed. */
|
||||
static int write_compressed(File fd, uchar *data, size_t len, size_t pagesize)
|
||||
{
|
||||
uchar *ptr = data;
|
||||
for (size_t written= 0; written < len;)
|
||||
{
|
||||
size_t n_bytes = MY_MIN(pagesize, len - written);
|
||||
size_t datasize= trim_binary_zeros(ptr,n_bytes);
|
||||
if (datasize > 0) {
|
||||
if (!my_write(fd, ptr, datasize, MYF(MY_WME | MY_NABP)))
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
if (datasize < n_bytes) {
|
||||
/* This punches a "hole" in the file. */
|
||||
size_t hole_bytes = n_bytes - datasize;
|
||||
if (my_seek(fd, hole_bytes, MY_SEEK_CUR, MYF(MY_WME | MY_NABP))
|
||||
== MY_FILEPOS_ERROR)
|
||||
return 1;
|
||||
}
|
||||
written += n_bytes;
|
||||
ptr += n_bytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Calculate Innodb tablespace specific data, when first page is written.
|
||||
We're interested in page compression and page size.
|
||||
*/
|
||||
static void init_ibd_data(ds_local_file_t *local_file, const uchar *buf, size_t len)
|
||||
{
|
||||
if (len < FIL_PAGE_DATA + FSP_SPACE_FLAGS) {
|
||||
/* Weird, bail out.*/
|
||||
return;
|
||||
}
|
||||
|
||||
ulint flags = mach_read_from_4(&buf[FIL_PAGE_DATA + FSP_SPACE_FLAGS]);
|
||||
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
|
||||
local_file->pagesize= ssize == 0 ? UNIV_PAGE_SIZE_ORIG : ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
|
||||
local_file->compressed = (my_bool)FSP_FLAGS_HAS_PAGE_COMPRESSION(flags);
|
||||
|
||||
#if defined(_WIN32) && (MYSQL_VERSION_ID > 100200)
|
||||
/* Make compressed file sparse, on Windows.
|
||||
In 10.1, we do not use sparse files. */
|
||||
if (local_file->compressed) {
|
||||
HANDLE handle= my_get_osfhandle(local_file->fd);
|
||||
if (!DeviceIoControl(handle, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, NULL, 0)) {
|
||||
fprintf(stderr, "Warning: cannot make file sparse");
|
||||
local_file->compressed = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int
|
||||
local_write(ds_file_t *file, const uchar *buf, size_t len)
|
||||
{
|
||||
uchar *b = (uchar*)buf;
|
||||
ds_local_file_t *local_file= (ds_local_file_t *)file->ptr;
|
||||
File fd = local_file->fd;
|
||||
|
||||
if (local_file->is_ibd && !local_file->init_ibd_done) {
|
||||
init_ibd_data(local_file, b , len);
|
||||
local_file->init_ibd_done= 1;
|
||||
}
|
||||
|
||||
if (local_file->compressed) {
|
||||
return write_compressed(fd, b, len, local_file->pagesize);
|
||||
}
|
||||
|
||||
if (!my_write(fd, b , len, MYF(MY_WME | MY_NABP))) {
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set EOF at file's current position.*/
|
||||
static int set_eof(File fd)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return !SetEndOfFile(my_get_osfhandle(fd));
|
||||
#elif defined(HAVE_FTRUNCATE)
|
||||
return ftruncate(fd, my_tell(fd, MYF(MY_WME)));
|
||||
#else
|
||||
#error no ftruncate
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int
|
||||
local_close(ds_file_t *file)
|
||||
{
|
||||
ds_local_file_t *local_file= (ds_local_file_t *)file->ptr;
|
||||
File fd = local_file->fd;
|
||||
int ret= 0;
|
||||
|
||||
if (local_file->compressed) {
|
||||
ret = set_eof(fd);
|
||||
}
|
||||
|
||||
my_close(fd, MYF(MY_WME));
|
||||
my_free(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
local_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
||||
|
|
@ -23,6 +23,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|||
|
||||
#include "datasink.h"
|
||||
|
||||
extern datasink_t datasink_local;
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
|
||||
datasink_t datasink_local;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ typedef struct {
|
|||
static ds_ctxt_t *stdout_init(const char *root);
|
||||
static ds_file_t *stdout_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int stdout_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int stdout_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int stdout_close(ds_file_t *file);
|
||||
static void stdout_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ stdout_open(ds_ctxt_t *ctxt __attribute__((unused)),
|
|||
|
||||
static
|
||||
int
|
||||
stdout_write(ds_file_t *file, const void *buf, size_t len)
|
||||
stdout_write(ds_file_t *file, const uchar *buf, size_t len)
|
||||
{
|
||||
File fd = ((ds_stdout_file_t *) file->ptr)->fd;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ typedef struct {
|
|||
static ds_ctxt_t *tmpfile_init(const char *root);
|
||||
static ds_file_t *tmpfile_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int tmpfile_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int tmpfile_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int tmpfile_close(ds_file_t *file);
|
||||
static void tmpfile_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ tmpfile_open(ds_ctxt_t *ctxt, const char *path,
|
|||
}
|
||||
|
||||
static int
|
||||
tmpfile_write(ds_file_t *file, const void *buf, size_t len)
|
||||
tmpfile_write(ds_file_t *file, const uchar *buf, size_t len)
|
||||
{
|
||||
File fd = ((ds_tmp_file_t *) file->ptr)->fd;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ General streaming interface */
|
|||
static ds_ctxt_t *xbstream_init(const char *root);
|
||||
static ds_file_t *xbstream_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int xbstream_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int xbstream_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int xbstream_close(ds_file_t *file);
|
||||
static void xbstream_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ err:
|
|||
|
||||
static
|
||||
int
|
||||
xbstream_write(ds_file_t *file, const void *buf, size_t len)
|
||||
xbstream_write(ds_file_t *file, const uchar *buf, size_t len)
|
||||
{
|
||||
ds_stream_file_t *stream_file;
|
||||
xb_wstream_file_t *xbstream_file;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue