* vim:expandtab:shiftwidth=8:tabstop=8:
*
* Copyright (c) 2002 Cray Inc.
+ * Copyright (c) 2003 Cluster File Systems, Inc.
*
- * This file is part of Portals, http://www.sf.net/projects/sandiaportals/
+ * This file is part of Lustre, http://www.lustre.org.
*
- * Portals is free software; you can redistribute it and/or
- * modify it under the terms of version 2.1 of the GNU Lesser General
- * Public License as published by the Free Software Foundation.
+ * Lustre is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
*
- * Portals is distributed in the hope that it will be useful,
+ * Lustre is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with Portals; if not, write to the Free Software
+ * You should have received a copy of the GNU General Public License
+ * along with Lustre; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
-#include <syscall.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <bridge.h>
#include <ipmap.h>
#include <connection.h>
+#include <pthread.h>
+#include <errno.h>
+#ifndef __CYGWIN__
+#include <syscall.h>
+#endif
/* Function: tcpnal_send
* Arguments: nal: pointer to my nal control block
*
* sends a packet to the peer, after insuring that a connection exists
*/
-#warning FIXME: "param 'type' is newly added, make use of it!!"
-int tcpnal_send(nal_cb_t *n,
- void *private,
- lib_msg_t *cookie,
- ptl_hdr_t *hdr,
- int type,
- ptl_nid_t nid,
- ptl_pid_t pid,
- unsigned int niov,
- struct iovec *iov,
- size_t len)
+ptl_err_t tcpnal_send(nal_cb_t *n,
+ void *private,
+ lib_msg_t *cookie,
+ ptl_hdr_t *hdr,
+ int type,
+ ptl_nid_t nid,
+ ptl_pid_t pid,
+ unsigned int niov,
+ struct iovec *iov,
+ size_t offset,
+ size_t len)
{
connection c;
bridge b=(bridge)n->nal_data;
- struct iovec tiov[2];
- int count = 1;
+ struct iovec tiov[257];
+ static pthread_mutex_t send_lock = PTHREAD_MUTEX_INITIALIZER;
+ ptl_err_t rc = PTL_OK;
+ int sysrc;
+ int total;
+ int ntiov;
+ int i;
if (!(c=force_tcp_connection((manager)b->lower,
PNAL_IP(nid,b),
- PNAL_PORT(nid,pid))))
- return(1);
+ PNAL_PORT(nid,pid),
+ b->local)))
+ return(PTL_FAIL);
-#if 0
/* TODO: these results should be checked. furthermore, provision
must be made for the SIGPIPE which is delivered when
writing on a tcp socket which has closed underneath
the application. there is a linux flag in the sendmsg
call which turns off the signally behaviour, but its
nonstandard */
- syscall(SYS_write, c->fd,hdr,sizeof(ptl_hdr_t));
- LASSERT (niov <= 1);
- if (len) syscall(SYS_write, c->fd,iov[0].iov_base,len);
-#else
- LASSERT (niov <= 1);
+
+ LASSERT (niov <= 256);
tiov[0].iov_base = hdr;
tiov[0].iov_len = sizeof(ptl_hdr_t);
+ ntiov = 1 + lib_extract_iov(256, &tiov[1], niov, iov, offset, len);
- if (len) {
- tiov[1].iov_base = iov[0].iov_base;
- tiov[1].iov_len = len;
- count++;
+ pthread_mutex_lock(&send_lock);
+#if 1
+ for (i = total = 0; i < ntiov; i++)
+ total += tiov[i].iov_len;
+
+ sysrc = syscall(SYS_writev, c->fd, tiov, ntiov);
+ if (sysrc != total) {
+ fprintf (stderr, "BAD SEND rc %d != %d, errno %d\n",
+ rc, total, errno);
+ rc = PTL_FAIL;
+ }
+#else
+ for (i = total = 0; i <= ntiov; i++) {
+ rc = send(c->fd, tiov[i].iov_base, tiov[i].iov_len, 0);
+
+ if (rc != tiov[i].iov_len) {
+ fprintf (stderr, "BAD SEND rc %d != %d, errno %d\n",
+ rc, tiov[i].iov_len, errno);
+ rc = PTL_FAIL;
+ break;
+ }
+ total += rc;
}
-
- syscall(SYS_writev, c->fd, tiov, count);
#endif
- lib_finalize(n, private, cookie);
-
- return(0);
+#if 0
+ fprintf (stderr, "sent %s total %d in %d frags\n",
+ hdr->type == PTL_MSG_ACK ? "ACK" :
+ hdr->type == PTL_MSG_PUT ? "PUT" :
+ hdr->type == PTL_MSG_GET ? "GET" :
+ hdr->type == PTL_MSG_REPLY ? "REPLY" :
+ hdr->type == PTL_MSG_HELLO ? "HELLO" : "UNKNOWN",
+ total, niov + 1);
+#endif
+ pthread_mutex_unlock(&send_lock);
+
+ if (rc == PTL_OK) {
+ /* NB the NAL only calls lib_finalize() if it returns PTL_OK
+ * from cb_send() */
+ lib_finalize(n, private, cookie, PTL_OK);
+ }
+
+ return(rc);
}
* blocking read of the requested data. must drain out the
* difference of mainpulated and requested lengths from the network
*/
-int tcpnal_recv(nal_cb_t *n,
- void *private,
- lib_msg_t *cookie,
- unsigned int niov,
- struct iovec *iov,
- ptl_size_t mlen,
- ptl_size_t rlen)
+ptl_err_t tcpnal_recv(nal_cb_t *n,
+ void *private,
+ lib_msg_t *cookie,
+ unsigned int niov,
+ struct iovec *iov,
+ size_t offset,
+ size_t mlen,
+ size_t rlen)
{
- if (mlen) {
- LASSERT (niov <= 1);
- read_connection(private,iov[0].iov_base,mlen);
- lib_finalize(n, private, cookie);
- }
+ struct iovec tiov[256];
+ int ntiov;
+ int i;
+
+ if (!niov)
+ goto finalize;
+
+ LASSERT(mlen);
+ LASSERT(rlen);
+ LASSERT(rlen >= mlen);
+
+ ntiov = lib_extract_iov(256, tiov, niov, iov, offset, mlen);
+
+ /* FIXME
+ * 1. Is this effecient enough? change to use readv() directly?
+ * 2. need check return from read_connection()
+ * - MeiJia
+ */
+ for (i = 0; i < ntiov; i++)
+ read_connection(private, tiov[i].iov_base, tiov[i].iov_len);
+
+finalize:
+ /* FIXME; we always assume success here... */
+ lib_finalize(n, private, cookie, PTL_OK);
if (mlen!=rlen){
char *trash=malloc(rlen-mlen);
free(trash);
}
- return(rlen);
+ return(PTL_OK);
}
*/
static int from_connection(void *a, void *d)
{
- connection c = d;
- bridge b=a;
- ptl_hdr_t hdr;
-
- if (read_connection(c, (unsigned char *)&hdr, sizeof(hdr))){
- lib_parse(b->nal_cb, &hdr, c);
- return(1);
- }
- return(0);
+ connection c = d;
+ bridge b = a;
+ ptl_hdr_t hdr;
+
+ if (read_connection(c, (unsigned char *)&hdr, sizeof(hdr))){
+ lib_parse(b->nal_cb, &hdr, c);
+ return(1);
+ }
+ return(0);
}