Changeset: a999c79cabb2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/a999c79cabb2
Modified Files:
        common/stream/mapi_stream.c
        common/stream/stream.h
Branch: copyintobinary
Log Message:

Implement mapi_request_download


diffs (170 lines):

diff --git a/common/stream/mapi_stream.c b/common/stream/mapi_stream.c
--- a/common/stream/mapi_stream.c
+++ b/common/stream/mapi_stream.c
@@ -24,15 +24,15 @@ discard(stream *s)
        }
 }
 
-struct mapi_recv_upload {
+struct mapi_filetransfer {
        stream *from_client; // set to NULL after sending MAPI_PROMPT3
        stream *to_client; // set to NULL when client sends empty
 };
 
 static ssize_t
-recv_upload_read(stream *restrict s, void *restrict buf, size_t elmsize, 
size_t cnt)
+upload_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt)
 {
-       struct mapi_recv_upload *state = s->stream_data.p;
+       struct mapi_filetransfer *state = s->stream_data.p;
 
        if (state->from_client == NULL) {
                assert(s->eof);
@@ -69,9 +69,9 @@ recv_upload_read(stream *restrict s, voi
 }
 
 static void
-recv_upload_close(stream *s)
+upload_close(stream *s)
 {
-       struct mapi_recv_upload *state = s->stream_data.p;
+       struct mapi_filetransfer *state = s->stream_data.p;
 
        stream *from = state->from_client;
        if (from)
@@ -79,25 +79,48 @@ recv_upload_close(stream *s)
 
        stream *to = state->to_client;
        mnstr_write(to, PROMPT3, strlen(PROMPT3), 1);
-       mnstr_flush(to, MNSTR_FLUSH_ALL);
+       mnstr_flush(to, MNSTR_FLUSH_DATA);
+}
+
+static ssize_t
+download_write(stream *restrict s, const void *restrict buf, size_t elmsize, 
size_t cnt)
+{
+       struct mapi_filetransfer *state = s->stream_data.p;
+       stream *to = state->to_client;
+       return to->write(to, buf, elmsize, cnt);
 }
 
 static void
-recv_upload_destroy(stream *s)
+download_close(stream *s)
 {
-       struct mapi_recv_upload *state = s->stream_data.p;
+       struct mapi_filetransfer *state = s->stream_data.p;
+
+       stream *to = state->to_client;
+       stream *from = state->from_client;
+       if (to)
+               mnstr_flush(to, MNSTR_FLUSH_DATA);
+       if (from)
+               discard(from);
+}
+
+static void
+destroy(stream *s)
+{
+       struct mapi_filetransfer *state = s->stream_data.p;
        free(state);
        destroy_stream(s);
 }
 
 
-stream*
-mapi_request_upload(const char *filename, bool binary, bstream *bs, stream *ws)
+static stream*
+setup_transfer(const char *req, const char *filename, bstream *bs, stream *ws)
 {
        const char *msg = NULL;
        stream *s = NULL;
-       struct mapi_recv_upload *state = NULL;
+       struct mapi_filetransfer *state = NULL;
        ssize_t nwritten;
+       ssize_t nread;
+       bool ok;
 
        while (!bs->eof)
                bstream_next(bs);
@@ -105,10 +128,7 @@ mapi_request_upload(const char *filename
        assert(isa_block_stream(ws));
        assert(isa_block_stream(rs));
 
-       if (binary)
-               nwritten = mnstr_printf(ws, "%srb %s\n", PROMPT3, filename);
-       else
-               nwritten = mnstr_printf(ws, "%sr 0 %s\n", PROMPT3, filename);
+       nwritten = mnstr_printf(ws, PROMPT3 "%s %s\n", req, filename);
        if (nwritten <= 0) {
                msg = mnstr_peek_error(ws);
                goto end;
@@ -119,7 +139,9 @@ mapi_request_upload(const char *filename
        }
 
        char buf[256];
-       if (mnstr_readline(rs, buf, sizeof(buf)) != 1 || buf[0] != '\n') {
+       nread = mnstr_readline(rs, buf, sizeof(buf));
+       ok = (nread == 0 || (nread == 1 && buf[0] == '\n'));
+       if (!ok) {
                msg = buf;
                discard(rs);
                goto end;
@@ -139,10 +161,6 @@ mapi_request_upload(const char *filename
        state->from_client = rs;
        state->to_client = ws;
        s->stream_data.p = state;
-       s->binary= binary;
-       s->read = recv_upload_read;
-       s->close = recv_upload_close;
-       s->destroy = recv_upload_destroy;
 end:
        if (msg) {
                mnstr_destroy(s);
@@ -152,3 +170,36 @@ end:
                return s;
        }
 }
+
+stream*
+mapi_request_upload(const char *filename, bool binary, bstream *bs, stream *ws)
+{
+       const char *req = binary ? "rb" : "r 0";
+       stream *s = setup_transfer(req, filename, bs, ws);
+       if (s == NULL)
+               return NULL;
+
+       s->binary = binary;
+       s->read = upload_read;
+       s->close = upload_close;
+       s->destroy = destroy;
+
+       return s;
+}
+
+stream*
+mapi_request_download(const char *filename, bool binary, bstream *bs, stream 
*ws)
+{
+       const char *req = binary ? "wb" : "w";
+       stream *s = setup_transfer(req, filename, bs, ws);
+       if (s == NULL)
+               return NULL;
+
+       s->binary = binary;
+       s->readonly = false;
+       s->write = download_write;
+       s->close = download_close;
+       s->destroy = destroy;
+
+       return s;
+}
diff --git a/common/stream/stream.h b/common/stream/stream.h
--- a/common/stream/stream.h
+++ b/common/stream/stream.h
@@ -265,5 +265,6 @@ stream_export stream *stream_fwf_create(
 stream_export stream *create_text_stream(stream *s);
 
 stream_export stream *mapi_request_upload(const char *filename, bool binary, 
bstream *rs, stream *ws);
+stream_export stream *mapi_request_download(const char *filename, bool binary, 
bstream *rs, stream *ws);
 
 #endif /*_STREAM_H_*/
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to