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

Reply via email to