|
Packit |
a4aae4 |
// XDRStreamMarshaller.cc
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// -*- mode: c++; c-basic-offset:4 -*-
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
// Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Copyright (c) 2002,2003,2016 OPeNDAP, Inc.
|
|
Packit |
a4aae4 |
// Author: Patrick West <pwest@ucar.edu>
|
|
Packit |
a4aae4 |
// James Gallagher <jgallagher@opendap.org>
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is free software; you can redistribute it and/or
|
|
Packit |
a4aae4 |
// modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License as published by the Free Software Foundation; either
|
|
Packit |
a4aae4 |
// version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is distributed in the hope that it will be useful,
|
|
Packit |
a4aae4 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4aae4 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4aae4 |
// Lesser General Public License for more details.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// (c) COPYRIGHT URI/MIT 1994-1999
|
|
Packit |
a4aae4 |
// Please read the full copyright statement in the file COPYRIGHT_URI.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Authors:
|
|
Packit |
a4aae4 |
// pwest Patrick West <pwest@ucar.edu>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef HAVE_PTHREAD_H
|
|
Packit |
a4aae4 |
#include <pthread.h>
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cassert>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <iostream>
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
#include <iomanip>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// #define DODS_DEBUG
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "XDRStreamMarshaller.h"
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
#include "MarshallerThread.h"
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#include "Vector.h"
|
|
Packit |
a4aae4 |
#include "XDRUtils.h"
|
|
Packit |
a4aae4 |
#include "util.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using namespace std;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Build this code so it does not use pthreads to write some kinds of
|
|
Packit |
a4aae4 |
// data (see the put_vector() and put_vector_part() methods) in a child thread.
|
|
Packit |
a4aae4 |
// #undef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
char *XDRStreamMarshaller::d_buf = 0;
|
|
Packit |
a4aae4 |
static const int XDR_DAP_BUFF_SIZE=256;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Build an instance of XDRStreamMarshaller. Bind the C++ stream out to this
|
|
Packit |
a4aae4 |
* instance. If the checksum parameter is true, initialize a checksum buffer
|
|
Packit |
a4aae4 |
* and enable the use of the reset_checksum() and get_checksum() methods.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param out Write to this stream object.
|
|
Packit |
a4aae4 |
* @param checksum If true, compute checksums. False by default
|
|
Packit |
a4aae4 |
* @param write_data If true, write data values. True by default
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
XDRStreamMarshaller::XDRStreamMarshaller(ostream &out) :
|
|
Packit |
a4aae4 |
d_out(out), d_partial_put_byte_count(0), tm(0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!d_buf) d_buf = (char *) malloc(XDR_DAP_BUFF_SIZE);
|
|
Packit |
a4aae4 |
if (!d_buf) throw Error(internal_error, "Failed to allocate memory for data serialization.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
xdrmem_create(&d_sink, d_buf, XDR_DAP_BUFF_SIZE, XDR_ENCODE);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
tm = new MarshallerThread;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
XDRStreamMarshaller::~XDRStreamMarshaller()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Added this because when USE_POS... is not defined, 'tm' has no
|
|
Packit |
a4aae4 |
// type, which the compiler complains about.
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
delete tm;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
xdr_destroy(&d_sink);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_byte(dods_byte val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error. Could not send byte data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_char(&d_sink, (char *) &val))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send byte data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send byte data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_int16(dods_int16 val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send int 16 data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!XDR_INT16(&d_sink, &val))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send int 16 data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send int 16 data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_int32(dods_int32 val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send int 32 data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!XDR_INT32(&d_sink, &val))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Culd not read int 32 data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send int 32 data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_float32(dods_float32 val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send float 32 data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_float(&d_sink, &val))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send float 32 data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send float 32 data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_float64(dods_float64 val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send float 64 data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_double(&d_sink, &val))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send float 64 data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send float 64 data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_uint16(dods_uint16 val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send uint 16 data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!XDR_UINT16(&d_sink, &val))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send uint 16 data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send uint 16 data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_uint32(dods_uint32 val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send uint 32 data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!XDR_UINT32(&d_sink, &val))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send uint 32 data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send uint 32 data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_str(const string &val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
int size = val.length() + 8;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
XDR str_sink;
|
|
Packit |
a4aae4 |
vector<char> str_buf(size);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
xdrmem_create(&str_sink, &str_buf[0], size, XDR_ENCODE);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&str_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send string data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const char *out_tmp = val.c_str();
|
|
Packit |
a4aae4 |
if (!xdr_string(&str_sink, (char **) &out_tmp, size))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send string data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&str_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send string data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(&str_buf[0], bytes_written);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
xdr_destroy(&str_sink);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (...) {
|
|
Packit |
a4aae4 |
xdr_destroy(&str_sink);
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_url(const string &val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
put_str(val);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_opaque(char *val, unsigned int len)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (len > XDR_DAP_BUFF_SIZE)
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error. Could not send opaque data - length of opaque data larger than allowed");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send opaque data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_opaque(&d_sink, val, len))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send opaque data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send opaque data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_int(int val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&d_sink, 0))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send int data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_int(&d_sink, &val))
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error(1). Could not send int data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&d_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
"Network I/O Error. Could not send int data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(d_buf, bytes_written);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_vector(char *val, int num, int width, Vector &vec)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
put_vector(val, num, width, vec.var()->type());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Prepare to send a single array/vector using a series of 'put' calls.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param num The number of elements in the Array/Vector
|
|
Packit |
a4aae4 |
* @see put_vector_part()
|
|
Packit |
a4aae4 |
* @see put_vector_end()
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_vector_start(int num)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
put_int(num);
|
|
Packit |
a4aae4 |
put_int(num);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_partial_put_byte_count = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Close a vector when its values are written using put_vector_part().
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @see put_vector_start()
|
|
Packit |
a4aae4 |
* @see put_vector_part()
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_vector_end()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Compute the trailing (padding) bytes
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Note that the XDR standard pads values to 4 byte boundaries.
|
|
Packit |
a4aae4 |
//unsigned int pad = (d_partial_put_byte_count % 4) == 0 ? 0: 4 - (d_partial_put_byte_count % 4);
|
|
Packit |
a4aae4 |
unsigned int mod_4 = d_partial_put_byte_count & 0x03;
|
|
Packit |
a4aae4 |
unsigned int pad = (mod_4 == 0) ? 0: 4 - mod_4;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (pad) {
|
|
Packit |
a4aae4 |
vector<char> padding(4, 0); // 4 zeros
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_out.write(&padding[0], pad);
|
|
Packit |
a4aae4 |
if (d_out.fail()) throw Error("Network I/O Error. Could not send vector data padding");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Start of parallel I/O support. jhrg 8/19/15
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_vector(char *val, int num, Vector &)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!val) throw InternalErr(__FILE__, __LINE__, "Could not send byte vector data. Buffer pointer is not set.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// write the number of members of the array being written and then set the position to 0
|
|
Packit |
a4aae4 |
put_int(num);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// this is the word boundary for writing xdr bytes in a vector.
|
|
Packit |
a4aae4 |
const unsigned int add_to = 8;
|
|
Packit |
a4aae4 |
// switch to memory on the heap since the thread will need to access it
|
|
Packit |
a4aae4 |
// after this code returns.
|
|
Packit |
a4aae4 |
char *byte_buf = new char[num + add_to];
|
|
Packit |
a4aae4 |
XDR byte_sink;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
xdrmem_create(&byte_sink, byte_buf, num + add_to, XDR_ENCODE);
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&byte_sink, 0))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error. Could not send byte vector data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_bytes(&byte_sink, (char **) &val, (unsigned int *) &num, num + add_to))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error(2). Could not send byte vector data - unable to encode data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&byte_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error. Could not send byte vector data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
tm->increment_child_thread_count();
|
|
Packit |
a4aae4 |
tm->start_thread(MarshallerThread::write_thread, d_out, byte_buf, bytes_written);
|
|
Packit |
a4aae4 |
xdr_destroy(&byte_sink);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
d_out.write(byte_buf, bytes_written);
|
|
Packit |
a4aae4 |
xdr_destroy(&byte_sink);
|
|
Packit |
a4aae4 |
delete [] byte_buf;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (...) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Caught an exception in put_vector_thread" << endl);
|
|
Packit |
a4aae4 |
xdr_destroy(&byte_sink);
|
|
Packit |
a4aae4 |
delete [] byte_buf;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// private
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Write elements of a Vector (i.e. an Array) to the stream using XDR encoding.
|
|
Packit |
a4aae4 |
* Encoding is performed on 'num' values that use 'width' bytes. The parameter
|
|
Packit |
a4aae4 |
* 'type' is used to choose the XDR encoding function.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param val Pointer to the values to write
|
|
Packit |
a4aae4 |
* @param num The number of elements in the memory referenced by 'val'
|
|
Packit |
a4aae4 |
* @param width The number of bytes in each element
|
|
Packit |
a4aae4 |
* @param type The DAP type of the elements
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_vector(char *val, unsigned int num, int width, Type type)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(val || num == 0);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// write the number of array members being written, then set the position back to 0
|
|
Packit |
a4aae4 |
put_int(num);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (num == 0)
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int use_width = width;
|
|
Packit |
a4aae4 |
if (use_width < 4) use_width = 4;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// the size is the number of elements num times the width of each
|
|
Packit |
a4aae4 |
// element, then add 4 bytes for the number of elements
|
|
Packit |
a4aae4 |
int size = (num * use_width) + 4;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// allocate enough memory for the elements
|
|
Packit |
a4aae4 |
//vector<char> vec_buf(size);
|
|
Packit |
a4aae4 |
char *vec_buf = new char[size];
|
|
Packit |
a4aae4 |
XDR vec_sink;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
xdrmem_create(&vec_sink, vec_buf, size, XDR_ENCODE);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// set the position of the sink to 0, we're starting at the beginning
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&vec_sink, 0))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error. Could not send vector data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// write the array to the buffer
|
|
Packit |
a4aae4 |
if (!xdr_array(&vec_sink, (char **) &val, (unsigned int *) &num, size, width, XDRUtils::xdr_coder(type)))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error(2). Could not send vector data - unable to encode.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// how much was written to the buffer
|
|
Packit |
a4aae4 |
unsigned int bytes_written = xdr_getpos(&vec_sink);
|
|
Packit |
a4aae4 |
if (!bytes_written)
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error. Could not send vector data - unable to get stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
tm->increment_child_thread_count();
|
|
Packit |
a4aae4 |
tm->start_thread(MarshallerThread::write_thread, d_out, vec_buf, bytes_written);
|
|
Packit |
a4aae4 |
xdr_destroy(&vec_sink);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
d_out.write(vec_buf, bytes_written);
|
|
Packit |
a4aae4 |
xdr_destroy(&vec_sink);
|
|
Packit |
a4aae4 |
delete [] vec_buf;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (...) {
|
|
Packit |
a4aae4 |
xdr_destroy(&vec_sink);
|
|
Packit |
a4aae4 |
delete [] vec_buf;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Write num values for an Array/Vector.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param val The values to write
|
|
Packit |
a4aae4 |
* @param num the number of values to write
|
|
Packit |
a4aae4 |
* @param width The width of the values
|
|
Packit |
a4aae4 |
* @param type The DAP2 type of the values.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @see put_vector_start()
|
|
Packit |
a4aae4 |
* @see put_vector_end()
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::put_vector_part(char *val, unsigned int num, int width, Type type)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (width == 1) {
|
|
Packit |
a4aae4 |
// Add space for the 4 bytes of length info and 4 bytes for padding, even though
|
|
Packit |
a4aae4 |
// we will not send either of those.
|
|
Packit |
a4aae4 |
const unsigned int add_to = 8;
|
|
Packit |
a4aae4 |
unsigned int bufsiz = num + add_to;
|
|
Packit |
a4aae4 |
//vector<char> byte_buf(bufsiz);
|
|
Packit |
a4aae4 |
char *byte_buf = new char[bufsiz];
|
|
Packit |
a4aae4 |
XDR byte_sink;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
xdrmem_create(&byte_sink, byte_buf, bufsiz, XDR_ENCODE);
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&byte_sink, 0))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error. Could not send byte vector data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!xdr_bytes(&byte_sink, (char **) &val, (unsigned int *) &num, bufsiz))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error(2). Could not send byte vector data - unable to encode data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
tm->increment_child_thread_count();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Increment the element count so we can figure out about the padding in put_vector_last()
|
|
Packit |
a4aae4 |
d_partial_put_byte_count += num;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
tm->start_thread(MarshallerThread::write_thread_part, d_out, byte_buf, num);
|
|
Packit |
a4aae4 |
xdr_destroy(&byte_sink);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
// Only send the num bytes that follow the 4 bytes of length info - we skip the
|
|
Packit |
a4aae4 |
// length info because it's already been sent and we don't send any trailing padding
|
|
Packit |
a4aae4 |
// bytes in this method (see put_vector_last() for that).
|
|
Packit |
a4aae4 |
d_out.write(byte_buf + 4, num);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (d_out.fail())
|
|
Packit |
a4aae4 |
throw Error ("Network I/O Error. Could not send initial part of byte vector data");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now increment the element count so we can figure out about the padding in put_vector_last()
|
|
Packit |
a4aae4 |
d_partial_put_byte_count += num;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
xdr_destroy(&byte_sink);
|
|
Packit |
a4aae4 |
delete [] byte_buf;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (...) {
|
|
Packit |
a4aae4 |
xdr_destroy(&byte_sink);
|
|
Packit |
a4aae4 |
delete [] byte_buf;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
int use_width = (width < 4) ? 4 : width;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// the size is the number of elements num times the width of each
|
|
Packit |
a4aae4 |
// element, then add 4 bytes for the (int) number of elements
|
|
Packit |
a4aae4 |
int size = (num * use_width) + 4;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// allocate enough memory for the elements
|
|
Packit |
a4aae4 |
//vector<char> vec_buf(size);
|
|
Packit |
a4aae4 |
char *vec_buf = new char[size];
|
|
Packit |
a4aae4 |
XDR vec_sink;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
xdrmem_create(&vec_sink, vec_buf, size, XDR_ENCODE);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// set the position of the sink to 0, we're starting at the beginning
|
|
Packit |
a4aae4 |
if (!xdr_setpos(&vec_sink, 0))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error. Could not send vector data - unable to set stream position.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// write the array to the buffer
|
|
Packit |
a4aae4 |
if (!xdr_array(&vec_sink, (char **) &val, (unsigned int *) &num, size, width, XDRUtils::xdr_coder(type)))
|
|
Packit |
a4aae4 |
throw Error("Network I/O Error(2). Could not send vector data -unable to encode data.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef USE_POSIX_THREADS
|
|
Packit |
a4aae4 |
Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
|
|
Packit |
a4aae4 |
tm->increment_child_thread_count();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Increment the element count so we can figure out about the padding in put_vector_last()
|
|
Packit |
a4aae4 |
d_partial_put_byte_count += (size - 4);
|
|
Packit |
a4aae4 |
tm->start_thread(MarshallerThread::write_thread_part, d_out, vec_buf, size - 4);
|
|
Packit |
a4aae4 |
xdr_destroy(&vec_sink);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
// write that much out to the output stream, skipping the length data that
|
|
Packit |
a4aae4 |
// XDR writes since we have already written the length info using put_vector_start()
|
|
Packit |
a4aae4 |
d_out.write(vec_buf + 4, size - 4);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (d_out.fail())
|
|
Packit |
a4aae4 |
throw Error ("Network I/O Error. Could not send part of vector data");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now increment the element count so we can figure out about the padding in put_vector_last()
|
|
Packit |
a4aae4 |
d_partial_put_byte_count += (size - 4);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
xdr_destroy(&vec_sink);
|
|
Packit |
a4aae4 |
delete [] vec_buf;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (...) {
|
|
Packit |
a4aae4 |
xdr_destroy(&vec_sink);
|
|
Packit |
a4aae4 |
delete [] vec_buf;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XDRStreamMarshaller::dump(ostream &strm) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "XDRStreamMarshaller::dump - (" << (void *) this << ")" << endl;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|
|
Packit |
a4aae4 |
|