Changeset: e406a4f2b834 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e406a4f2b834
Modified Files:
clients/Tests/exports.stable.out
clients/mapiclient/mclient.c
clients/mapilib/mapi.c
clients/mapilib/mapi.h
tools/merovingian/daemon/snapshot.c
Branch: copyintobinary
Log Message:
Add binary download support to libmapi and mclient
diffs (242 lines):
diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -700,6 +700,7 @@ MapiMsg mapi_set_columnar_protocol(Mapi
MapiMsg mapi_set_size_header(Mapi mid, bool value)
__attribute__((__nonnull__(1)));
MapiMsg mapi_set_time_zone(Mapi mid, int seconds_east_of_utc)
__attribute__((__nonnull__(1)));
MapiMsg mapi_set_timeout(Mapi mid, unsigned int timeout, bool (*callback)(void
*), void *callback_data) __attribute__((__nonnull__(1)));
+void mapi_setfilecallback2(Mapi mid, char *(*getfunc)(void *priv, const char
*filename, bool binary, uint64_t offset, size_t *size), char *(*putfunc)(void
*priv, const char *filename, bool, const void *data, size_t size), void *priv)
__attribute__((__nonnull__(1)));
void mapi_setfilecallback(Mapi mid, char *(*getfunc)(void *priv, const char
*filename, bool binary, uint64_t offset, size_t *size), char *(*putfunc)(void
*priv, const char *filename, const void *data, size_t size), void *priv)
__attribute__((__nonnull__(1)));
int mapi_split_line(MapiHdl hdl) __attribute__((__nonnull__(1)));
MapiMsg mapi_store_field(MapiHdl hdl, int fnr, int outtype, void *outparam)
__attribute__((__nonnull__(1)));
diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c
--- a/clients/mapiclient/mclient.c
+++ b/clients/mapiclient/mclient.c
@@ -3045,13 +3045,15 @@ getfile(void *data, const char *filename
}
static char *
-putfile(void *data, const char *filename, const void *buf, size_t bufsize)
+putfile(void *data, const char *filename, bool binary, const void *buf, size_t
bufsize)
{
struct privdata *priv = data;
if (filename != NULL) {
- if ((priv->f = open_wastream(filename)) == NULL)
+ stream *s = binary ? open_wstream(filename) :
open_wastream(filename);
+ if (s == NULL)
return (char*)mnstr_peek_error(NULL);
+ priv->f = s;
#ifdef HAVE_ICONV
if (encoding) {
stream *f = priv->f;
@@ -3559,7 +3561,7 @@ main(int argc, char **argv)
struct privdata priv;
priv = (struct privdata) {0};
- mapi_setfilecallback(mid, getfile, putfile, &priv);
+ mapi_setfilecallback2(mid, getfile, putfile, &priv);
if (logfile)
mapi_log(mid, logfile);
diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -927,8 +927,10 @@ struct MapiStruct {
stream *from, *to;
uint32_t index; /* to mark the log records */
void *filecontentprivate;
+ void *filecontentprivate_old;
char *(*getfilecontent)(void *, const char *, bool, uint64_t, size_t *);
- char *(*putfilecontent)(void *, const char *, const void *, size_t);
+ char *(*putfilecontent)(void *, const char *, bool, const void *,
size_t);
+ char *(*putfilecontent_old)(void *, const char *, const void *, size_t);
};
struct MapiResultSet {
@@ -3178,7 +3180,7 @@ mapi_disconnect(Mapi mid)
* than the requested offset, the first call to the callback function
* may return NULL.
*
- * char *putfile(void *private, const char *filename,
+ * char *putfile(void *private, const char *filename, bool binary,
* const void *data, size_t size);
* Send data to a file.
*
@@ -3187,6 +3189,9 @@ mapi_disconnect(Mapi mid)
* mapi_setfilecallback;
* filename - the file to be written, files are always written as text
* files;
+ * binary - if set, the data to be written is binary and the file
+ * should therefore be opened in binary mode, otherwise the
+ * data is UTF-8 encoded text;
* data - the data to be written;
* size - the size of the data to be written.
*
@@ -3201,10 +3206,40 @@ mapi_disconnect(Mapi mid)
* called again for the same file. Otherwise, the callback function
* returns NULL.
*
- * Note, there is no support for binary files. All files written
- * using this callback function are text files. All data sent to the
- * callback function is encoded in UTF-8. Note also that multibyte
- * sequences may be split over two calls.
+ * Note also that multibyte sequences may be split over two calls.
+ */
+void
+mapi_setfilecallback2(Mapi mid,
+ char *(*getfilecontent)(void *,
+ const char *, bool,
+ uint64_t, size_t *),
+ char *(*putfilecontent)(void *,
+ const char *, bool,
+ const void *, size_t),
+ void *filecontentprivate)
+{
+ mid->getfilecontent = getfilecontent;
+ mid->putfilecontent = putfilecontent;
+ mid->filecontentprivate = filecontentprivate;
+ mid->putfilecontent_old = NULL;
+ mid->filecontentprivate_old = NULL;
+}
+
+static char *
+putfilecontent_wrap(void *priv, const char *filename, bool binary, const void
*data, size_t size)
+{
+ Mapi mid = priv;
+ void *priv_old = mid->filecontentprivate_old;
+ if (filename && binary)
+ return "Client does not support writing binary files";
+ return mid->putfilecontent_old(priv_old, filename, data, size);
+}
+
+/* DEPRECATED. Set callback function to retrieve or send file content for COPY
+ * INTO queries.
+ *
+ * Deprecated because it does not support binary downloads.
+ * Use mapi_setfilecallback2 instead.
*/
void
mapi_setfilecallback(Mapi mid,
@@ -3217,8 +3252,10 @@ mapi_setfilecallback(Mapi mid,
void *filecontentprivate)
{
mid->getfilecontent = getfilecontent;
- mid->putfilecontent = putfilecontent;
- mid->filecontentprivate = filecontentprivate;
+ mid->putfilecontent = putfilecontent_wrap;
+ mid->filecontentprivate = mid;
+ mid->putfilecontent_old = putfilecontent;
+ mid->filecontentprivate_old = filecontentprivate;
}
#define testBinding(hdl,fnr) \
@@ -4174,7 +4211,7 @@ parse_header_line(MapiHdl hdl, char *lin
}
static void
-write_file(MapiHdl hdl, char *filename)
+write_file(MapiHdl hdl, char *filename, bool binary)
{
Mapi mid = hdl->mid;
char *line;
@@ -4194,7 +4231,7 @@ write_file(MapiHdl hdl, char *filename)
mnstr_flush(mid->to, MNSTR_FLUSH_DATA);
return;
}
- line = mid->putfilecontent(mid->filecontentprivate, filename, NULL, 0);
+ line = mid->putfilecontent(mid->filecontentprivate, filename, binary,
NULL, 0);
free(filename);
if (line != NULL) {
if (strchr(line, '\n'))
@@ -4207,11 +4244,11 @@ write_file(MapiHdl hdl, char *filename)
while ((len = mnstr_read(mid->from, data, 1, sizeof(data))) > 0) {
if (line == NULL)
line = mid->putfilecontent(mid->filecontentprivate,
- NULL, data, len);
+ NULL, binary, data, len);
}
if (line == NULL)
line = mid->putfilecontent(mid->filecontentprivate,
- NULL, NULL, 0);
+ NULL, binary, NULL, 0);
if (line && strchr(line, '\n'))
line = "incorrect response from application";
mnstr_printf(mid->to, "%s\n", line ? line : "");
@@ -4384,13 +4421,14 @@ read_into_cache(MapiHdl hdl, int lookahe
} else if (line[1] == PROMPT3[1] && line[2] == '\0') {
mid->active = hdl;
line = read_line(mid);
+ bool binary = false;
/* rb FILE
* r OFF FILE
- * w ???
+ * w FILE
+ * wb FILE
*/
switch (*line++) {
case 'r': {
- bool binary = false;
uint64_t off = 0;
if (*line == 'b') {
line++;
@@ -4407,12 +4445,16 @@ read_into_cache(MapiHdl hdl, int lookahe
break;
}
case 'w':
+ if (*line == 'b') {
+ line++;
+ binary = true;
+ }
if (*line++ != ' ') {
mnstr_printf(mid->to,
"!HY000!unrecognized command from server\n");
mnstr_flush(mid->to,
MNSTR_FLUSH_DATA);
break;
}
- write_file(hdl, strdup(line));
+ write_file(hdl, strdup(line), binary);
break;
}
continue;
diff --git a/clients/mapilib/mapi.h b/clients/mapilib/mapi.h
--- a/clients/mapilib/mapi.h
+++ b/clients/mapilib/mapi.h
@@ -84,6 +84,14 @@ mapi_export MapiMsg mapi_reconnect(Mapi
__attribute__((__nonnull__(1)));
mapi_export MapiMsg mapi_ping(Mapi mid)
__attribute__((__nonnull__(1)));
+mapi_export void mapi_setfilecallback2(
+ Mapi mid,
+ char *(*getfunc)(void *priv, const char *filename,
+ bool binary, uint64_t offset, size_t *size),
+ char *(*putfunc)(void *priv, const char *filename, bool binary,
+ const void *data, size_t size),
+ void *priv)
+ __attribute__((__nonnull__(1)));
mapi_export void mapi_setfilecallback(
Mapi mid,
char *(*getfunc)(void *priv, const char *filename,
diff --git a/tools/merovingian/daemon/snapshot.c
b/tools/merovingian/daemon/snapshot.c
--- a/tools/merovingian/daemon/snapshot.c
+++ b/tools/merovingian/daemon/snapshot.c
@@ -48,9 +48,10 @@ const char *VALID_EXTENSIONS[] = {
static char*
snapshot_database_stream_helper(
- void *priv, const char *filename,
+ void *priv, const char *filename, bool binary,
const void *data, size_t size)
{
+ (void)binary; // old servers request ascii because the protocol didn't
support binary yet
if (size == 0)
return NULL;
@@ -115,7 +116,7 @@ snapshot_database_stream(char *dbname, s
goto bailout;
}
- mapi_setfilecallback(conn, NULL, snapshot_database_stream_helper, &ss);
+ mapi_setfilecallback2(conn, NULL, snapshot_database_stream_helper, &ss);
handle = mapi_prepare(conn, "CALL sys.hot_snapshot('/root/dummy', 0)");
if (handle == NULL || mapi_error(conn)) {
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]