aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hiper/Makefile38
-rw-r--r--hiper/STATUS300
-rwxr-xr-xhiper/collecturls.pl34
-rw-r--r--hiper/hiper.c416
-rw-r--r--hiper/hipev.c410
-rw-r--r--hiper/shiper.c557
-rw-r--r--hiper/ulimiter.c101
7 files changed, 0 insertions, 1856 deletions
diff --git a/hiper/Makefile b/hiper/Makefile
deleted file mode 100644
index fea1655ae..000000000
--- a/hiper/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Build test apps for the Hiper project
-# During dev at least, we use a static libcurl.
-#
-
-LDFLAGS = -lcrypt -lidn -lssl -lcrypto -lz -lresolv -L../ares/.libs \
- -lcares
-LIBCURL = -L../lib/.libs/ -lcurl
-CFLAGS = -I../include -g
-
-all: shiper hiper hipev ulimiter
-
-hiper: hiper.o $(LIBCURL)
- $(CC) -o $@ $< $(LIBCURL) $(LDFLAGS)
-
-hiper.o: hiper.c
- $(CC) $(CFLAGS) -c $<
-
-hipev: hipev.o $(LIBCURL)
- $(CC) -o $@ $< $(LIBCURL) $(LDFLAGS) -levent
-
-hipev.o: hipev.c
- $(CC) $(CFLAGS) -c $<
-
-shiper: shiper.o $(LIBCURL)
- $(CC) -o $@ $< $(LIBCURL) $(LDFLAGS)
-
-shiper.o: shiper.c
- $(CC) $(CFLAGS) -c $<
-
-ulimiter: ulimiter.c
- $(CC) -o $@ $<
-
-clean:
- rm -f hiper.o hiper shiper shiper.o *~ ulimiter
-
-$(LIBCURL):
- (cd ../lib && make)
diff --git a/hiper/STATUS b/hiper/STATUS
deleted file mode 100644
index 918611b8f..000000000
--- a/hiper/STATUS
+++ /dev/null
@@ -1,300 +0,0 @@
-Date: January 5, 2006
-Author: Daniel Stenberg
-
- Status of project Hiper - high performance libcurl modifications
- ================================================================
-
-What is Hiper
-
- You won't find such a description in this document. See
- http://curl.haxx.se/libcurl/hiper/ for further details.
-
-Live Progress Info
-
- During my work, I've posted occational updates on the curl-library mailing
- list but more importantly done frequent updates of
- http://curl.haxx.se/libcurl/hiper/schedule.html
-
-Schedule
-
- I took time off my regular job during Decemember 2005 and the first week of
- January 2006 to work on hiper full-time.
-
-Step 1 - Measure the Existing Solution
-
- I started full-time work on project Hiper on December 1st 2005. I began by
- putting together a test application that used the existing API to allow me
- to properly and with accuracy measure execution and transfer speeds when
- doing a large amount of transfers.
-
- I soon discovered that it was impossible to do any sensible measurements by
- using live and actual URLs since the transfers were too unrelialble and
- uncontrolled. I then enhanced the current HTTP server in the curl test suite
- and made that support a large amount of transfers and some extra magic
- "commands" that would make the server either just sit "idle" or "stream"
- (continuously sending data in a never-ending stream). I then wrote up two
- files using the curl test suite file format and by acessing the properly
- formatted URLs on my localhost the HTTP server would either run "idle" or
- run "stream".
-
- Having this working, I patched libcurl to always only recv() a single byte
- off the network each time, just to make sure that the time spent on reading
- data is constant and never very long.
-
- I adjusted the test application (actually called 'hiper') to create Y idle
- transfers and Z stream transfers, had it run for N seconds and then quit and
- produce a summary on stdout. Now I got very solid and repeatable results. I
- started to run repeated tests and save the results when I ran into the
- dreaded 1024 socket maximum limit.
-
- One side of the problem is that the fd_set type only allows 1024 file
- descriptors (on my Linux), which I had to solve by simply making my own type
- with room for more connections and do ugly typecasts in the code. The other
- side of the problem is that user applications have a limit imposed by the
- system on the maximum amount of file descriptors it can have open and I had
- to work around that by writing a special tool that runs setuid root that
- increases the limit, downgrades to a normal user again and then run the
- command line of your choice. This second approach has to be used for both
- 'hiper' and the test HTTP server. (You need to build the HTTP server with
- CURL_SWS_FORK_ENABLED defined to have it do forks since it isn't desirable
- to do so when running the normal curl tests.)
-
- Now I could run my test program without problems. I decided to run the tests
- with 1 stream connection and a varying amount of idle ones. I did 1001,
- 2001, 3001, 5001 and 9001 connections and measured how long select() and
- curl_multi_perform() (including the curl_multi_fdset() call) would take in
- average, over a period of 20 seconds. I ran each test 5-6 times and I used
- the average time of all the runs.
-
- The times in number of microseconds:
-
- Connections multi_perform select
- 1001 3504 951
- 2001 7606 1988
- 3001 11045 2715
- 5001 16406 4024
- 9001 32147 8030
-
- Test system
- CPU: Athlon XP 2800
- RAM: 1 GB
- Linux: 2.6
- glibc: 2.3.5
- libcurl: 7.15.1
-
- The only reason I stopped at 9001 connections is that my test machine ran
- out of avaiable memory by then as I ran the test server on the same machine,
- and I didn't want to risk the test result accuracy by having it start using
- the swap during the tests.
-
- It means that at 9000 connections we spend 40ms for each socket action, even
- when only one socket ever have action.
-
- With these 32000 microseconds curl_multi_perform() takes for 9000
- connections, it loops 18000 laps which makes less than 2 microseconds per
- lap. (Of course counting time/laps is an oversimplification, but anyway.)
- Hopefully we should achieve less than 10 microseconds for each call to
- curl_multi_socket() for an active connection.
-
- The timing graph displayed on the libevent site (duplicated on the hiper
- project page) suggests that libevent is pretty much fixed at 50 microseconds
- (although I don't know what test box was used in their testing, we can
- compare the select()-times from my tests and see that they are at least
- resonably close).
-
- Summing up, the current ~40 ms spent at 9000 connections could then possibly
- be lowered to something around 60 us!
-
-Step 2 - Implement curl_multi_socket API
-
- Most of the design decisions and debates about this new API have already
- been held on the curl-library mailing list a long time ago so I had a basic
- idea on what approach to use. The main ideas of the new API are simply:
-
- 1 - The application can use whatever event system it likes as it gets info
- from libcurl about what file descriptors libcurl waits for what action
- on. (The previous API returns fd_sets which is very select()-centric).
-
- 2 - When the application discovers action on a single socket, it calls
- libcurl and informs that there was action on this particular socket and
- libcurl can then act on that socket/transfer only and not care about
- any other transfers. (The previous API always had to scan through all
- the existing transfers.)
-
- The idea is that curl_multi_socket() calls a given callback with information
- about what socket to wait for what action on, and the callback only gets
- called if the status of that socket has changed.
-
- In the API draft from before, we have a timeout argument on a per socket
- basis and we also allowed curl_multi_socket() to pass in an 'easy handle'
- instead of socket to allow libcurl to shortcut a lookup and work on the
- affected easy handle right away. Both these turned out to be bad ideas.
-
- The timeout argument was removed from the socket callback since after much
- thinking I came to the conclusion that we really don't want to handle
- timeouts on a per socket basis. We need it on a per transfer (easy handle)
- basis and thus we can't provide it in the callbacks in a nice way. Instead,
- we have to offer a curl_multi_timeout() that returns the largest amount of
- time we should wait before we call the "timeout action" of libcurl, to
- trigger the proper internal timeout action on the affected transfer. To get
- this to work, I added a struct to each easy handle in which we store an
- "expire time" (if any). The structs are then "splay sorted" so that we can
- add and remove times from the linked list and yet somewhat swiftly figure
- out 1 - how long time there is until the next timer expires and 2 - which
- timer (handle) should we take care of now. Of course, the upside of all this
- is that we get a curl_multi_timeout() that should also work with old-style
- applications that use curl_multi_perform().
-
- The easy handle argument was removed fom the curl_multi_socket() function
- because having it there would require the application to do a socket to easy
- handle conversion on its own. I find it very unlikely that applications
- would want to do that and since libcurl would need such a lookup on its own
- anyway since we didn't want to force applications to do that translation
- code (it would be optional), it seemed like an unnecessary option. I also
- realized that when we use underlying libraries such as c-ares (for DNS
- asynch resolving) there might in fact be more than one transfer waiting for
- action on the same socket and thus it makes the lookup even tricker and even
- less likely to ever get done by applications. Instead I created an internal
- "socket to easy handles" hash table that given a socket (file descriptor)
- returns a list of easy handles that waits for some action on that socket.
-
- To make libcurl be able to report plain sockets in the socket callback, I
- had to re-organize the internals of the curl_multi_fdset() etc so that the
- conversion from sockets to fd_sets for that function is only done in the
- last step before the data is returned. I also had to extend c-ares to get a
- function that can return plain sockets, as that library too returned only
- fd_sets and that is no longer good enough. The changes done to c-ares have
- been committed and are available in the c-ares CVS repository destined to be
- included in the upcoming c-ares 1.3.1 release.
-
- The 'shiper' tool is the test application I wrote that uses the new
- curl_multi_socket() in its current state. It seems to be working and it uses
- the API as it is documented and supposed to work. It is still using
- select(), because I needed that during development (like until I had the
- socket hash implemented etc) and because I haven't yet learned how to use
- libevent or similar.
-
- The hiper/shiper tools are very simple and initiates lots of connections and
- have them running for the test period and then kills them all.
-
- Since I wasn't done with the implementation until early January I haven't
- had time to run very many measurements and checks, but I have done a few
- runs with up to a few hundred connections (with a single active one). The
- curl_multi_socket() invoke then takes 3-6 microseconds in average (using the
- read-only-1-byte-at-a-time hack). If this number does increase a lot when we
- add connections, it certainly matches my in my opinion very ambitious goal.
- We are now below the 60 microseconds "per socket action" goal. It is
- destined to be somewhat higher the more connections we have since the hash
- table gets more populated and the splay tree will grow etc.
-
- Some tests at 7000 and 9000 connections showed that the socket hash lookup
- is somewhat of a bottle neck. Its current implementation may be a bit too
- limiting. It simply has a fixed-size array, and on each entry in the array
- it has a linked list with entries. So the hash only checks which list to
- scan through. The code I had used so for used a list with merely 7 slots (as
- that is what the DNS hash uses) but with 7000 connections that would make an
- average of 1000 nodes in each list to run through. I upped that to 97 slots
- (I believe a prime is suitable) and noticed a significant speed increase. I
- need to reconsider the hash implementation or use a rather large default
- value like this. At 9000 connections I was still below 10us per call.
-
-Status Right Now
-
- The curl_multi_socket() API is implemented according to how it is
- documented. The man pages for curl_multi_socket and curl_multi_timeout are
- both committed to CVS and are available online for easy browsing:
-
- http://curl.haxx.se/libcurl/c/curl_multi_socket.html
- http://curl.haxx.se/libcurl/c/curl_multi_timeout.html
-
- The hiper-5.patch I made available early morning January 5th, 2006 should
- apply fine on a recent CVS checkout (at the time of this writing curl 7.15.1
- is the latest public curl release but the hiper patch does not apply fine on
- that).
-
-What is Left for the curl_multi_socket API
-
- 1 - More measuring with more extreme number of connections
-
- 2 - More testing with actual URLs and complete from start to end transfers.
-
- I'm quite sure we don't set expire times all over in the code properly, so
- there is bound to be some timeout bugs left.
-
- What it really takes is for me to commit the code and to make an official
- release with it so that we get people "out there" to help out testing it.
-
-What is Left for project Hiper
-
- 1 - Add HTTP pipelining support
-
- 2 - Add a zero (or at least close to zero) copy interface
-
- Neither of these points have been planned or detailed exactly how they will
- be implemented.
-
-Roadmap Ahead
-
- I plan and hope to return to full-time hiper work later on this spring or
- possibly summer to continue where I pause now. Of course some spare time
- might also be spent until then to get us moving forward.
-
----------------------------------------------------------------------------
-
-April 11, 2006
-
- While sitting staring on my screen trying to write up a *nice* sample script
- using libevent, it strikes me that since libevent is pretty much based around
- its structs that you setup for each event/file descriptor, my application
- wants to figure out the correct struct that is associted with the file
- descriptor that libcurl provides in the socket callback.
-
- This feels like an operation most applications will need when using the
- multi_socket API, so it feels like I should better try to figure out a decent
- way to offer this basic functionality already in libcurl - and the fact that
- we already have the file descriptors in a hash we can probably just as well
- extend it somewhat and store some custom pointers as well.
-
- We need to offer the app a way to set a private pointer to be associated with
- the particular file descriptor, and then be able to provide that pointer on
- subsequent callback calls.
-
----------------------------------------------------------------------------
-
-April 20, 2006
-
- I was wrong when I previously claimed we could have more than one easy handle
- using the same socket. I've cleaned up and simplified code now to adjust to
- this.
-
----------------------------------------------------------------------------
-
-July 9, 2006
-
- TODO: We need to alter how we use c-ares for getting info about its sockets,
- as c-ares now provides a callback approach very similar to how libcurl is
- about to work.
-
- I'm adding a function called curl_multi_assign() that will set a private
- pointer added to the internal libcurl hash table for the particular socket
- passed in to this function:
-
- CURLMcode curl_multi_assign(CURLM *multi_handle,
- curl_socket_t sockfd,
- void *sockp);
-
- 'sockp' being a custom pointer set by the application to be associated with
- this socket. The socket has to be already existing and in-use by libcurl,
- like having already called the callback telling about its existance.
-
- The set hashp pointer will then be passed on to the callback in upcoming
- calls when this same socket is used (in the brand new 'socketp' argument).
-
----------------------------------------------------------------------------
-
-July 30, 2006
-
- Shockingly stupid (of me not having realized this before), but we really need
- to add a 'running_handles' argument to the curl_multi_socket() and
- curl_multi_socket_all() prototypes so that the caller can get to know when
- all the transfers are actually done!
diff --git a/hiper/collecturls.pl b/hiper/collecturls.pl
deleted file mode 100755
index 6a0da3686..000000000
--- a/hiper/collecturls.pl
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/perl
-
-# 1) http://randomurl.com/body.php
-# 2) http://random.yahoo.com/fast/ryl
-# 3) http://www.uroulette.com/visit
-
-# 1) very slow, responds with URL in body meta style:
-# <meta http-equiv="refresh" content="0; url=http://www.webmasterworld.com/forum85/735.htm">
-
-# 2) Responds with non-HTTP headers like:
-# Status: 301
-# Location: http://www.adaptive.net/
-
-# 3) ordinary 30X code and Location:
-
-my $url;
-map { $url .= " http://www.uroulette.com/visit"; } (1 .. 12);
-
-print $url."\n";
-
-my $count=0;
-
-open(DUMP, ">>dump");
-
-while(1) {
- my @getit = `curl -si $url`;
- for my $l (@getit) {
- if($l =~ /^Location: (.*)/) {
- print DUMP "$1\n";
- print STDERR "$count\r";
- $count++;
- }
- }
-}
diff --git a/hiper/hiper.c b/hiper/hiper.c
deleted file mode 100644
index 0cfa7bba0..000000000
--- a/hiper/hiper.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*****************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * $Id$
- *
- * Connect N connections. Z are idle, and X are active. Transfer as fast as
- * possible.
- *
- * Run for a specific amount of time (10 secs for now). Output detailed timing
- * information.
- *
- */
-
-/* The maximum number of simultanoues connections/transfers we support */
-#define NCONNECTIONS 50000
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/poll.h>
-
-#include <curl/curl.h>
-
-#define MICROSEC 1000000 /* number of microseconds in one second */
-
-/* The maximum time (in microseconds) we run the test */
-#define RUN_FOR_THIS_LONG (20*MICROSEC)
-
-/* Number of loops (seconds) we allow the total download amount and alive
- connections to remain the same until we bail out. Set this slightly higher
- when using asynch supported libcurl. */
-#define IDLE_TIME 10
-
-struct globalinfo {
- size_t dlcounter;
-};
-
-struct connection {
- CURL *e;
- int id; /* just a counter for easy browsing */
- char *url;
- size_t dlcounter;
- struct globalinfo *global;
- char error[CURL_ERROR_SIZE];
-};
-
-/* on port 8999 we run a modified (fork-) sws that supports pure idle and full
- stream mode */
-#define PORT "8999"
-
-#define HOST "192.168.1.13"
-
-#define URL_IDLE "http://" HOST ":" PORT "/1000"
-#define URL_ACTIVE "http://" HOST ":" PORT "/1001"
-
-static size_t
-writecallback(void *ptr, size_t size, size_t nmemb, void *data)
-{
- size_t realsize = size * nmemb;
- struct connection *c = (struct connection *)data;
-
- c->dlcounter += realsize;
- c->global->dlcounter += realsize;
-
-#if 0
- printf("%02d: %d, total %d\n",
- c->id, c->dlcounter, c->global->dlcounter);
-#endif
- return realsize;
-}
-
-/* return the diff between two timevals, in us */
-static long tvdiff(struct timeval *newer, struct timeval *older)
-{
- return (newer->tv_sec-older->tv_sec)*1000000+
- (newer->tv_usec-older->tv_usec);
-}
-
-
-/* store the start time of the program in this variable */
-static struct timeval timer;
-
-static void timer_start(void)
-{
- /* capture the time of the start moment */
- gettimeofday(&timer, NULL);
-}
-
-static struct timeval cont; /* at this moment we continued */
-
-int still_running; /* keep number of running handles */
-
-struct conncount {
- long time_us;
- long laps;
- long maxtime;
-};
-
-static struct timeval timerpause;
-static void timer_pause(void)
-{
- /* capture the time of the pause moment */
- gettimeofday(&timerpause, NULL);
-
- /* If we have a previous continue (all times except the first), we can now
- store the time for a whole "lap" */
- if(cont.tv_sec) {
- long lap;
-
- lap = tvdiff(&timerpause, &cont);
- }
-}
-
-static long paused; /* amount of us we have been pausing */
-
-static void timer_continue(void)
-{
- /* Capture the time of the restored operation moment, now calculate how long
- time we were paused and added that to the 'paused' variable.
- */
- gettimeofday(&cont, NULL);
-
- paused += tvdiff(&cont, &timerpause);
-}
-
-static long total; /* amount of us from start to stop */
-static void timer_total(void)
-{
- struct timeval stop;
- /* Capture the time of the operation stopped moment, now calculate how long
- time we were running and how much of that pausing.
- */
- gettimeofday(&stop, NULL);
-
- total = tvdiff(&stop, &timer);
-}
-
-struct globalinfo info;
-struct connection *conns;
-
-long selects;
-long selectsalive;
-long timeouts;
-
-long perform;
-long performalive;
-long performselect;
-long topselect;
-
-int num_total;
-int num_idle;
-int num_active;
-
-static void report(void)
-{
- int i;
- long active = total - paused;
- long numdl = 0;
-
- for(i=0; i < num_total; i++) {
- if(conns[i].dlcounter)
- numdl++;
- }
-
- printf("Summary from %d simultanoues transfers (%d active)\n",
- num_total, num_active);
- printf("%d out of %d connections provided data\n", numdl, num_total);
-
- printf("Total time: %ldus select(): %ldus curl_multi_perform(): %ldus\n",
- total, paused, active);
-
- printf("%d calls to curl_multi_perform() average %d alive "
- "Average time: %dus\n",
- perform, performalive/perform, active/perform);
-
- printf("%d calls to select(), average %d alive "
- "Average time: %dus\n",
- selects, selectsalive/selects,
- paused/selects);
- printf(" Average number of readable connections per select() return: %d\n",
- performselect/selects);
- printf(" Max number of readable connections for a single select() "
- "return: %d\n",
- topselect);
-
- printf("%ld select() timeouts\n", timeouts);
-
- printf("Downloaded %ld bytes in %ld bytes/sec, %ld usec/byte\n",
- info.dlcounter,
- info.dlcounter/(total/1000000),
- total/info.dlcounter);
-
-#if 0
- for(i=1; i< num_total; i++) {
- if(timecount[i].laps) {
- printf("Time %d connections, average %ld max %ld (%ld laps) "
- "average/conn: %ld\n",
- i,
- timecount[i].time_us/timecount[i].laps,
- timecount[i].maxtime,
- timecount[i].laps,
- (timecount[i].time_us/timecount[i].laps)/i );
- }
- }
-#endif
-}
-
-struct ourfdset {
- char fdbuffer[NCONNECTIONS/8];
-};
-#define FD2_ZERO(x) FD_ZERO((fd_set *)x)
-
-typedef struct ourfdset fd2_set;
-
-int main(int argc, char **argv)
-{
- CURLM *multi_handle;
- CURLMsg *msg;
- CURLcode code = CURLE_OK;
- CURLMcode mcode = CURLM_OK;
- int rc;
- int i;
-
- int prevalive=-1;
- int prevsamecounter=0;
- int prevtotal = -1;
- fd2_set fdsizecheck;
- int selectmaxamount;
-
- memset(&info, 0, sizeof(struct globalinfo));
-
- selectmaxamount = sizeof(fdsizecheck) * 8;
- printf("select() supports max %d connections\n", selectmaxamount);
-
- if(argc < 3) {
- printf("Usage: hiper [num idle] [num active]\n");
- return 1;
- }
-
- num_idle = atoi(argv[1]);
- num_active = atoi(argv[2]);
-
- num_total = num_idle + num_active;
-
- if(num_total > selectmaxamount) {
- printf("Requested more connections than supported!\n");
- return 4;
- }
-
- conns = calloc(num_total, sizeof(struct connection));
- if(!conns) {
- printf("Out of memory\n");
- return 3;
- }
-
- if(num_total >= NCONNECTIONS) {
- printf("Increase NCONNECTIONS!\n");
- return 2;
- }
-
- /* init the multi stack */
- multi_handle = curl_multi_init();
-
- for(i=0; i< num_total; i++) {
- CURL *e;
- char *nl;
-
- memset(&conns[i], 0, sizeof(struct connection));
-
- if(i < num_idle)
- conns[i].url = URL_IDLE;
- else
- conns[i].url = URL_ACTIVE;
-
-#if 0
- printf("%d: Add URL %s\n", i, conns[i].url);
-#endif
- e = curl_easy_init();
-
- if(!e) {
- printf("curl_easy_init() for handle %d failed, exiting!\n", i);
- return 2;
- }
-
- conns[i].e = e;
- conns[i].id = i;
- conns[i].global = &info;
-
- curl_easy_setopt(e, CURLOPT_URL, conns[i].url);
- curl_easy_setopt(e, CURLOPT_WRITEFUNCTION, writecallback);
- curl_easy_setopt(e, CURLOPT_WRITEDATA, &conns[i]);
-#if 1
- curl_easy_setopt(e, CURLOPT_VERBOSE, 1);
-#endif
- curl_easy_setopt(e, CURLOPT_ERRORBUFFER, conns[i].error);
- curl_easy_setopt(e, CURLOPT_PRIVATE, &conns[i]);
-
- /* add the easy to the multi */
- if(CURLM_OK != curl_multi_add_handle(multi_handle, e)) {
- printf("curl_multi_add_handle() returned error for %d\n", i);
- return 3;
- }
- }
-
- /* we start some action by calling perform right away */
- while(CURLM_CALL_MULTI_PERFORM ==
- curl_multi_perform(multi_handle, &still_running));
-
- printf("Starting timer, expects to run for %ldus\n", RUN_FOR_THIS_LONG);
- timer_start();
-
- while(still_running == num_total) {
- struct timeval timeout;
- int rc; /* select() return code */
- long timeout_ms;
-
- fd2_set fdread;
- fd2_set fdwrite;
- fd2_set fdexcep;
- int maxfd;
-
- FD2_ZERO(&fdread);
- FD2_ZERO(&fdwrite);
- FD2_ZERO(&fdexcep);
-
- curl_multi_timeout(multi_handle, &timeout_ms);
-
- /* set timeout to wait */
- timeout.tv_sec = timeout_ms/1000;
- timeout.tv_usec = (timeout_ms%1000)*1000;
-
- /* get file descriptors from the transfers */
- curl_multi_fdset(multi_handle,
- (fd_set *)&fdread,
- (fd_set *)&fdwrite,
- (fd_set *)&fdexcep, &maxfd);
-
- timer_pause();
- selects++;
- selectsalive += still_running;
- rc = select(maxfd+1,
- (fd_set *)&fdread,
- (fd_set *)&fdwrite,
- (fd_set *)&fdexcep, &timeout);
-
-#if 0
- /* Output this here to make it outside the timer */
- printf("Running: %d (%d bytes)\n", still_running, info.dlcounter);
-#endif
- timer_continue();
-
- switch(rc) {
- case -1:
- /* select error */
- break;
- case 0:
- timeouts++;
- default:
- /* timeout or readable/writable sockets */
- do {
- perform++;
- performalive += still_running;
- }
- while(CURLM_CALL_MULTI_PERFORM ==
- curl_multi_perform(multi_handle, &still_running));
-
- performselect += rc;
- if(rc > topselect)
- topselect = rc;
- break;
- }
-
- if(total > RUN_FOR_THIS_LONG) {
- printf("Stopped after %ldus\n", total);
- break;
- }
-
- if(prevalive != still_running) {
- printf("%d connections alive\n", still_running);
- }
- prevalive = still_running;
-
- timer_total(); /* calculate the total time spent so far */
- }
-
- if(still_running != num_total) {
- /* something made connections fail, extract the reason and tell */
- int msgs_left;
- struct connection *cptr;
- while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
- if (msg->msg == CURLMSG_DONE) {
- curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &cptr);
-
- printf("%d => (%d) %s", cptr->id, msg->data.result, cptr->error);
- }
- }
-
- }
-
- curl_multi_cleanup(multi_handle);
-
- /* cleanup all the easy handles */
- for(i=0; i< num_total; i++)
- curl_easy_cleanup(conns[i].e);
-
- report();
-
- return code;
-}
diff --git a/hiper/hipev.c b/hiper/hipev.c
deleted file mode 100644
index 6087f5b7d..000000000
--- a/hiper/hipev.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*****************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * $Id$
- *
- * Connect N connections. Z are idle, and X are active. Transfer as fast as
- * possible.
- *
- * Output detailed timing information.
- *
- * Uses libevent.
- *
- */
-
-/* The maximum number of simultanoues connections/transfers we support */
-#define NCONNECTIONS 50000
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/poll.h>
-
-#include <curl/curl.h>
-
-#include <event.h> /* for libevent */
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#define MICROSEC 1000000 /* number of microseconds in one second */
-
-/* The maximum time (in microseconds) we run the test */
-#define RUN_FOR_THIS_LONG (5*MICROSEC)
-
-/* Number of loops (seconds) we allow the total download amount and alive
- connections to remain the same until we bail out. Set this slightly higher
- when using asynch supported libcurl. */
-#define IDLE_TIME 10
-
-struct globalinfo {
- size_t dlcounter;
-};
-
-struct connection {
- CURL *e;
- int id; /* just a counter for easy browsing */
- char *url;
- size_t dlcounter;
- struct globalinfo *global;
- char error[CURL_ERROR_SIZE];
-};
-
-/* this is the struct associated with each file descriptor libcurl tells us
- it is dealing with */
-struct fdinfo {
- /* create a link list of fdinfo structs */
- struct fdinfo *next;
- struct fdinfo *prev;
- curl_socket_t sockfd;
- CURL *easy;
- int action; /* as set by libcurl */
- long timeout; /* as set by libcurl */
- struct event ev; /* */
- int evset; /* true if the 'ev' struct has been used in a event_set() call */
- CURLM *multi; /* pointer to the multi handle */
- int *running_handles; /* pointer to the running_handles counter */
-};
-
-static struct fdinfo *allsocks;
-
-static int running_handles;
-
-/* we have the timerevent global so that when the final socket-based event is
- done, we can remove the timerevent as well */
-static struct event timerevent;
-
-static void update_timeout(CURLM *multi_handle);
-
-/* called from libevent on action on a particular socket ("event") */
-static void eventcallback(int fd, short type, void *userp)
-{
- struct fdinfo *fdp = (struct fdinfo *)userp;
- CURLMcode rc;
-
- fprintf(stderr, "EVENT callback type %d\n", type);
-
- /* tell libcurl to deal with the transfer associated with this socket */
- do {
- rc = curl_multi_socket(fdp->multi, fd, fdp->running_handles);
- } while (rc == CURLM_CALL_MULTI_PERFORM);
-
- if(rc) {
- fprintf(stderr, "curl_multi_socket() returned %d\n", (int)rc);
- }
-
- fprintf(stderr, "running_handles: %d\n", *fdp->running_handles);
- if(!*fdp->running_handles) {
- /* last transfer is complete, kill pending timeout */
- fprintf(stderr, "last transfer done, kill timeout\n");
- if(evtimer_pending(&timerevent, NULL))
- evtimer_del(&timerevent);
- }
- else
- update_timeout(fdp->multi);
-}
-
-/* called from libevent when our timer event expires */
-static void timercallback(int fd, short type, void *userp)
-{
- (void)fd; /* not used for this */
- (void)type; /* ignored in here */
- CURLM *multi_handle = (CURLM *)userp;
- int running_handles;
- CURLMcode rc;
-
- fprintf(stderr, "EVENT timeout\n");
-
- /* tell libcurl to deal with the transfer associated with this socket */
- do {
- rc = curl_multi_socket(multi_handle, CURL_SOCKET_TIMEOUT,
- &running_handles);
- } while (rc == CURLM_CALL_MULTI_PERFORM);
-
- if(running_handles)
- /* Get the current timeout value from libcurl and set a new timeout */
- update_timeout(multi_handle);
-}
-
-static void remsock(struct fdinfo *f)
-{
- if(!f)
- /* did not find socket to remove! */
- return;
-
- if(f->evset)
- event_del(&f->ev);
-
- if(f->prev)
- f->prev->next = f->next;
- if(f->next)
- f->next->prev = f->prev;
- else
- /* this was the last entry */
- allsocks = NULL;
-}
-
-static void setsock(struct fdinfo *fdp, curl_socket_t s, CURL *easy,
- int action)
-{
- fdp->sockfd = s;
- fdp->action = action;
- fdp->easy = easy;
-
- if(fdp->evset)
- /* first remove the existing event if the old setup was used */
- event_del(&fdp->ev);
-
- /* now use and add the current socket setup to libevent. The EV_PERSIST is
- the key here as otherwise libevent will automatically remove the event
- when it occurs the first time */
- event_set(&fdp->ev, fdp->sockfd,
- (action&CURL_POLL_IN?EV_READ:0)|
- (action&CURL_POLL_OUT?EV_WRITE:0)| EV_PERSIST,
- eventcallback, fdp);
-
- fdp->evset=1;
-
- fprintf(stderr, "event_add() for fd %d\n", s);
-
- /* We don't use any socket-specific timeout but intead we use a single
- global one. This is (mostly) because libcurl doesn't expose any
- particular socket- based timeout value. */
- event_add(&fdp->ev, NULL);
-}
-
-static void addsock(curl_socket_t s, CURL *easy, int action, CURLM *multi)
-{
- struct fdinfo *fdp = calloc(sizeof(struct fdinfo), 1);
-
- fdp->multi = multi;
- fdp->running_handles = &running_handles;
- setsock(fdp, s, easy, action);
-
- if(allsocks) {
- fdp->next = allsocks;
- allsocks->prev = fdp;
-
- /* now set allsocks to point to the new struct */
- allsocks = fdp;
- }
- else
- allsocks = fdp;
-
- /* Set this association in libcurl */
- curl_multi_assign(multi, s, fdp);
-}
-
-/* on port 8999 we run a fork enabled sws that supports 'idle' and 'stream' */
-#define PORT "8999"
-
-#define HOST "127.0.0.1"
-
-#define URL_IDLE "http://" HOST ":" PORT "/1000"
-#if 1
-#define URL_ACTIVE "http://" HOST ":" PORT "/1001"
-#else
-#define URL_ACTIVE "http://localhost/"
-#endif
-
-static int socket_callback(CURL *easy, /* easy handle */
- curl_socket_t s, /* socket */
- int what, /* see above */
- void *cbp, /* callback pointer */
- void *socketp) /* socket pointer */
-{
- struct fdinfo *fdp = (struct fdinfo *)socketp;
- char *whatstr[]={
- "none",
- "IN",
- "OUT",
- "INOUT",
- "REMOVE"};
-
- fprintf(stderr, "socket %d easy %p what %s\n", s, easy,
- whatstr[what]);
-
- if(what == CURL_POLL_REMOVE)
- remsock(fdp);
- else {
- if(!fdp) {
- /* not previously known, add it and set association */
- printf("Add info for socket %d %s%s\n", s,
- what&CURL_POLL_IN?"READ":"",
- what&CURL_POLL_OUT?"WRITE":"" );
- addsock(s, easy, what, cbp);
- }
- else {
- /* we already know about it, just change action/timeout */
- printf("Changing info for socket %d from %d to %d\n",
- s, fdp->action, what);
- setsock(fdp, s, easy, what);
- }
- }
- return 0; /* return code meaning? */
-}
-
-
-static size_t
-writecallback(void *ptr, size_t size, size_t nmemb, void *data)
-{
- size_t realsize = size * nmemb;
- struct connection *c = (struct connection *)data;
- (void)ptr;
-
- c->dlcounter += realsize;
- c->global->dlcounter += realsize;
-
- printf("%02d: %d, total %d\n",
- c->id, c->dlcounter, c->global->dlcounter);
-
- return realsize;
-}
-
-struct globalinfo info;
-struct connection *conns;
-
-int num_total;
-int num_idle;
-int num_active;
-
-static void update_timeout(CURLM *multi_handle)
-{
- long timeout_ms;
- struct timeval timeout;
-
- /* Since we need a global timeout to occur after a given time of inactivity,
- we use a single timeout-event. Get the timeout value from libcurl, and
- update it after every call to libcurl. */
- curl_multi_timeout(multi_handle, &timeout_ms);
-
- /* convert ms to timeval */
- timeout.tv_sec = timeout_ms/1000;
- timeout.tv_usec = (timeout_ms%1000)*1000;
- evtimer_add(&timerevent, &timeout);
-}
-
-int main(int argc, char **argv)
-{
- CURLM *multi_handle;
- CURLMsg *msg;
- CURLcode code = CURLE_OK;
- int i;
-
- memset(&info, 0, sizeof(struct globalinfo));
-
- if(argc < 3) {
- printf("Usage: hiper-event [num idle] [num active]\n");
- return 1;
- }
-
- num_idle = atoi(argv[1]);
- num_active = atoi(argv[2]);
-
- num_total = num_idle + num_active;
-
- conns = calloc(num_total, sizeof(struct connection));
- if(!conns) {
- printf("Out of memory\n");
- return 3;
- }
-
- if(num_total >= NCONNECTIONS) {
- printf("Too many connections requested, increase NCONNECTIONS!\n");
- return 2;
- }
-
- event_init(); /* Initalize the event library */
-
- printf("About to do %d connections\n", num_total);
-
- /* init the multi stack */
- multi_handle = curl_multi_init();
-
- /* initialize the timeout event */
- evtimer_set(&timerevent, timercallback, multi_handle);
-
- for(i=0; i< num_total; i++) {
- CURL *e;
-
- memset(&conns[i], 0, sizeof(struct connection));
-
- if(i < num_idle)
- conns[i].url = URL_IDLE;
- else
- conns[i].url = URL_ACTIVE;
-
- e = curl_easy_init();
-
- if(!e) {
- printf("curl_easy_init() for handle %d failed, exiting!\n", i);
- return 2;
- }
-
- conns[i].e = e;
- conns[i].id = i;
- conns[i].global = &info;
-
- curl_easy_setopt(e, CURLOPT_URL, conns[i].url);
- curl_easy_setopt(e, CURLOPT_WRITEFUNCTION, writecallback);
- curl_easy_setopt(e, CURLOPT_WRITEDATA, &conns[i]);
- curl_easy_setopt(e, CURLOPT_VERBOSE, 0);
- curl_easy_setopt(e, CURLOPT_ERRORBUFFER, conns[i].error);
- curl_easy_setopt(e, CURLOPT_PRIVATE, &conns[i]);
-
- /* add the easy to the multi */
- if(CURLM_OK != curl_multi_add_handle(multi_handle, e)) {
- printf("curl_multi_add_handle() returned error for %d\n", i);
- return 3;
- }
- }
-
- curl_multi_setopt(multi_handle, CURLMOPT_SOCKETFUNCTION, socket_callback);
- curl_multi_setopt(multi_handle, CURLMOPT_SOCKETDATA, multi_handle);
-
- /* we start the action by calling *socket_all() */
- while(CURLM_CALL_MULTI_PERFORM == curl_multi_socket_all(multi_handle,
- &running_handles));
-
- /* update timeout */
- update_timeout(multi_handle);
-
- /* event_dispatch() runs the event main loop. It ends when no events are
- left to wait for. */
-
- event_dispatch();
-
- {
- /* something made connections fail, extract the reason and tell */
- int msgs_left;
- struct connection *cptr;
- while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
- if (msg->msg == CURLMSG_DONE) {
- curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &cptr);
-
- printf("%d => (%d) %s\n",
- cptr->id, msg->data.result, cptr->error);
- }
- }
- }
-
- curl_multi_cleanup(multi_handle);
-
- /* cleanup all the easy handles */
- for(i=0; i< num_total; i++)
- curl_easy_cleanup(conns[i].e);
-
- return code;
-}
diff --git a/hiper/shiper.c b/hiper/shiper.c
deleted file mode 100644
index 12c27c805..000000000
--- a/hiper/shiper.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*****************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * $Id$
- *
- * Connect N connections. Z are idle, and X are active. Transfer as fast as
- * possible.
- *
- * Run for a specific amount of time (10 secs for now). Output detailed timing
- * information.
- *
- * The same is hiper.c but instead using the new *socket() API instead of the
- * "old" *perform() call.
- *
- * Uses a select() approach but only for keeping the code simple and
- * stand-alone. See hipev.c for a libevent-based example.
- *
- */
-
-/* The maximum number of simultanoues connections/transfers we support */
-#define NCONNECTIONS 50000
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/poll.h>
-
-#include <curl/curl.h>
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#define MICROSEC 1000000 /* number of microseconds in one second */
-
-/* The maximum time (in microseconds) we run the test */
-#define RUN_FOR_THIS_LONG (5*MICROSEC)
-
-/* Number of loops (seconds) we allow the total download amount and alive
- connections to remain the same until we bail out. Set this slightly higher
- when using asynch supported libcurl. */
-#define IDLE_TIME 10
-
-struct ourfdset {
- /* __fds_bits is what the Linux glibc headers use when they declare the
- fd_set struct so by using this we can actually avoid the typecase for the
- FD_SET() macro usage but it would hardly be portable */
- char __fds_bits[NCONNECTIONS/8];
-};
-#define FD2_ZERO(x) memset(x, 0, sizeof(struct ourfdset))
-
-typedef struct ourfdset fd2_set;
-
-struct globalinfo {
- size_t dlcounter;
-};
-
-struct connection {
- CURL *e;
- int id; /* just a counter for easy browsing */
- char *url;
- size_t dlcounter;
- struct globalinfo *global;
- char error[CURL_ERROR_SIZE];
-};
-
-struct fdinfo {
- /* create a link list of fdinfo structs */
- struct fdinfo *next;
- struct fdinfo *prev;
- curl_socket_t sockfd;
- CURL *easy;
- int action; /* as set by libcurl */
- long timeout; /* as set by libcurl */
-};
-
-static struct fdinfo *allsocks;
-
-static struct fdinfo *findsock(curl_socket_t s)
-{
- /* return the struct for the given socket */
- struct fdinfo *fdp = allsocks;
-
- while(fdp) {
- if(fdp->sockfd == s)
- break;
- fdp = fdp->next;
- }
- return fdp; /* a struct pointer or NULL */
-}
-
-static void remsock(curl_socket_t s)
-{
- struct fdinfo *fdp = allsocks;
-
- while(fdp) {
- if(fdp->sockfd == s)
- break;
- fdp = fdp->next;
- }
- if(!fdp)
- /* did not find socket to remove! */
- return;
-
- if(fdp->prev)
- fdp->prev->next = fdp->next;
- if(fdp->next)
- fdp->next->prev = fdp->prev;
- else
- /* this was the last entry */
- allsocks = NULL;
-}
-
-static void setsock(struct fdinfo *fdp, curl_socket_t s, CURL *easy,
- int action)
-{
- fdp->sockfd = s;
- fdp->action = action;
- fdp->easy = easy;
-}
-
-static void addsock(curl_socket_t s, CURL *easy, int action)
-{
- struct fdinfo *fdp = calloc(sizeof(struct fdinfo), 1);
-
- setsock(fdp, s, easy, action);
-
- if(allsocks) {
- fdp->next = allsocks;
- allsocks->prev = fdp;
-
- /* now set allsocks to point to the new struct */
- allsocks = fdp;
- }
- else
- allsocks = fdp;
-}
-
-static void fdinfo2fdset(fd2_set *fdread, fd2_set *fdwrite, int *maxfd)
-{
- struct fdinfo *fdp = allsocks;
- int writable=0;
-
- FD2_ZERO(fdread);
- FD2_ZERO(fdwrite);
-
- *maxfd = 0;
-
-#if 0
- printf("Wait for: ");
-#endif
-
- while(fdp) {
- if(fdp->action & CURL_POLL_IN) {
- FD_SET(fdp->sockfd, (fd_set *)fdread);
- }
- if(fdp->action & CURL_POLL_OUT) {
- FD_SET(fdp->sockfd, (fd_set *)fdwrite);
- writable++;
- }
-
-#if 0
- printf("%d (%s%s) ",
- fdp->sockfd,
- (fdp->action & CURL_POLL_IN)?"r":"",
- (fdp->action & CURL_POLL_OUT)?"w":"");
-#endif
-
- if(fdp->sockfd > *maxfd)
- *maxfd = fdp->sockfd;
-
- fdp = fdp->next;
- }
-#if 0
- if(writable)
- printf("Check for %d writable sockets\n", writable);
-#endif
-}
-
-/* on port 8999 we run a fork enabled sws that supports 'idle' and 'stream' */
-#define PORT "8999"
-
-#define HOST "192.168.1.13"
-
-#define URL_IDLE "http://" HOST ":" PORT "/1000"
-#define URL_ACTIVE "http://" HOST ":" PORT "/1001"
-
-
-static int socket_callback(CURL *easy, /* easy handle */
- curl_socket_t s, /* socket */
- int what, /* see above */
- void *userp) /* "private" pointer */
-{
- struct fdinfo *fdp;
- printf("socket %d easy %p what %d\n", s, easy, what);
-
- if(what == CURL_POLL_REMOVE)
- remsock(s);
- else {
- fdp = findsock(s);
-
- if(!fdp) {
- addsock(s, easy, what);
- }
- else {
- /* we already know about it, just change action/timeout */
- printf("Changing info for socket %d from %d to %d\n",
- s, fdp->action, what);
- setsock(fdp, s, easy, what);
- }
- }
- return 0; /* return code meaning? */
-}
-
-
-static size_t
-writecallback(void *ptr, size_t size, size_t nmemb, void *data)
-{
- size_t realsize = size * nmemb;
- struct connection *c = (struct connection *)data;
-
- c->dlcounter += realsize;
- c->global->dlcounter += realsize;
-
-#if 0
- printf("%02d: %d, total %d\n",
- c->id, c->dlcounter, c->global->dlcounter);
-#endif
- return realsize;
-}
-
-/* return the diff between two timevals, in us */
-static long tvdiff(struct timeval *newer, struct timeval *older)
-{
- return (newer->tv_sec-older->tv_sec)*1000000+
- (newer->tv_usec-older->tv_usec);
-}
-
-
-/* store the start time of the program in this variable */
-static struct timeval timer;
-
-static void timer_start(void)
-{
- /* capture the time of the start moment */
- gettimeofday(&timer, NULL);
-}
-
-static struct timeval cont; /* at this moment we continued */
-
-int still_running; /* keep number of running handles */
-
-struct conncount {
- long time_us;
- long laps;
- long maxtime;
-};
-
-static struct timeval timerpause;
-static void timer_pause(void)
-{
- /* capture the time of the pause moment */
- gettimeofday(&timerpause, NULL);
-
- /* If we have a previous continue (all times except the first), we can now
- store the time for a whole "lap" */
- if(cont.tv_sec) {
- long lap;
-
- lap = tvdiff(&timerpause, &cont);
- }
-}
-
-static long paused; /* amount of us we have been pausing */
-
-static void timer_continue(void)
-{
- /* Capture the time of the restored operation moment, now calculate how long
- time we were paused and added that to the 'paused' variable.
- */
- gettimeofday(&cont, NULL);
-
- paused += tvdiff(&cont, &timerpause);
-}
-
-static long total; /* amount of us from start to stop */
-static void timer_total(void)
-{
- struct timeval stop;
- /* Capture the time of the operation stopped moment, now calculate how long
- time we were running and how much of that pausing.
- */
- gettimeofday(&stop, NULL);
-
- total = tvdiff(&stop, &timer);
-}
-
-struct globalinfo info;
-struct connection *conns;
-
-long selects;
-long timeouts;
-
-long multi_socket;
-long performalive;
-long performselect;
-long topselect;
-
-int num_total;
-int num_idle;
-int num_active;
-
-static void report(void)
-{
- int i;
- long active = total - paused;
- long numdl = 0;
-
- for(i=0; i < num_total; i++) {
- if(conns[i].dlcounter)
- numdl++;
- }
-
- printf("Summary from %d simultanoues transfers (%d active)\n",
- num_total, num_active);
- printf("%d out of %d connections provided data\n", numdl, num_total);
-
- printf("Total time: %ldus paused: %ldus curl_multi_socket(): %ldus\n",
- total, paused, active);
-
- printf("%d calls to select() "
- "Average time: %dus\n",
- selects, paused/selects);
- printf(" Average number of readable connections per select() return: %d\n",
- performselect/selects);
-
- printf(" Max number of readable connections for a single select() "
- "return: %d\n",
- topselect);
-
- printf("%ld calls to multi_socket(), "
- "Average time: %ldus\n",
- multi_socket, active/multi_socket);
-
- printf("%ld select() timeouts\n", timeouts);
-
- printf("Downloaded %ld bytes in %ld bytes/sec, %ld usec/byte\n",
- info.dlcounter,
- info.dlcounter/(total/1000000),
- total/info.dlcounter);
-
-}
-
-int main(int argc, char **argv)
-{
- CURLM *multi_handle;
- CURLMsg *msg;
- CURLcode code = CURLE_OK;
- CURLMcode mcode = CURLM_OK;
- int rc;
- int i;
- fd2_set fdsizecheck;
- int selectmaxamount;
- struct fdinfo *fdp;
- char act;
- int running_handles;
-
- memset(&info, 0, sizeof(struct globalinfo));
-
- selectmaxamount = sizeof(fdsizecheck) * 8;
- printf("select() supports max %d connections\n", selectmaxamount);
-
- if(argc < 3) {
- printf("Usage: hiper [num idle] [num active]\n");
- return 1;
- }
-
- num_idle = atoi(argv[1]);
- num_active = atoi(argv[2]);
-
- num_total = num_idle + num_active;
-
- if(num_total > selectmaxamount) {
- printf("Requested more connections than supported!\n");
- return 4;
- }
-
- conns = calloc(num_total, sizeof(struct connection));
- if(!conns) {
- printf("Out of memory\n");
- return 3;
- }
-
- if(num_total >= NCONNECTIONS) {
- printf("Too many connections requested, increase NCONNECTIONS!\n");
- return 2;
- }
-
- printf("About to do %d connections\n", num_total);
-
- /* init the multi stack */
- multi_handle = curl_multi_init();
-
- for(i=0; i< num_total; i++) {
- CURL *e;
- char *nl;
-
- memset(&conns[i], 0, sizeof(struct connection));
-
- if(i < num_idle)
- conns[i].url = URL_IDLE;
- else
- conns[i].url = URL_ACTIVE;
-
- e = curl_easy_init();
-
- if(!e) {
- printf("curl_easy_init() for handle %d failed, exiting!\n", i);
- return 2;
- }
-
- conns[i].e = e;
- conns[i].id = i;
- conns[i].global = &info;
-
- curl_easy_setopt(e, CURLOPT_URL, conns[i].url);
- curl_easy_setopt(e, CURLOPT_WRITEFUNCTION, writecallback);
- curl_easy_setopt(e, CURLOPT_WRITEDATA, &conns[i]);
- curl_easy_setopt(e, CURLOPT_VERBOSE, 0);
- curl_easy_setopt(e, CURLOPT_ERRORBUFFER, conns[i].error);
- curl_easy_setopt(e, CURLOPT_PRIVATE, &conns[i]);
-
- /* add the easy to the multi */
- if(CURLM_OK != curl_multi_add_handle(multi_handle, e)) {
- printf("curl_multi_add_handle() returned error for %d\n", i);
- return 3;
- }
- }
-
- curl_multi_setopt(multi_handle, CURLMOPT_SOCKETFUNCTION, socket_callback);
- curl_multi_setopt(multi_handle, CURLMOPT_SOCKETDATA, NULL);
-
- /* we start the action by calling *socket() right away */
- while(CURLM_CALL_MULTI_PERFORM == curl_multi_socket_all(multi_handle,
- &running_handles));
-
- printf("Starting timer, expects to run for %ldus\n", RUN_FOR_THIS_LONG);
- timer_start();
- timer_pause();
-
- while(1) {
- struct timeval timeout;
- int rc; /* select() return code */
- long timeout_ms;
-
- fd2_set fdread;
- fd2_set fdwrite;
- int maxfd;
-
- curl_multi_timeout(multi_handle, &timeout_ms);
-
- /* set timeout to wait */
- timeout.tv_sec = timeout_ms/1000;
- timeout.tv_usec = (timeout_ms%1000)*1000;
-
- /* convert file descriptors from the transfers to fd_sets */
- fdinfo2fdset(&fdread, &fdwrite, &maxfd);
-
- selects++;
- rc = select(maxfd+1,
- (fd_set *)&fdread,
- (fd_set *)&fdwrite,
- NULL, &timeout);
- switch(rc) {
- case -1:
- /* select error */
- break;
- case 0:
- timeouts++;
- curl_multi_socket(multi_handle, CURL_SOCKET_TIMEOUT, &running_handles);
- break;
-
- default:
- /* timeout or readable/writable sockets */
-
- for(i=0, fdp = allsocks; fdp; fdp = fdp->next) {
- act = 0;
- if((fdp->action & CURL_POLL_IN) &&
- FD_ISSET(fdp->sockfd, &fdread)) {
- act |= CURL_POLL_IN;
- i++;
- }
- if((fdp->action & CURL_POLL_OUT) &&
- FD_ISSET(fdp->sockfd, &fdwrite)) {
- act |= CURL_POLL_OUT;
- i++;
- }
-
- if(act) {
- multi_socket++;
- timer_continue();
- if(act & CURL_POLL_OUT)
- act--;
- curl_multi_socket(multi_handle, fdp->sockfd, &running_handles);
- timer_pause();
- }
- }
-
- performselect += rc;
- if(rc > topselect)
- topselect = rc;
- break;
- }
-
- timer_total(); /* calculate the total time spent so far */
-
- if(total > RUN_FOR_THIS_LONG) {
- printf("Stopped after %ldus\n", total);
- break;
- }
- }
-
- if(still_running != num_total) {
- /* something made connections fail, extract the reason and tell */
- int msgs_left;
- struct connection *cptr;
- while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
- if (msg->msg == CURLMSG_DONE) {
- curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &cptr);
-
- printf("%d => (%d) %s", cptr->id, msg->data.result, cptr->error);
- }
- }
-
- }
-
- curl_multi_cleanup(multi_handle);
-
- /* cleanup all the easy handles */
- for(i=0; i< num_total; i++)
- curl_easy_cleanup(conns[i].e);
-
- report();
-
- return code;
-}
diff --git a/hiper/ulimiter.c b/hiper/ulimiter.c
deleted file mode 100644
index cb2273279..000000000
--- a/hiper/ulimiter.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*****************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * $Id$
- *
- * Little tool to raise the amount of maximum file descriptor and then run the
- * given command line (using the hard-coded uid/gid).
- *
- */
-
-#include <stdio.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h> /* for errno translation */
-
-/* ulimiter
- *
- * Source code inspiration from:
- * http://www.cs.wisc.edu/condor/condorg/linux_scalability.html
- */
-
-#define UID 1000 /* the user who must run this */
-
-#define GID 1000 /* group id to run the program as */
-
-/* Number of open files to increase to */
-#define NEW_MAX 10000
-
-int main(int argc, char *argv[])
-{
- int ret;
- struct rlimit rl;
- char *brgv[20];
- int brgc=argc-1;
- int i;
-
- for(i=1; i< argc; i++)
- brgv[i-1]=argv[i];
- brgv[i-1]=NULL; /* terminate the list */
-
- if(getuid() != UID) {
- fprintf(stderr, "Only uid %d is allowed to run this\n", UID);
- return 1;
- }
-
- ret = getrlimit(RLIMIT_NOFILE, &rl);
- if(ret != 0) {
- fprintf(stderr, "Unable to read open file limit.\n"
- "(getrlimit(RLIMIT_NOFILE, &rl) failed)\n"
- "(%d, %s)", errno, strerror(errno));
- return 1;
- }
-
- fprintf(stderr, "Limit was %d (max %d), setting to %d\n",
- rl.rlim_cur, rl.rlim_max, NEW_MAX);
-
- rl.rlim_cur = rl.rlim_max = NEW_MAX;
- ret = setrlimit(RLIMIT_NOFILE, &rl);
- if(ret != 0) {
- fprintf(stderr, "Unable to set open file limit.\n"
- "(setrlimit(RLIMIT_NOFILE, &rl) failed)\n"
- "(%d, %s)", errno, strerror(errno));
- return 1;
- }
-
- ret = getrlimit(RLIMIT_NOFILE, &rl);
- if(ret != 0) {
- fprintf(stderr, "Unable to read new open file limit.\n"
- "(getrlimit(RLIMIT_NOFILE, &rl) failed)\n"
- "(%d, %s)", errno, strerror(errno));
- return 1;
- }
- if(rl.rlim_cur < NEW_MAX) {
- fprintf(stderr, "Failed to set new open file limit.\n"
- "Limit is %d, expected %d\n",
- rl.rlim_cur, NEW_MAX);
- return 1;
- }
-
- if(setgid(GID) != 0) {
- fprintf(stderr, "setgid failed (%d, %s)\n", errno, strerror(errno));
- return 1;
- }
- if(setuid(UID) != 0) {
- fprintf(stderr, "setuid failed (%d, %s)\n", errno, strerror(errno));
- return 1;
- }
-
- ret = execv(brgv[0], brgv);
-
- fprintf(stderr, "execl returned, failure\n"
- "returned %d, errno is %d (%s)\n",
- ret, errno, strerror(errno));
- return 1;
-}