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