Author: suokko
Date: Thu Jun  5 00:40:07 2008
New Revision: 27002

URL: http://svn.gna.org/viewcvs/wesnoth?rev=27002&view=rev
Log:
* Implemented send_file using sendfile() system call

Modified:
    trunk/SConstruct
    trunk/changelog
    trunk/src/network_worker.cpp

Modified: trunk/SConstruct
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/SConstruct?rev=27002&r1=27001&r2=27002&view=diff
==============================================================================
--- trunk/SConstruct (original)
+++ trunk/SConstruct Thu Jun  5 00:40:07 2008
@@ -177,6 +177,8 @@
     if env['fribidi']:
         env['fribidi'] = conf.CheckLibWithHeader('fribidi', 
'fribidi/fribidi.h', 'C', 'fribidi_utf8_to_unicode(NULL,0,NULL);') or 
Warning("Can't find libfribidi, disabling freebidi support.")
 
+    env['sendfile'] = conf.CheckLibWithHeader('sendfile', 'sys/sendfile.h', 
'C', 'sendfile(0,0,0,0);') or Warning("Can't find sendfile, disabling sendfile 
support.")
+
     have_server_prereqs = conf.CheckSDL('SDL_net') or Warning("Server 
prerequisites are not met. wesnothd and campaignd cannot be built.")
 
     if env["python"]:
@@ -238,6 +240,9 @@
 
 if env['python']:
     env.Append(CPPDEFINES = "HAVE_PYTHON")
+
+if env['sendfile']:
+    env.Append(CPPDEFINES = "USE_SENDFILE")
 
 if sys.platform != "win32":
     if env['prefsdir']:

Modified: trunk/changelog
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/changelog?rev=27002&r1=27001&r2=27002&view=diff
==============================================================================
--- trunk/changelog (original)
+++ trunk/changelog Thu Jun  5 00:40:07 2008
@@ -90,6 +90,7 @@
    * Fixed null-pointer reference in network code
    * Made networking code check system buffer size and limit send length
    * Implemented send_file to reduce memory usage when sending files
+   * Implemented send_file using sendfile() system call 
    * Fixed tokenizer not to strip CR from quoted string becaue it would
      destroy images transfered over network
    * Added possibility to use per fight EV statistics proposed by maboul

Modified: trunk/src/network_worker.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/network_worker.cpp?rev=27002&r1=27001&r2=27002&view=diff
==============================================================================
--- trunk/src/network_worker.cpp (original)
+++ trunk/src/network_worker.cpp Thu Jun  5 00:40:07 2008
@@ -41,6 +41,9 @@
 
 #ifdef USE_SENDFILE
 #include <sys/sendfile.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#define HAVE_POLL_H
 #endif
 
 #include <boost/iostreams/filter/gzip.hpp>
@@ -304,7 +307,7 @@
 #ifdef __BEOS__
        int timeout = 15000;
 #endif
-       check_send_buffer_size(sock);
+//     check_send_buffer_size(sock);
        size_t upto = 0;
        size_t size = buf.size();
        if (in_size != -1)
@@ -326,12 +329,15 @@
                        // check if the socket is still locked
                        const threading::lock lock(*shard_mutexes[shard]);
                        if(sockets_locked[shard][sock] != SOCKET_LOCKED)
+                       {
                                return SOCKET_ERRORED;
-               }
-               send_len = minimum<int>(system_send_buffer_size,  
static_cast<int>(size - upto));
+                       }
+               }
+               send_len = static_cast<int>(size - upto);
                const int res = SDLNet_TCP_Send(sock, &buf[upto],send_len);
 
-               if( res == static_cast<int>(size - upto)) {
+
+               if( res == send_len) {
                        if (!raw_data_only)
                        {
                                const threading::lock lock(*stats_mutex);
@@ -339,11 +345,7 @@
                        }
                        return SOCKET_READY;
                }
-#if defined(EAGAIN) && !defined(__BEOS__) && !defined(_WIN32)
-               if(errno == EAGAIN)
-#elif defined(EWOULDBLOCK)
-               if(errno == EWOULDBLOCK)
-#endif
+       
                {
                        // update how far we are
                        upto += static_cast<size_t>(res);
@@ -360,6 +362,7 @@
                                poll_res = poll(&fd, 1, 15000);
                        } while(poll_res == -1 && errno == EINTR);
 
+                       
                        if(poll_res > 0)
                                continue;
 #elif defined(USE_SELECT) && !defined(__BEOS__)
@@ -399,36 +402,93 @@
        size_t upto = 0;
        int send_size = 0;
        size_t filesize = file_size(buf->config_error);
-
 #ifdef USE_SENDFILE
-       std::vector<char>& buffer;
+       std::vector<char> buffer;
        buffer.reserve(4);
        SDLNet_Write32(filesize,&buffer[0]);
+       int socket = reinterpret_cast<_TCPsocket*>(buf->sock)->channel;
+       int in_file = open(buf->config_error.c_str(),O_NOATIME | O_RDONLY);
+       int cock = 1;
+       int poll_res;
+       struct pollfd fd = {socket, POLLOUT, 0 };
+       setsockopt(socket, IPPROTO_TCP, TCP_CORK, &cock, sizeof(cock));;
+       do {
+               poll_res = poll(&fd, 1, 600000);
+       } while(poll_res == -1 && errno == EINTR);
+
+       SOCKET_STATE result = send_buffer(buf->sock, buffer, 4);
+       
+       
+       if (result != SOCKET_READY)
+       {
+               close(in_file);
+               cock = 0;
+               setsockopt(socket, IPPROTO_TCP, TCP_CORK, &cock, sizeof(cock));
+               return result;
+       }
+       result = SOCKET_READY;
 #else
        SDLNet_Write32(filesize,&buf->raw_buffer[0]);
        scoped_istream file_stream = istream_file(buf->config_error);
-       send_buffer(buf->sock, buf->raw_buffer, 4);
+       SOCKET_STATE result = send_buffer(buf->sock, buf->raw_buffer, 4);
+
+       if (result != SOCKET_READY)
+       {
+               return result;
+       }
 #endif
        while (true)
        {
 #ifdef USE_SENDFILE
+
+               do {
+                       poll_res = poll(&fd, 1, 600000);
+               } while(poll_res == -1 && errno == EINTR);
+
+               if (poll_res <= 0 )
+               {
+                       result = SOCKET_ERRORED;
+                       break;
+               }
+
+
+               int bytes = ::sendfile(socket, in_file, 0, filesize);
+
+               upto += bytes;
+
+
+               if (upto == filesize)
+               {
+                       buf->raw_buffer.push_back(0);
+                       result = send_buffer(buf->sock, buf->raw_buffer, 1);
+                       break;
+               }
 #else
                // read data
                file_stream->read(&buf->raw_buffer[0], buf->raw_buffer.size());
                send_size = file_stream->gcount();
                upto += send_size;
                // send data to socket
-               send_buffer(buf->sock, buf->raw_buffer, send_size);
+               result = send_buffer(buf->sock, buf->raw_buffer, send_size);
+               if (result != SOCKET_READY)
+               {
+                       break;
+               }
                if (upto == filesize)
                {
                        buf->raw_buffer[0] = 0;
-                       send_buffer(buf->sock, buf->raw_buffer, 1);
+                       result = send_buffer(buf->sock, buf->raw_buffer, 1);
                        break;
                }
 
 #endif
        }
-       return SOCKET_READY;
+#ifdef USE_SENDFILE
+       close(in_file);
+       cock = 0;
+       setsockopt(socket, IPPROTO_TCP, TCP_CORK, &cock, sizeof(cock));
+#endif
+       return result;
 }
 
 static SOCKET_STATE receive_buf(TCPsocket sock, std::vector<char>& buf)
@@ -577,7 +637,7 @@
                        if(!sent_buf->config_error.empty())
                        {
                                // We have file to send over net
-                               send_file(sent_buf);
+                               result = send_file(sent_buf);
                        } else {
                                if(sent_buf->raw_buffer.empty()) {
                                        const std::string &value = 
sent_buf->stream.str();
@@ -768,15 +828,17 @@
                // throw the error in parent thread
                std::string error = (*itor)->config_error;
                buffer* buf = *itor;
+               received_data_queue.erase(itor);
                if (gzipped)
                        *gzipped = buf->gzipped;
-               received_data_queue.erase(itor);
                delete buf;
                throw config::error(error);
        } else {
                cfg.swap((*itor)->config_buf);
                const TCPsocket res = (*itor)->sock;
                buffer* buf = *itor;
+               if (gzipped)
+                       *gzipped = buf->gzipped;
                received_data_queue.erase(itor);
                delete buf;
                return res;


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to