Пример #1
0
pwr_tStatus
wb_dbs::writeSectFile(size_t size)
{
  char f[dbs_dAlign(sizeof(dbs_sFile))];
  dbs_sFile *fp = (dbs_sFile*)f;
  PDR pdrs;

  co_GetOwnFormat(&fp->format);
  fp->cookie = dbs_cMagicCookie;
  fp->size = size;
  fp->offset = dbs_dAlign(sizeof(*fp));
  fp->formatVersion = dbs_cVersionFormat;
  fp->version = dbs_cVersionFile;
  fp->sectVersion = dbs_cVersionDirectory;
  fp->pwrVersion = 1;
  fp->time = m_volume.time;
  fp->fileType = dbs_eFile_volume;

  strcpy(fp->userName, "");
  strcpy(fp->comment, "");

  pdrmem_create(&pdrs, (char *) fp, sizeof(*fp), PDR_DECODE, fp->format, fp->format);
  if (!pdr_dbs_sFile(&pdrs, fp))
    return LDH__XDR;

  if (fseek(m_fp, 0, SEEK_SET) != 0)
    return LDH__FILEPOS;

  if (fwrite(f, sizeof(f) , 1, m_fp) < 1) return LDH__FILEWRITE;

  return LDH__SUCCESS;
}
Пример #2
0
dbs_sEnv *
dbs_Open(pwr_tStatus *sts, dbs_sEnv *ep, const char *filename)
{
    FILE *f;
    co_mFormat srcFormat, ownFormat;
    PDR pdrs;
    dbs_sSect sect;

    *sts = DBS__SUCCESS;
    memset(ep, 0, sizeof(*ep));
    
    f = fopen(filename, "r");
    if (f == NULL) {
        *sts = errno_GetStatus();
        return NULL;
    } 

    if (fread(&ep->file, sizeof(ep->file), 1, f) == 0) {
        *sts = errno_GetStatus();
        fclose(f);
        return NULL;
    }
    
    fseek(f, ep->file.offset, SEEK_SET);

    if (fread(&sect, sizeof(sect), 1, f) == 0) {
        *sts = errno_GetStatus();
        fclose(f);
        return NULL;
    }

    ep->nSect = sect.size / dbs_dAlign(sizeof(sect));
    

#if 0
    srcFormat.m = ntohl(ep->file.format.m);    
#else
    srcFormat.m = ep->file.format.m;    
#endif
    co_GetOwnFormat(&ownFormat);

    if (srcFormat.m != ownFormat.m) {
        pdrmem_create(&pdrs, &ep->file, sizeof(ep->file), PDR_DECODE, srcFormat, ownFormat);
        if (!pdr_dbs_sFile(&pdrs, &ep->file)) {
            *sts = DBS__PDRFILE;
            fclose(f);
            return NULL;
        }
    }
    
    fseek(f, 0, SEEK_SET);
    ep->f = f;

    return ep;
}
Пример #3
0
int Message_recv(XPlat_Socket sock_fd, vector_t* packets_in, Rank iinlet_rank)
{
    int retval;
    unsigned int i;
    uint32_t num_packets = 0;
    uint32_t num_buffers = 0;
    PDR pdrs;
    enum pdr_op op = PDR_DECODE;
    size_t psz, recv_total, total_bytes = 0;
    uint64_t buf_len = 0;
    ssize_t readRet;
    XPlat_NCBuf_t* ncbufs;
    Packet_t* new_packet;
    uint64_t *packet_sizes;
    char *buf = NULL;
    
    mrn_dbg_func_begin();
 
    mrn_dbg(5, mrn_printf(FLF, stderr, "sock_fd = %d\n", sock_fd));

    //
    // packet count
    //

    mrn_dbg(5, mrn_printf(FLF, stderr, "Calling sizeof ...\n"));
    pdr_sizeof((pdrproc_t)(pdr_uint32), &num_packets, &buf_len);
    assert(buf_len);
    buf = (char*) malloc(buf_len + 1);
    assert(buf);

    mrn_dbg(3, mrn_printf(FLF, stderr, "Reading packet count\n"));

    readRet = MRN_recv(sock_fd, buf, buf_len + 1);
    if( readRet != (ssize_t)buf_len + 1) {
        mrn_dbg(3, mrn_printf(FLF, stderr, "MRN_recv() of packet count failed\n"));
        free(buf);
        return -1;
    }
    
    mrn_dbg(5, mrn_printf(FLF, stderr, "Calling memcreate ...\n"));
    pdrmem_create(&pdrs, &(buf[1]), buf_len, op, (pdr_byteorder) buf[0]);
    mrn_dbg(5, mrn_printf(FLF, stderr, "Calling uint32 ...\n"));
    if( ! pdr_uint32(&pdrs, &num_packets) ) {
        error(ERR_PACKING, iinlet_rank, "pdr_uint32() failed\n");
        free(buf);
        return -1;
    } 
    free(buf);
    mrn_dbg(3, mrn_printf(FLF, stderr, "Will receive %u packets\n", num_packets));

    if( num_packets > 10000 )
        mrn_dbg(1, mrn_printf(FLF, stderr, "WARNING: Receiving more than 10000 packets\n"));
    if( num_packets == 0 )
        mrn_dbg(1, mrn_printf(FLF, stderr, "WARNING: Receiving zero packets\n"));

    num_buffers = num_packets * 2;

    //
    // packet size vector
    //
    
    //buf_len's value is hardcode, breaking pdr encapsulation barrier
    buf_len = (sizeof(uint64_t) * num_buffers) + 1; // 1 byte pdr overhead

    //mrn_dbg(5, mrn_printf(FLF, stderr, "Calling malloc(%u) ...\n", buf_len));
    buf = (char*) malloc( buf_len );
    if( buf == NULL ) {
        mrn_dbg(1, mrn_printf(FLF, stderr,
                              "malloc failed for buf\n"));
        return -1;
    }

    //mrn_dbg(5, mrn_printf(FLF, stderr, "Calling malloc ...\n"));
    packet_sizes = (uint64_t*) malloc( sizeof(uint64_t) * (size_t)num_buffers );
    if( packet_sizes == NULL ) {
        mrn_dbg(1, mrn_printf(FLF, stderr,
                              "malloc failed for packet_sizes\n"));
        return -1;
    }

    mrn_dbg(5, mrn_printf(FLF, stderr, 
                          "Calling read(%p, %"PRIu64") for %d buffer lengths.\n",
                          buf, buf_len, num_buffers));
    readRet = MRN_recv(sock_fd, buf, (size_t)buf_len);
    if( readRet != (ssize_t)buf_len ) {
        mrn_dbg(3, mrn_printf(FLF, stderr, "MRN_recv() %"PRIsszt" of %"PRIsszt" bytes received\n", readRet, buf_len));
        free(buf);
        //free(packet_sizes);
        return -1;
    }

    pdrmem_create(&pdrs, buf, buf_len, op, pdrmem_getbo());
    if( ! pdr_vector(&pdrs, (char*)packet_sizes, num_buffers,
                     (uint64_t) sizeof(uint64_t), (pdrproc_t)pdr_uint64) ) {
        mrn_dbg(1, mrn_printf(FLF, stderr, "pdr_vector() failed\n"));
        error(ERR_PACKING, iinlet_rank, "pdr_uint32() failed\n");
        free(buf);
        free(packet_sizes);
        return -1;
    }
    free(buf);

    //
    // packets
    //
    
    /* recv packet buffers */
    ncbufs = (XPlat_NCBuf_t*) malloc( sizeof(XPlat_NCBuf_t) * (size_t)num_buffers );
    assert(ncbufs);

    mrn_dbg(5, mrn_printf(FLF, stderr, "Reading %u packets:\n", num_packets));

    for( i = 0; i < num_buffers; i++ ) {
        psz = (size_t) packet_sizes[i];
        ncbufs[i].buf = (char*) malloc(psz);
        assert(ncbufs[i].buf);
        ncbufs[i].len = psz;
        total_bytes += psz;
        mrn_dbg(5, mrn_printf(FLF, stderr, "- buffer[%u] has size %"PRIsszt"\n", 
                              i, psz));
    }

    mrn_dbg(5, mrn_printf(FLF, stderr, 
                          "Reading num_buffers=%d\n", num_buffers));
    recv_total = 0;
    for(i = 0; i < num_buffers; i++ ) {
        readRet = MRN_recv( sock_fd, ncbufs[i].buf, ncbufs[i].len );
        if( readRet < 0 ) {
            mrn_dbg(1, mrn_printf(FLF, stderr, 
                                  "MRN_recv() failed for packet %u\n", i));
            break;
        }
        recv_total += (int) readRet;
    }
    if( recv_total != total_bytes ) {
        mrn_dbg(1, mrn_printf(FLF, stderr,
                              "%"PRIsszt" of %"PRIsszt" received\n", 
                              recv_total, total_bytes));

        for( i = 0; i < num_buffers; i++ )
            free((void*)(ncbufs[i].buf));
        free(ncbufs);
        free(packet_sizes);
        return -1;

    }

    //
    // post-processing
    //

    retval = 0;
    mrn_dbg(3, mrn_printf(FLF, stderr, "Creating Packets ...\n"));
    for( i = 0; i < num_buffers; i += 2 ) {
        mrn_dbg(5, mrn_printf(FLF, stderr, "creating packet[%d]\n",i));

        new_packet = new_Packet_t_3( ncbufs[i].len, ncbufs[i].buf, 
                                     ncbufs[i+1].len, ncbufs[i+1].buf, 
                                     iinlet_rank );
        if( new_packet == NULL ) {
            mrn_dbg(1, mrn_printf(FLF, stderr, "packet creation failed\n"));
            retval = -1;
            break;
        }   

        pushBackElement(packets_in, new_packet);
    }

    // release dynamically allocated memory

    // Note: on success return, don't release the packet buffers; 
    //       that memory was passed to the Packet object(s).
    if( retval == -1 ) {
        for (i = 0; i < num_buffers; i++) {
            char * b = ncbufs[i].buf;
            free(b);
        }
    }
    free( ncbufs );
    free( packet_sizes );

    mrn_dbg_func_end();
    return retval;
}
Пример #4
0
int Message_send(Message_t* msg_out, XPlat_Socket sock_fd)
{
    uint32_t num_buffers, num_packets;
    uint64_t buf_len;
    PDR pdrs;
    enum pdr_op op = PDR_ENCODE;
    int err, go_away = 0;
    size_t total_bytes;
    ssize_t sret, mcwret;
    char* buf = NULL;

    XPlat_NCBuf_t ncbufs[2];
    uint64_t packet_sizes[2];

    mrn_dbg(3, mrn_printf(FLF, stderr, "Sending packets from message %p\n", msg_out));

    if( msg_out->packet == NULL ) { // if there is no packet to send
        mrn_dbg(3, mrn_printf(FLF, stderr, "Nothing to send!\n"));
        return 0;
    }

    if( (msg_out->packet->tag == PROT_SHUTDOWN) || 
        (msg_out->packet->tag == PROT_SHUTDOWN_ACK) )
        go_away = 1;

    //
    // pre-processing
    //

    /* lightweight send is always single packet */
    num_packets = 1;
    num_buffers = num_packets * 2;

    ncbufs[0].buf = msg_out->packet->hdr;
    ncbufs[0].len = msg_out->packet->hdr_len;
    ncbufs[1].buf = msg_out->packet->buf;
    ncbufs[1].len = (size_t)msg_out->packet->buf_len;
    total_bytes = ncbufs[0].len + ncbufs[1].len;

    packet_sizes[0] = ncbufs[0].len;
    packet_sizes[1] = ncbufs[1].len;


    //
    // packet count
    //

    pdr_sizeof((pdrproc_t)(pdr_uint32), &num_packets, &buf_len);
    assert(buf_len);
    buf = (char*) malloc(buf_len + 1);
    assert(buf);
    pdrmem_create(&pdrs, &(buf[1]), buf_len, op, pdrmem_getbo());

    if( ! pdr_uint32(&pdrs, &num_packets) ) {
        mrn_dbg( 1, mrn_printf(FLF, stderr, "pdr_uint32() failed\n") );
        free(buf);
        return -1;
    }
    buf[0] = (char) pdrmem_getbo();
    mrn_dbg(5, mrn_printf(FLF, stderr, "writing packet count\n"));
    mcwret = MRN_send(sock_fd, buf, buf_len + 1);
    if( mcwret != (ssize_t)buf_len + 1) {
        mrn_dbg(1, mrn_printf(FLF, stderr, "MRN_send() failed\n"));
        free(buf);
        return -1;
    }
    mrn_dbg(5, mrn_printf(FLF, stderr, "MRN_send() succeeded\n"));
    free(buf);

    //
    // packet size vector
    //

    buf_len = (num_buffers * sizeof(uint64_t)) + 1; // 1 extra bytes overhead
    buf = (char*) malloc( buf_len );
    assert(buf);
    pdrmem_create(&pdrs, buf, (uint64_t)buf_len, op, pdrmem_getbo());

    if( ! pdr_vector(&pdrs, (char*)(packet_sizes), num_buffers, 
                     (uint64_t) sizeof(uint64_t), (pdrproc_t) pdr_uint64) ) {
        mrn_dbg(1, mrn_printf(FLF, stderr, "pdr_vector() failed\n"));
        free(buf);
        return -1;
    }

    mrn_dbg(5, mrn_printf(FLF, stderr, "write(%p, %d) of size vector\n", 
                          buf, buf_len));
    mcwret = MRN_send(sock_fd, buf, (size_t)buf_len);
    if( mcwret != (ssize_t)buf_len ) {
        mrn_dbg(1, mrn_printf(FLF, stderr, "MRN_send failed\n"));
        free(buf);
        return -1;
    }
    free(buf);

    //
    // packets
    //

    mrn_dbg(3, mrn_printf(FLF, stderr,
                          "Sending %d packets (%d total bytes)\n", 
                          num_packets, total_bytes));

    sret = XPlat_SocketUtils_Send(sock_fd, ncbufs, num_buffers);
    if( sret != (ssize_t)total_bytes ) {
        err = XPlat_NetUtils_GetLastError();
        mrn_dbg(1, mrn_printf(FLF, stderr,
                              "XPlat_SocketUtils_Send() returned %d of %d bytes,"
                              " errno = %d, nbuffers = %d\n", 
                              sret, total_bytes, err, num_packets));
        return -1;
    }

    if( go_away )
        XPlat_SocketUtils_Close(sock_fd);

    mrn_dbg_func_end();
    return 0;
}
Пример #5
0
int Message::recv( XPlat_Socket sock_fd, std::list< PacketPtr > &packets_in,
                   Rank iinlet_rank )
{
    Timer t1;
    t1.start();
    ssize_t retval;
    size_t buf_len;
    uint64_t *packet_sizes;
    char *buf = NULL;
    XPlat::SocketUtils::NCBuf* ncbufs;
    uint64_t len;
    unsigned int i, j;
    int rc = 0;
    ssize_t total_bytes = 0;
    uint32_t num_packets = 0, num_buffers;
    PDR pdrs;
    enum pdr_op op = PDR_DECODE;
    bool using_prealloc = true;
    int pkt_size;
    PacketPtr pkt; 
    Stream * strm;
    std::list< PacketPtr >::iterator piter;

    retval = MRN_recv( sock_fd, _packet_count_buf, size_t(_packet_count_buf_len + 1));
    if( retval != (ssize_t)_packet_count_buf_len + 1 ) {
        mrn_dbg( 3, mrn_printf(FLF, stderr, "MRN_recv() %" PRIsszt" of %" PRIszt" bytes received\n", 
                               retval, _packet_count_buf_len));
        return -1;
    }

    pdrmem_create( &pdrs, &(_packet_count_buf[1]), _packet_count_buf_len, op, (pdr_byteorder)_packet_count_buf[0] );

    if( ! pdr_uint32(&pdrs, &num_packets) ) {
        mrn_dbg( 1, mrn_printf(FLF, stderr, "pdr_uint32() failed\n") );
        return -1;
    }
    
    num_buffers = num_packets * 2;

    //
    // packet size vector
    //

    // buf_len's value is hardcoded, breaking pdr encapsulation barrier :(
    buf_len = (sizeof(uint64_t) * num_buffers) + 1;  // 1 byte pdr overhead
           
    if( num_buffers < _ncbuf_len ) {
        buf = _packet_sizes_buf;
        packet_sizes = _packet_sizes;
        ncbufs = _ncbuf;
        memset( (void *)_ncbuf, 0, sizeof(_ncbuf) );
    }
    else {
        using_prealloc = false;
        buf = (char*) malloc( buf_len );
        packet_sizes = (uint64_t*) malloc( sizeof(uint64_t) * num_buffers );
        ncbufs = new XPlat::SocketUtils::NCBuf[num_buffers];
        memset( (void*)ncbufs, 0,
                 num_buffers * sizeof(XPlat::SocketUtils::NCBuf) );
    }

    retval = MRN_recv( sock_fd, buf, buf_len );
    if( retval != (ssize_t)buf_len ) {
        mrn_dbg( 3, mrn_printf(FLF, stderr, "MRN_recv() %" PRIsszt" of %" PRIsszt" bytes received\n", 
                               retval, buf_len ));
        rc = -1;
        goto recv_cleanup_return;
    }

    pdrmem_create( &pdrs, buf, buf_len, op, pdrmem_getbo() );

    if( ! pdr_vector(&pdrs, (char*)packet_sizes, num_buffers,
                     sizeof(uint64_t), (pdrproc_t)pdr_uint64) ) {
        mrn_dbg( 1, mrn_printf(FLF, stderr, "pdr_vector() failed\n" ));
        rc = -1;
        goto recv_cleanup_return;
    }


    /* NOTE: we tell users that packet header and data buffers will have similar
             alignment characteristics to malloc, so if we ever stop using malloc
             we will need to make sure that the buffers are properly aligned */
    for( i = 0; i < num_buffers; i++ ) {
        len = packet_sizes[i];
        ncbufs[i].buf = (char*) malloc( size_t(len) );
        ncbufs[i].len = size_t(len);
        total_bytes += size_t(len);
    }

    retval = XPlat::SocketUtils::Recv( sock_fd, ncbufs, num_buffers );
    if( retval != total_bytes ) {
        mrn_dbg( 1, mrn_printf(FLF, stderr, "SocketUtils::Recv %" PRIsszt" of %" PRIsszt" bytes received\n", 
                               retval, total_bytes) );
        rc = -1;
        goto recv_cleanup_return;
    }

    //
    // post-processing
    //

    for( i = 0, j = 0; j < num_packets; i += 2, j++ ) {
        PacketPtr new_packet( new Packet((unsigned int)ncbufs[i].len,
                                         ncbufs[i].buf,
                                         ncbufs[i+1].len,
                                         ncbufs[i+1].buf,
                                         iinlet_rank) );

        if( new_packet->has_Error() ) {
            mrn_dbg( 1, mrn_printf(FLF, stderr, "packet creation failed\n") );
            rc = -1;
            goto recv_cleanup_return;
        }
        packets_in.push_back( new_packet );
        ncbufs[i].buf = NULL;
        ncbufs[i+1].buf = NULL;        
    }

    t1.stop();
    pkt_size = (int) packets_in.size();
    piter = packets_in.begin();
    for( ; piter != packets_in.end(); piter++ ) {
        pkt = *piter;
        strm =  _net->get_Stream( pkt->get_StreamId() );
        if( strm != NULL ) {
            // Time for packet at this point in time.
            if( strm->get_PerfData()->is_Enabled(PERFDATA_MET_ELAPSED_SEC, 
                        PERFDATA_CTX_PKT_RECV) ) {
                pkt->set_Timer(PERFDATA_PKT_TIMERS_RECV, t1);
            }
            pkt->start_Timer(PERFDATA_PKT_TIMERS_RECV_TO_FILTER);
            pkt->set_IncomingPktCount(pkt_size);
        }
    }
 recv_cleanup_return:

    if( -1 == rc ) {
        for( unsigned u = 0; u < num_buffers; u++ ) {
            if( NULL != ncbufs[u].buf )
                free( (void*)(ncbufs[u].buf) );
        }
    }

    if( ! using_prealloc ) {
        free( buf );
        free( packet_sizes );
        delete[] ncbufs;
    }

    mrn_dbg_func_end();
    return rc;
}
Пример #6
0
int Message::send( XPlat_Socket sock_fd )
{
    ssize_t sret;
    size_t buf_len, total_bytes = 0;
    Stream* strm;
    PerfDataMgr* pdm = NULL;
    uint64_t *packet_sizes = NULL;
    char *buf = NULL;
    XPlat::SocketUtils::NCBuf* ncbufs;
    Timer tmp;
    unsigned int i, j;
    int packetLength, rc = 0;
    uint32_t num_packets, num_buffers, num_ncbufs;
    PDR pdrs;
    enum pdr_op op = PDR_ENCODE;
    bool using_prealloc = true;
    bool go_away = false;
    PacketPtr pkt;
    std::list< PacketPtr > send_packets;
    std::list< PacketPtr >::iterator piter;

    _packet_sync.Lock();
    _send_sync.Lock();
    if( _packets.size() == 0 ) {   //nothing to do
        mrn_dbg( 3, mrn_printf(FLF, stderr, "Nothing to send!\n") );
        _packet_sync.Unlock();
        _send_sync.Unlock();
        return 0;
    }
    send_packets = _packets;
    _packets.clear();
    _packet_sync.Unlock();

    piter = send_packets.begin();
    for( ; piter != send_packets.end(); piter++ ) {
        pkt = *piter;
        strm = _net->get_Stream( pkt->get_StreamId() );
        if( NULL != strm ) {
            pdm = strm->get_PerfData();
            if( NULL != pdm ) {
                if( pdm->is_Enabled(PERFDATA_MET_ELAPSED_SEC, 
                                    PERFDATA_CTX_PKT_SEND) ) {
                    pkt->start_Timer(PERFDATA_PKT_TIMERS_SEND);
                    pkt->stop_Timer(PERFDATA_PKT_TIMERS_FILTER_TO_SEND);
                }
            }
        }
    }

    // Allocation (if required)
    num_packets = uint32_t(send_packets.size());
    num_buffers = num_packets * 2;
    num_ncbufs = num_buffers + 2;
    buf_len = ((size_t)num_buffers * sizeof(uint64_t)) + 1;  //1 extra bytes overhead

    if( num_ncbufs < _ncbuf_len ) {
        buf = _packet_sizes_buf;
        ncbufs = _ncbuf;
        packet_sizes = _packet_sizes;
    }
    else {
        using_prealloc = false;
        buf = (char*) malloc( buf_len );
        ncbufs = new XPlat::SocketUtils::NCBuf[ num_ncbufs ];
        packet_sizes = (uint64_t*) malloc( sizeof(uint64_t) * num_buffers );
    }

    //
    // packets
    //
    piter = send_packets.begin();
    for( i = 0; piter != send_packets.end(); piter++, i += 2 ) {

        /* j accounts for skipping first two ncbufs that hold pkt count and sizes */
        j = i + 2;

        PacketPtr& curPacket = *piter;
        
        /* check for final packet */
        int tag = curPacket->get_Tag();

        if( (tag == PROT_SHUTDOWN) || (tag == PROT_SHUTDOWN_ACK) )
            go_away = true;

        uint32_t hsz = curPacket->get_HeaderLen();
        uint64_t dsz = curPacket->get_BufferLen();

        if( hsz == 0 ) {
            /* lazy encoding of packet header */
            curPacket->encode_pdr_header();
            hsz = curPacket->get_HeaderLen();
        }

        ncbufs[j].buf = const_cast< char* >( curPacket->get_Header() );
        ncbufs[j].len = hsz;
        packet_sizes[i] = (uint64_t)hsz;

        ncbufs[j+1].buf = const_cast< char* >( curPacket->get_Buffer() );
        ncbufs[j+1].len = size_t(dsz);
        packet_sizes[i+1] = (uint64_t)dsz;

        total_bytes += (size_t)hsz + (size_t)dsz;
    }

    //
    // packet count
    //
    pdrmem_create( &pdrs, &(_packet_count_buf[1]), _packet_count_buf_len, op, pdrmem_getbo() );
    pdr_uint32(&pdrs, &num_packets);
    ncbufs[0].buf = _packet_count_buf;
    ncbufs[0].len = size_t(_packet_count_buf_len + 1);
    _packet_count_buf[0] = (char) pdrmem_getbo();
    //
    // packet sizes
    //
    pdrmem_create( &pdrs, buf, buf_len, op, pdrmem_getbo() );
    if( ! pdr_vector(&pdrs, (char*)packet_sizes, num_buffers, 
                     sizeof(uint64_t), (pdrproc_t)pdr_uint64) ) {
        mrn_dbg( 1, mrn_printf(FLF, stderr, "pdr_vector() failed\n" ));
        rc = -1;
        goto send_cleanup_return;
    }
    ncbufs[1].buf = buf;
    ncbufs[1].len = buf_len;

    // Send it all
    sret = XPlat::SocketUtils::Send( sock_fd, ncbufs, num_ncbufs );
    if( sret < (ssize_t)(total_bytes + _packet_count_buf_len + buf_len + 1) ) {
        mrn_dbg( 1, mrn_printf(FLF, stderr,
                               "XPlat::SocketUtils::Send() returned %" PRIsszt
		               " of %" PRIszt" bytes, nbuffers = %u\n",
                               sret, total_bytes, num_buffers ));
        rc = -1;
        goto send_cleanup_return;
    }

    packetLength = (int) send_packets.size();
    piter = send_packets.begin();
    for( ; piter != send_packets.end(); piter++ ) {
        pkt = *piter;
        strm = _net->get_Stream( pkt->get_StreamId() );
        if( NULL != strm ) {
            pdm = strm->get_PerfData();
            if( NULL != pdm ) {
                pkt->set_Timer( PERFDATA_PKT_TIMERS_RECV_TO_FILTER, tmp );
                if( pdm->is_Enabled(PERFDATA_MET_ELAPSED_SEC, 
                                    PERFDATA_CTX_PKT_SEND) ) {
                    pkt->set_OutgoingPktCount( packetLength );
                    pkt->stop_Timer( PERFDATA_PKT_TIMERS_SEND );
                    pdm->add_PacketTimers( pkt );
                }   
                else if( pdm->is_Enabled(PERFDATA_MET_ELAPSED_SEC,  PERFDATA_CTX_PKT_NET_SENDCHILD) || 
                     pdm->is_Enabled(PERFDATA_MET_ELAPSED_SEC, PERFDATA_CTX_PKT_NET_SENDPAR) ||
                     pdm->is_Enabled(PERFDATA_MET_ELAPSED_SEC, PERFDATA_CTX_PKT_FILTER_TO_SEND)) 
                {
                    pdm->add_PacketTimers( pkt );
                }
            }
        }
    }

 send_cleanup_return:
    _send_sync.Unlock();

    if( ! using_prealloc ) {
        free( buf );
        free( packet_sizes );
        delete[] ncbufs;
    }

    if( go_away ) {
        // exit send thread
        mrn_dbg( 5, mrn_printf(FLF, stderr, "I'm going away now!\n" ));
        tsd_t* tsd = (tsd_t*)XPlat::XPlat_TLSKey->GetUserData();
        if( NULL != tsd ) {
            delete tsd;
            if(XPlat::XPlat_TLSKey->SetUserData(NULL) != 0) {
                mrn_dbg(1, mrn_printf(FLF, stderr, "Thread 0x%lx failed to set"
                            " thread-specific user data to NULL.\n",
                            XPlat::Thread::GetId()));
            }
            if(XPlat::XPlat_TLSKey->DestroyData() != 0) {
                mrn_dbg(1, mrn_printf(FLF, stderr, "Thread 0x%lx failed to "
                            "destroy thread-specific data.\n",
                            XPlat::Thread::GetId()));
            }
        }
        XPlat::Thread::Exit(NULL);
    }    

    mrn_dbg_func_end();
    return rc;
}