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 -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org