176404edcSAsim Jamshed #include <stdio.h>
276404edcSAsim Jamshed #include <stdlib.h>
376404edcSAsim Jamshed #include <string.h>
476404edcSAsim Jamshed #include <unistd.h>
576404edcSAsim Jamshed #include <stdint.h>
676404edcSAsim Jamshed #include <time.h>
776404edcSAsim Jamshed #include <sys/time.h>
876404edcSAsim Jamshed #include <sys/types.h>
976404edcSAsim Jamshed #include <sys/stat.h>
1076404edcSAsim Jamshed #include <fcntl.h>
1176404edcSAsim Jamshed #include <pthread.h>
1276404edcSAsim Jamshed #include <signal.h>
1376404edcSAsim Jamshed #include <sys/socket.h>
1476404edcSAsim Jamshed #include <netinet/in.h>
1576404edcSAsim Jamshed #include <arpa/inet.h>
1676404edcSAsim Jamshed #include <sys/queue.h>
1776404edcSAsim Jamshed #include <assert.h>
1876404edcSAsim Jamshed
1976404edcSAsim Jamshed #include <mos_api.h>
2076404edcSAsim Jamshed #include "cpu.h"
2176404edcSAsim Jamshed #include "rss.h"
2276404edcSAsim Jamshed #include "http_parsing.h"
2376404edcSAsim Jamshed #include "debug.h"
2476404edcSAsim Jamshed #include "applib.h"
2576404edcSAsim Jamshed
2676404edcSAsim Jamshed #define CONFIG_FILE "config/epwget.conf"
2776404edcSAsim Jamshed static struct conf_var g_conf[] = {
2876404edcSAsim Jamshed { "url", {0} },
2976404edcSAsim Jamshed { "total_flows", {0} },
3076404edcSAsim Jamshed { "core_limit", {0} },
3176404edcSAsim Jamshed { "total_concurrency", {0} },
3276404edcSAsim Jamshed { "dest_port", {0} },
33*9120200aSAsim Jamshed { "keep_alive", {0} },
3476404edcSAsim Jamshed };
3576404edcSAsim Jamshed #define NUM_CONF_VAR (sizeof(g_conf) / sizeof(struct conf_var))
3676404edcSAsim Jamshed
3776404edcSAsim Jamshed #define PORT_NUM 80
3876404edcSAsim Jamshed //#define PORT_NUM 3333
3976404edcSAsim Jamshed
4076404edcSAsim Jamshed #define MAX_URL_LEN 128
4176404edcSAsim Jamshed #define MAX_FILE_LEN 128
4276404edcSAsim Jamshed #define HTTP_HEADER_LEN 1024
4376404edcSAsim Jamshed
4476404edcSAsim Jamshed #define IP_RANGE 1
4576404edcSAsim Jamshed #define MAX_IP_STR_LEN 16
4676404edcSAsim Jamshed
4776404edcSAsim Jamshed #define BUF_SIZE (8*1024)
4876404edcSAsim Jamshed
4976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
5076404edcSAsim Jamshed struct mtcp_conf g_mcfg;
5176404edcSAsim Jamshed static pthread_t mtcp_thread[MAX_CPUS];
5276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
5376404edcSAsim Jamshed static mctx_t g_mctx[MAX_CPUS];
5476404edcSAsim Jamshed static int done[MAX_CPUS];
5576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
5676404edcSAsim Jamshed static int num_cores;
5776404edcSAsim Jamshed static int core_limit;
5876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
5976404edcSAsim Jamshed static int fio = FALSE;
6076404edcSAsim Jamshed static char outfile[MAX_FILE_LEN + 1];
6176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
6276404edcSAsim Jamshed static char host[MAX_IP_STR_LEN + 1];
6376404edcSAsim Jamshed static char path[MAX_URL_LEN + 1];
6476404edcSAsim Jamshed static in_addr_t daddr;
6576404edcSAsim Jamshed static in_port_t dport;
6676404edcSAsim Jamshed static in_addr_t saddr;
6776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
6876404edcSAsim Jamshed static int total_flows;
6976404edcSAsim Jamshed static int flows[MAX_CPUS];
7076404edcSAsim Jamshed static int flowcnt = 0;
7176404edcSAsim Jamshed static int concurrency;
7276404edcSAsim Jamshed static int max_fds;
7376404edcSAsim Jamshed static uint16_t dest_port;
74*9120200aSAsim Jamshed static int keep_alive = FALSE;
7576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
7676404edcSAsim Jamshed struct wget_stat
7776404edcSAsim Jamshed {
7876404edcSAsim Jamshed uint64_t waits;
7976404edcSAsim Jamshed uint64_t events;
8076404edcSAsim Jamshed uint64_t connects;
8176404edcSAsim Jamshed uint64_t reads;
8276404edcSAsim Jamshed uint64_t writes;
8376404edcSAsim Jamshed uint64_t completes;
8476404edcSAsim Jamshed
8576404edcSAsim Jamshed uint64_t errors;
8676404edcSAsim Jamshed uint64_t timedout;
8776404edcSAsim Jamshed
8876404edcSAsim Jamshed uint64_t sum_resp_time;
8976404edcSAsim Jamshed uint64_t max_resp_time;
9076404edcSAsim Jamshed };
9176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
9276404edcSAsim Jamshed struct thread_context
9376404edcSAsim Jamshed {
9476404edcSAsim Jamshed int core;
9576404edcSAsim Jamshed
9676404edcSAsim Jamshed mctx_t mctx;
9776404edcSAsim Jamshed int ep;
9876404edcSAsim Jamshed struct wget_vars *wvars;
9976404edcSAsim Jamshed
10076404edcSAsim Jamshed int target;
10176404edcSAsim Jamshed int started;
10276404edcSAsim Jamshed int errors;
10376404edcSAsim Jamshed int incompletes;
10476404edcSAsim Jamshed int done;
10576404edcSAsim Jamshed int pending;
10676404edcSAsim Jamshed
10776404edcSAsim Jamshed int maxevents;
10876404edcSAsim Jamshed struct mtcp_epoll_event *events;
10976404edcSAsim Jamshed
11076404edcSAsim Jamshed struct wget_stat stat;
11176404edcSAsim Jamshed };
11276404edcSAsim Jamshed typedef struct thread_context* thread_context_t;
11376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
11476404edcSAsim Jamshed struct wget_vars
11576404edcSAsim Jamshed {
11676404edcSAsim Jamshed int request_sent;
11776404edcSAsim Jamshed
11876404edcSAsim Jamshed char response[HTTP_HEADER_LEN];
11976404edcSAsim Jamshed int resp_len;
12076404edcSAsim Jamshed int headerset;
12176404edcSAsim Jamshed uint32_t header_len;
12276404edcSAsim Jamshed uint64_t file_len;
12376404edcSAsim Jamshed uint64_t recv;
12476404edcSAsim Jamshed uint64_t write;
12576404edcSAsim Jamshed
12676404edcSAsim Jamshed struct timeval t_start;
12776404edcSAsim Jamshed struct timeval t_end;
12876404edcSAsim Jamshed
12976404edcSAsim Jamshed int fd;
13076404edcSAsim Jamshed };
13176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1321c9bc629SAsim Jamshed static struct thread_context *g_ctx[MAX_CPUS] = {0};
1331c9bc629SAsim Jamshed static struct wget_stat *g_stat[MAX_CPUS] = {0};
13476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
13576404edcSAsim Jamshed static thread_context_t
CreateContext(mctx_t mctx)13676404edcSAsim Jamshed CreateContext(mctx_t mctx)
13776404edcSAsim Jamshed {
13876404edcSAsim Jamshed thread_context_t ctx;
13976404edcSAsim Jamshed
14076404edcSAsim Jamshed ctx = (thread_context_t)calloc(1, sizeof(struct thread_context));
14176404edcSAsim Jamshed if (!ctx) {
14276404edcSAsim Jamshed perror("malloc");
14376404edcSAsim Jamshed TRACE_ERROR("Failed to allocate memory for thread context.\n");
14476404edcSAsim Jamshed return NULL;
14576404edcSAsim Jamshed }
14676404edcSAsim Jamshed
14776404edcSAsim Jamshed ctx->mctx = mctx;
14876404edcSAsim Jamshed ctx->core = mctx->cpu;
14976404edcSAsim Jamshed
15076404edcSAsim Jamshed g_mctx[ctx->core] = mctx;
15176404edcSAsim Jamshed
15276404edcSAsim Jamshed return ctx;
15376404edcSAsim Jamshed }
15476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
15576404edcSAsim Jamshed static void
DestroyContext(thread_context_t ctx)15676404edcSAsim Jamshed DestroyContext(thread_context_t ctx)
15776404edcSAsim Jamshed {
1581c9bc629SAsim Jamshed g_stat[ctx->core] = NULL;
15976404edcSAsim Jamshed free(ctx);
16076404edcSAsim Jamshed }
16176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
16276404edcSAsim Jamshed static inline int
CreateConnection(thread_context_t ctx)16376404edcSAsim Jamshed CreateConnection(thread_context_t ctx)
16476404edcSAsim Jamshed {
16576404edcSAsim Jamshed mctx_t mctx = ctx->mctx;
16676404edcSAsim Jamshed struct mtcp_epoll_event ev;
16776404edcSAsim Jamshed struct sockaddr_in addr;
16876404edcSAsim Jamshed int sockid;
16976404edcSAsim Jamshed int ret;
17076404edcSAsim Jamshed
17176404edcSAsim Jamshed assert(mctx);
17276404edcSAsim Jamshed
17376404edcSAsim Jamshed errno = 0;
17476404edcSAsim Jamshed sockid = mtcp_socket(mctx, AF_INET, SOCK_STREAM, 0);
17576404edcSAsim Jamshed if (sockid < 0) {
17676404edcSAsim Jamshed TRACE_INFO("Failed to create socket! (%s)\n",
17776404edcSAsim Jamshed strerror(errno));
17876404edcSAsim Jamshed return -1;
17976404edcSAsim Jamshed }
18076404edcSAsim Jamshed memset(&ctx->wvars[sockid], 0, sizeof(struct wget_vars));
18176404edcSAsim Jamshed ret = mtcp_setsock_nonblock(mctx, sockid);
18276404edcSAsim Jamshed if (ret < 0) {
18376404edcSAsim Jamshed TRACE_ERROR("Failed to set socket in nonblocking mode.\n");
18476404edcSAsim Jamshed exit(-1);
18576404edcSAsim Jamshed }
18676404edcSAsim Jamshed
18776404edcSAsim Jamshed addr.sin_family = AF_INET;
18876404edcSAsim Jamshed addr.sin_addr.s_addr = daddr;
18976404edcSAsim Jamshed addr.sin_port = dport;
19076404edcSAsim Jamshed
19176404edcSAsim Jamshed ret = mtcp_connect(mctx, sockid,
19276404edcSAsim Jamshed (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
19376404edcSAsim Jamshed if (ret < 0) {
19476404edcSAsim Jamshed if (errno != EINPROGRESS) {
19576404edcSAsim Jamshed perror("mtcp_connect");
19676404edcSAsim Jamshed mtcp_close(mctx, sockid);
19776404edcSAsim Jamshed return -1;
19876404edcSAsim Jamshed }
19976404edcSAsim Jamshed }
20076404edcSAsim Jamshed
20176404edcSAsim Jamshed ctx->started++;
20276404edcSAsim Jamshed ctx->pending++;
20376404edcSAsim Jamshed ctx->stat.connects++;
20476404edcSAsim Jamshed
20576404edcSAsim Jamshed ev.events = MOS_EPOLLOUT;
20676404edcSAsim Jamshed ev.data.sock = sockid;
20776404edcSAsim Jamshed mtcp_epoll_ctl(mctx, ctx->ep, MOS_EPOLL_CTL_ADD, sockid, &ev);
20876404edcSAsim Jamshed
20976404edcSAsim Jamshed return sockid;
21076404edcSAsim Jamshed }
21176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
21276404edcSAsim Jamshed static inline void
CloseConnection(thread_context_t ctx,int sockid)21376404edcSAsim Jamshed CloseConnection(thread_context_t ctx, int sockid)
21476404edcSAsim Jamshed {
21576404edcSAsim Jamshed mtcp_epoll_ctl(ctx->mctx, ctx->ep, MOS_EPOLL_CTL_DEL, sockid, NULL);
21676404edcSAsim Jamshed mtcp_close(ctx->mctx, sockid);
21776404edcSAsim Jamshed ctx->pending--;
21876404edcSAsim Jamshed ctx->done++;
21976404edcSAsim Jamshed assert(ctx->pending >= 0);
22076404edcSAsim Jamshed while (/*ctx->pending*/ mtcp_get_connection_cnt(ctx->mctx) < concurrency && ctx->started < ctx->target) {
22176404edcSAsim Jamshed if (CreateConnection(ctx) < 0) {
22276404edcSAsim Jamshed done[ctx->core] = TRUE;
22376404edcSAsim Jamshed break;
22476404edcSAsim Jamshed }
22576404edcSAsim Jamshed }
22676404edcSAsim Jamshed }
22776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
22876404edcSAsim Jamshed static inline int
SendHTTPRequest(thread_context_t ctx,int sockid,struct wget_vars * wv)22976404edcSAsim Jamshed SendHTTPRequest(thread_context_t ctx, int sockid, struct wget_vars *wv)
23076404edcSAsim Jamshed {
23176404edcSAsim Jamshed char request[HTTP_HEADER_LEN];
23276404edcSAsim Jamshed struct mtcp_epoll_event ev;
23376404edcSAsim Jamshed int wr;
23476404edcSAsim Jamshed int len;
23576404edcSAsim Jamshed
23676404edcSAsim Jamshed wv->headerset = FALSE;
23776404edcSAsim Jamshed wv->recv = 0;
23876404edcSAsim Jamshed wv->header_len = wv->file_len = 0;
23976404edcSAsim Jamshed
240*9120200aSAsim Jamshed if (keep_alive) {
241*9120200aSAsim Jamshed snprintf(request, HTTP_HEADER_LEN, "GET %s HTTP/1.0\r\n"
242*9120200aSAsim Jamshed "User-Agent: Wget/1.12 (linux-gnu)\r\n"
243*9120200aSAsim Jamshed "Accept: */*\r\n"
244*9120200aSAsim Jamshed "Host: %s\r\n"
245*9120200aSAsim Jamshed "Connection: Keep-Alive\r\n\r\n",
246*9120200aSAsim Jamshed path, host);
247*9120200aSAsim Jamshed } else {
24876404edcSAsim Jamshed snprintf(request, HTTP_HEADER_LEN, "GET %s HTTP/1.0\r\n"
24976404edcSAsim Jamshed "User-Agent: Wget/1.12 (linux-gnu)\r\n"
25076404edcSAsim Jamshed "Accept: */*\r\n"
25176404edcSAsim Jamshed "Host: %s\r\n"
25276404edcSAsim Jamshed // "Connection: Keep-Alive\r\n\r\n",
25376404edcSAsim Jamshed "Connection: Close\r\n\r\n",
25476404edcSAsim Jamshed path, host);
255*9120200aSAsim Jamshed }
256*9120200aSAsim Jamshed
25776404edcSAsim Jamshed len = strlen(request);
25876404edcSAsim Jamshed
25976404edcSAsim Jamshed wr = mtcp_write(ctx->mctx, sockid, request, len);
26076404edcSAsim Jamshed if (wr < len) {
26176404edcSAsim Jamshed TRACE_ERROR("Socket %d: Sending HTTP request failed. "
26276404edcSAsim Jamshed "try: %d, sent: %d\n", sockid, len, wr);
26376404edcSAsim Jamshed CloseConnection(ctx, sockid);
26476404edcSAsim Jamshed }
26576404edcSAsim Jamshed ctx->stat.writes += wr;
26676404edcSAsim Jamshed TRACE_APP("Socket %d HTTP Request of %d bytes. sent.\n", sockid, wr);
26776404edcSAsim Jamshed wv->request_sent = TRUE;
26876404edcSAsim Jamshed
26976404edcSAsim Jamshed ev.events = MOS_EPOLLIN;
27076404edcSAsim Jamshed ev.data.sock = sockid;
27176404edcSAsim Jamshed mtcp_epoll_ctl(ctx->mctx, ctx->ep, MOS_EPOLL_CTL_MOD, sockid, &ev);
27276404edcSAsim Jamshed
27376404edcSAsim Jamshed gettimeofday(&wv->t_start, NULL);
27476404edcSAsim Jamshed
27576404edcSAsim Jamshed char fname[MAX_FILE_LEN + 1];
27676404edcSAsim Jamshed if (fio) {
27776404edcSAsim Jamshed snprintf(fname, MAX_FILE_LEN, "%s.%d", outfile, flowcnt++);
27876404edcSAsim Jamshed wv->fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
27976404edcSAsim Jamshed if (wv->fd < 0) {
28076404edcSAsim Jamshed TRACE_APP("Failed to open file descriptor for %s\n", fname);
28176404edcSAsim Jamshed exit(1);
28276404edcSAsim Jamshed }
28376404edcSAsim Jamshed }
28476404edcSAsim Jamshed
28576404edcSAsim Jamshed return 0;
28676404edcSAsim Jamshed }
28776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
28876404edcSAsim Jamshed static inline int
DownloadNext(thread_context_t ctx,int sockid,struct wget_vars * wv)289*9120200aSAsim Jamshed DownloadNext(thread_context_t ctx, int sockid, struct wget_vars *wv)
290*9120200aSAsim Jamshed {
291*9120200aSAsim Jamshed mctx_t mctx = ctx->mctx;
292*9120200aSAsim Jamshed uint64_t tdiff;
293*9120200aSAsim Jamshed struct mtcp_epoll_event ev;
294*9120200aSAsim Jamshed
295*9120200aSAsim Jamshed TRACE_APP("Socket %d File download complete!\n", sockid);
296*9120200aSAsim Jamshed gettimeofday(&wv->t_end, NULL);
297*9120200aSAsim Jamshed
298*9120200aSAsim Jamshed ctx->stat.completes++;
299*9120200aSAsim Jamshed
300*9120200aSAsim Jamshed if (wv->recv - wv->header_len != wv->file_len) {
301*9120200aSAsim Jamshed fprintf(stderr, "Response size mismatch! "
302*9120200aSAsim Jamshed "actual recved: %ld, expected to recved: %ld\n",
303*9120200aSAsim Jamshed wv->recv-wv->header_len, wv->file_len);
304*9120200aSAsim Jamshed }
305*9120200aSAsim Jamshed
306*9120200aSAsim Jamshed tdiff = (wv->t_end.tv_sec - wv->t_start.tv_sec) * 1000000 +
307*9120200aSAsim Jamshed (wv->t_end.tv_usec - wv->t_start.tv_usec);
308*9120200aSAsim Jamshed TRACE_APP("Socket %d Total received bytes: %lu (%luMB)\n",
309*9120200aSAsim Jamshed sockid, wv->recv, wv->recv / 1000000);
310*9120200aSAsim Jamshed TRACE_APP("Socket %d Total spent time: %lu us\n", sockid, tdiff);
311*9120200aSAsim Jamshed if (tdiff > 0) {
312*9120200aSAsim Jamshed TRACE_APP("Socket %d Average bandwidth: %lf[MB/s]\n",
313*9120200aSAsim Jamshed sockid, (double)wv->recv / tdiff);
314*9120200aSAsim Jamshed }
315*9120200aSAsim Jamshed ctx->stat.sum_resp_time += tdiff;
316*9120200aSAsim Jamshed if (tdiff > ctx->stat.max_resp_time)
317*9120200aSAsim Jamshed ctx->stat.max_resp_time = tdiff;
318*9120200aSAsim Jamshed
319*9120200aSAsim Jamshed ctx->done++;
320*9120200aSAsim Jamshed
321*9120200aSAsim Jamshed /* instead of closing the connection, download the next file */
322*9120200aSAsim Jamshed memset(&ctx->wvars[sockid], 0, sizeof(struct wget_vars));
323*9120200aSAsim Jamshed
324*9120200aSAsim Jamshed ctx->started++;
325*9120200aSAsim Jamshed
326*9120200aSAsim Jamshed ev.events = MOS_EPOLLOUT;
327*9120200aSAsim Jamshed ev.data.sock = sockid;
328*9120200aSAsim Jamshed mtcp_epoll_ctl(mctx, ctx->ep, MOS_EPOLL_CTL_MOD, sockid, &ev);
329*9120200aSAsim Jamshed
330*9120200aSAsim Jamshed return 0;
331*9120200aSAsim Jamshed }
332*9120200aSAsim Jamshed /*----------------------------------------------------------------------------*/
333*9120200aSAsim Jamshed static inline int
DownloadComplete(thread_context_t ctx,int sockid,struct wget_vars * wv)33476404edcSAsim Jamshed DownloadComplete(thread_context_t ctx, int sockid, struct wget_vars *wv)
33576404edcSAsim Jamshed {
33676404edcSAsim Jamshed #ifdef APP
33776404edcSAsim Jamshed mctx_t mctx = ctx->mctx;
33876404edcSAsim Jamshed #endif
33976404edcSAsim Jamshed uint64_t tdiff;
34076404edcSAsim Jamshed
34176404edcSAsim Jamshed TRACE_APP("Socket %d File download complete!\n", sockid);
34276404edcSAsim Jamshed gettimeofday(&wv->t_end, NULL);
34376404edcSAsim Jamshed CloseConnection(ctx, sockid);
34476404edcSAsim Jamshed ctx->stat.completes++;
34576404edcSAsim Jamshed
34676404edcSAsim Jamshed if (wv->recv - wv->header_len != wv->file_len) {
34776404edcSAsim Jamshed fprintf(stderr, "Response size mismatch! "
34876404edcSAsim Jamshed "actual recved: %ld, expected to recved: %ld\n",
34976404edcSAsim Jamshed wv->recv-wv->header_len, wv->file_len);
35076404edcSAsim Jamshed }
35176404edcSAsim Jamshed
35276404edcSAsim Jamshed tdiff = (wv->t_end.tv_sec - wv->t_start.tv_sec) * 1000000 +
35376404edcSAsim Jamshed (wv->t_end.tv_usec - wv->t_start.tv_usec);
35476404edcSAsim Jamshed TRACE_APP("Socket %d Total received bytes: %lu (%luMB)\n",
35576404edcSAsim Jamshed sockid, wv->recv, wv->recv / 1000000);
35676404edcSAsim Jamshed TRACE_APP("Socket %d Total spent time: %lu us\n", sockid, tdiff);
35776404edcSAsim Jamshed if (tdiff > 0) {
35876404edcSAsim Jamshed TRACE_APP("Socket %d Average bandwidth: %lf[MB/s]\n",
35976404edcSAsim Jamshed sockid, (double)wv->recv / tdiff);
36076404edcSAsim Jamshed }
36176404edcSAsim Jamshed ctx->stat.sum_resp_time += tdiff;
36276404edcSAsim Jamshed if (tdiff > ctx->stat.max_resp_time)
36376404edcSAsim Jamshed ctx->stat.max_resp_time = tdiff;
36476404edcSAsim Jamshed
36576404edcSAsim Jamshed if (fio && wv->fd > 0)
36676404edcSAsim Jamshed close(wv->fd);
36776404edcSAsim Jamshed
36876404edcSAsim Jamshed return 0;
36976404edcSAsim Jamshed }
37076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
37176404edcSAsim Jamshed static inline int
HandleReadEvent(thread_context_t ctx,int sockid,struct wget_vars * wv)37276404edcSAsim Jamshed HandleReadEvent(thread_context_t ctx, int sockid, struct wget_vars *wv)
37376404edcSAsim Jamshed {
37476404edcSAsim Jamshed mctx_t mctx = ctx->mctx;
37576404edcSAsim Jamshed char buf[BUF_SIZE];
37676404edcSAsim Jamshed char *pbuf;
37776404edcSAsim Jamshed int rd, copy_len;
37876404edcSAsim Jamshed
37976404edcSAsim Jamshed rd = 1;
38076404edcSAsim Jamshed while (rd > 0) {
38176404edcSAsim Jamshed rd = mtcp_read(mctx, sockid, buf, BUF_SIZE);
38276404edcSAsim Jamshed if (rd <= 0)
38376404edcSAsim Jamshed break;
38476404edcSAsim Jamshed ctx->stat.reads += rd;
38576404edcSAsim Jamshed
38676404edcSAsim Jamshed TRACE_APP("Socket %d: mtcp_read ret: %d, total_recv: %lu, "
38776404edcSAsim Jamshed "header_set: %d, header_len: %u, file_len: %lu\n",
38876404edcSAsim Jamshed sockid, rd, wv->recv + rd,
38976404edcSAsim Jamshed wv->headerset, wv->header_len, wv->file_len);
39076404edcSAsim Jamshed
39176404edcSAsim Jamshed pbuf = buf;
39276404edcSAsim Jamshed if (!wv->headerset) {
39376404edcSAsim Jamshed copy_len = MIN(rd, HTTP_HEADER_LEN - wv->resp_len);
39476404edcSAsim Jamshed memcpy(wv->response + wv->resp_len, buf, copy_len);
39576404edcSAsim Jamshed wv->resp_len += copy_len;
39676404edcSAsim Jamshed wv->header_len = find_http_header(wv->response, wv->resp_len);
39776404edcSAsim Jamshed if (wv->header_len > 0) {
39876404edcSAsim Jamshed wv->response[wv->header_len] = '\0';
39976404edcSAsim Jamshed wv->file_len = http_header_long_val(wv->response,
40076404edcSAsim Jamshed CONTENT_LENGTH_HDR, sizeof(CONTENT_LENGTH_HDR) - 1);
401*9120200aSAsim Jamshed if (wv->file_len < 0) {
402*9120200aSAsim Jamshed /* failed to find for the Content-Length field */
403*9120200aSAsim Jamshed wv->recv += rd;
404*9120200aSAsim Jamshed rd = 0;
405*9120200aSAsim Jamshed CloseConnection(ctx, sockid);
406*9120200aSAsim Jamshed return 0;
407*9120200aSAsim Jamshed }
40876404edcSAsim Jamshed TRACE_APP("Socket %d Parsed response header. "
40976404edcSAsim Jamshed "Header length: %u, File length: %lu (%luMB)\n",
41076404edcSAsim Jamshed sockid, wv->header_len,
41176404edcSAsim Jamshed wv->file_len, wv->file_len / 1024 / 1024);
41276404edcSAsim Jamshed wv->headerset = TRUE;
41376404edcSAsim Jamshed wv->recv += (rd - (wv->resp_len - wv->header_len));
41476404edcSAsim Jamshed
41576404edcSAsim Jamshed pbuf += (rd - (wv->resp_len - wv->header_len));
416d8823779SAsim Jamshed rd = (wv->resp_len - wv->header_len);
41776404edcSAsim Jamshed
41876404edcSAsim Jamshed } else {
41976404edcSAsim Jamshed /* failed to parse response header */
42076404edcSAsim Jamshed wv->recv += rd;
42176404edcSAsim Jamshed rd = 0;
42276404edcSAsim Jamshed ctx->stat.errors++;
42376404edcSAsim Jamshed ctx->errors++;
42476404edcSAsim Jamshed CloseConnection(ctx, sockid);
42576404edcSAsim Jamshed return 0;
42676404edcSAsim Jamshed }
42776404edcSAsim Jamshed }
42876404edcSAsim Jamshed wv->recv += rd;
42976404edcSAsim Jamshed
43076404edcSAsim Jamshed if (fio && wv->fd > 0) {
43176404edcSAsim Jamshed int wr = 0;
43276404edcSAsim Jamshed while (wr < rd) {
43376404edcSAsim Jamshed int _wr = write(wv->fd, pbuf + wr, rd - wr);
43476404edcSAsim Jamshed assert (_wr == rd - wr);
43576404edcSAsim Jamshed if (_wr < 0) {
43676404edcSAsim Jamshed perror("write");
43776404edcSAsim Jamshed TRACE_ERROR("Failed to write.\n");
43876404edcSAsim Jamshed assert(0);
43976404edcSAsim Jamshed break;
44076404edcSAsim Jamshed }
44176404edcSAsim Jamshed wr += _wr;
44276404edcSAsim Jamshed wv->write += _wr;
44376404edcSAsim Jamshed }
44476404edcSAsim Jamshed }
44576404edcSAsim Jamshed
44676404edcSAsim Jamshed if (wv->header_len && (wv->recv >= wv->header_len + wv->file_len)) {
44776404edcSAsim Jamshed break;
44876404edcSAsim Jamshed }
44976404edcSAsim Jamshed }
45076404edcSAsim Jamshed
45176404edcSAsim Jamshed if (rd > 0) {
45276404edcSAsim Jamshed if (wv->header_len && (wv->recv >= wv->header_len + wv->file_len)) {
45376404edcSAsim Jamshed TRACE_APP("Socket %d Done Write: "
45476404edcSAsim Jamshed "header: %u file: %lu recv: %lu write: %lu\n",
45576404edcSAsim Jamshed sockid, wv->header_len, wv->file_len,
45676404edcSAsim Jamshed wv->recv - wv->header_len, wv->write);
457*9120200aSAsim Jamshed
458*9120200aSAsim Jamshed if (keep_alive && ctx->started < ctx->target)
459*9120200aSAsim Jamshed DownloadNext(ctx, sockid, wv);
460*9120200aSAsim Jamshed else
46176404edcSAsim Jamshed DownloadComplete(ctx, sockid, wv);
46276404edcSAsim Jamshed
46376404edcSAsim Jamshed return 0;
46476404edcSAsim Jamshed }
46576404edcSAsim Jamshed
46676404edcSAsim Jamshed } else if (rd == 0) {
46776404edcSAsim Jamshed /* connection closed by remote host */
46876404edcSAsim Jamshed TRACE_DBG("Socket %d connection closed with server.\n", sockid);
46976404edcSAsim Jamshed
47076404edcSAsim Jamshed if (wv->header_len && (wv->recv >= wv->header_len + wv->file_len)) {
47176404edcSAsim Jamshed DownloadComplete(ctx, sockid, wv);
47276404edcSAsim Jamshed } else {
47376404edcSAsim Jamshed ctx->stat.errors++;
47476404edcSAsim Jamshed ctx->incompletes++;
47576404edcSAsim Jamshed CloseConnection(ctx, sockid);
47676404edcSAsim Jamshed }
47776404edcSAsim Jamshed
47876404edcSAsim Jamshed } else if (rd < 0) {
47976404edcSAsim Jamshed if (errno != EAGAIN) {
48076404edcSAsim Jamshed TRACE_DBG("Socket %d: mtcp_read() error %s\n",
48176404edcSAsim Jamshed sockid, strerror(errno));
48276404edcSAsim Jamshed ctx->stat.errors++;
48376404edcSAsim Jamshed ctx->errors++;
48476404edcSAsim Jamshed CloseConnection(ctx, sockid);
48576404edcSAsim Jamshed }
48676404edcSAsim Jamshed }
48776404edcSAsim Jamshed
48876404edcSAsim Jamshed return 0;
48976404edcSAsim Jamshed }
49076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
49176404edcSAsim Jamshed static void
PrintStats()49276404edcSAsim Jamshed PrintStats()
49376404edcSAsim Jamshed {
49476404edcSAsim Jamshed struct wget_stat total = {0};
49576404edcSAsim Jamshed struct wget_stat *st;
49676404edcSAsim Jamshed uint64_t avg_resp_time;
49776404edcSAsim Jamshed uint64_t total_resp_time = 0;
49876404edcSAsim Jamshed int i;
49976404edcSAsim Jamshed
50076404edcSAsim Jamshed for (i = 0; i < core_limit; i++) {
50176404edcSAsim Jamshed st = g_stat[i];
50276404edcSAsim Jamshed if (!st)
50376404edcSAsim Jamshed continue;
50476404edcSAsim Jamshed avg_resp_time = st->completes? st->sum_resp_time / st->completes : 0;
50576404edcSAsim Jamshed
50676404edcSAsim Jamshed total.waits += st->waits;
50776404edcSAsim Jamshed total.events += st->events;
50876404edcSAsim Jamshed total.connects += st->connects;
50976404edcSAsim Jamshed total.reads += st->reads;
51076404edcSAsim Jamshed total.writes += st->writes;
51176404edcSAsim Jamshed total.completes += st->completes;
51276404edcSAsim Jamshed total_resp_time += avg_resp_time;
51376404edcSAsim Jamshed if (st->max_resp_time > total.max_resp_time)
51476404edcSAsim Jamshed total.max_resp_time = st->max_resp_time;
51576404edcSAsim Jamshed total.errors += st->errors;
51676404edcSAsim Jamshed total.timedout += st->timedout;
51776404edcSAsim Jamshed
51876404edcSAsim Jamshed memset(st, 0, sizeof(struct wget_stat));
51976404edcSAsim Jamshed }
52076404edcSAsim Jamshed fprintf(stderr, "[ ALL ] connect: %7lu, read: %4lu MB, write: %4lu MB, "
52176404edcSAsim Jamshed "completes: %7lu (resp_time avg: %4lu, max: %6lu us)\n",
52276404edcSAsim Jamshed total.connects,
523e160edcaSAsim Jamshed total.reads / 1024 / 1024, total.writes / 1024 / 1024,
52476404edcSAsim Jamshed total.completes, total_resp_time / core_limit, total.max_resp_time);
52576404edcSAsim Jamshed }
52676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
52776404edcSAsim Jamshed static void
GlbInitWget()52876404edcSAsim Jamshed GlbInitWget()
52976404edcSAsim Jamshed {
53076404edcSAsim Jamshed struct mtcp_conf mcfg;
53176404edcSAsim Jamshed char *url;
53276404edcSAsim Jamshed int total_concurrency = 0;
53376404edcSAsim Jamshed int flow_per_thread;
53476404edcSAsim Jamshed int flow_remainder_cnt;
53576404edcSAsim Jamshed int i;
53676404edcSAsim Jamshed
53776404edcSAsim Jamshed num_cores = GetNumCPUs();
53876404edcSAsim Jamshed core_limit = num_cores;
53976404edcSAsim Jamshed concurrency = 100;
54076404edcSAsim Jamshed total_flows = -1;
54176404edcSAsim Jamshed
54276404edcSAsim Jamshed LoadConfig(CONFIG_FILE, g_conf, NUM_CONF_VAR);
54376404edcSAsim Jamshed
54476404edcSAsim Jamshed url = g_conf[0].value;
54576404edcSAsim Jamshed total_flows = atoi(g_conf[1].value);
54676404edcSAsim Jamshed core_limit = atoi(g_conf[2].value);
54776404edcSAsim Jamshed total_concurrency = atoi(g_conf[3].value);
54876404edcSAsim Jamshed dest_port = atoi(g_conf[4].value);
549*9120200aSAsim Jamshed keep_alive = atoi(g_conf[5].value);
55076404edcSAsim Jamshed
55176404edcSAsim Jamshed if ((strlen(url) == 0)
55276404edcSAsim Jamshed || (strlen(url) > MAX_URL_LEN)
55376404edcSAsim Jamshed || (total_flows <= 0)) {
55476404edcSAsim Jamshed TRACE_INFO("Invalid configuration\n");
55576404edcSAsim Jamshed exit(0);
55676404edcSAsim Jamshed }
55776404edcSAsim Jamshed
55876404edcSAsim Jamshed char* slash_p = strchr(url, '/');
55976404edcSAsim Jamshed if (slash_p) {
56076404edcSAsim Jamshed strncpy(host, url, slash_p - url);
56176404edcSAsim Jamshed strncpy(path, strchr(url, '/'), MAX_URL_LEN);
56276404edcSAsim Jamshed } else {
56376404edcSAsim Jamshed strncpy(host, url, MAX_IP_STR_LEN);
56476404edcSAsim Jamshed strncpy(path, "/", 1);
56576404edcSAsim Jamshed }
56676404edcSAsim Jamshed
56776404edcSAsim Jamshed daddr = inet_addr(host);
56876404edcSAsim Jamshed dport = (dest_port == 0) ? htons(PORT_NUM) : htons(dest_port);
56976404edcSAsim Jamshed saddr = INADDR_ANY;
57076404edcSAsim Jamshed
57176404edcSAsim Jamshed if (total_flows < core_limit) {
57276404edcSAsim Jamshed core_limit = total_flows;
57376404edcSAsim Jamshed }
57476404edcSAsim Jamshed
57576404edcSAsim Jamshed /* per-core concurrency = total_concurrency / # cores */
57676404edcSAsim Jamshed if (total_concurrency > 0)
57776404edcSAsim Jamshed concurrency = total_concurrency / core_limit;
57876404edcSAsim Jamshed
57976404edcSAsim Jamshed /* set the max number of fds 3x larger than concurrency */
58076404edcSAsim Jamshed max_fds = concurrency * 3;
58176404edcSAsim Jamshed
58276404edcSAsim Jamshed TRACE_CONFIG("Application configuration:\n");
58376404edcSAsim Jamshed TRACE_CONFIG("URL: %s\n", path);
58476404edcSAsim Jamshed TRACE_CONFIG("# of total_flows: %d\n", total_flows);
58576404edcSAsim Jamshed TRACE_CONFIG("# of cores: %d\n", core_limit);
58676404edcSAsim Jamshed TRACE_CONFIG("Concurrency: %d\n", total_concurrency);
58776404edcSAsim Jamshed
58876404edcSAsim Jamshed mtcp_getconf(&mcfg);
58976404edcSAsim Jamshed mcfg.max_concurrency = max_fds;
59076404edcSAsim Jamshed mcfg.max_num_buffers = max_fds;
59176404edcSAsim Jamshed mtcp_setconf(&mcfg);
59276404edcSAsim Jamshed
59376404edcSAsim Jamshed flow_per_thread = total_flows / core_limit;
59476404edcSAsim Jamshed flow_remainder_cnt = total_flows % core_limit;
59576404edcSAsim Jamshed
59676404edcSAsim Jamshed for (i = 0; i < MAX_CPUS; i++) {
59776404edcSAsim Jamshed done[i] = FALSE;
59876404edcSAsim Jamshed flows[i] = flow_per_thread;
59976404edcSAsim Jamshed
60076404edcSAsim Jamshed if (flow_remainder_cnt-- > 0)
60176404edcSAsim Jamshed flows[i]++;
60276404edcSAsim Jamshed }
60376404edcSAsim Jamshed
60476404edcSAsim Jamshed return;
60576404edcSAsim Jamshed }
60676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
60776404edcSAsim Jamshed static void
InitWget(mctx_t mctx,void ** app_ctx)60876404edcSAsim Jamshed InitWget(mctx_t mctx, void **app_ctx)
60976404edcSAsim Jamshed {
61076404edcSAsim Jamshed thread_context_t ctx;
61176404edcSAsim Jamshed int ep;
61276404edcSAsim Jamshed
61376404edcSAsim Jamshed assert(mctx);
61476404edcSAsim Jamshed
61576404edcSAsim Jamshed int core = mctx->cpu;
61676404edcSAsim Jamshed
61776404edcSAsim Jamshed ctx = CreateContext(mctx);
61876404edcSAsim Jamshed if (!ctx)
61976404edcSAsim Jamshed exit(-1);
62076404edcSAsim Jamshed g_ctx[core] = ctx;
62176404edcSAsim Jamshed g_stat[core] = &ctx->stat;
62276404edcSAsim Jamshed srand(time(NULL));
62376404edcSAsim Jamshed
62476404edcSAsim Jamshed mtcp_init_rss(mctx, saddr, IP_RANGE, daddr, dport);
62576404edcSAsim Jamshed
62676404edcSAsim Jamshed if (flows[core] == 0) {
62776404edcSAsim Jamshed TRACE_DBG("Application thread %d finished.\n", core);
62876404edcSAsim Jamshed exit(-1);
62976404edcSAsim Jamshed }
63076404edcSAsim Jamshed ctx->target = flows[core];
63176404edcSAsim Jamshed
63276404edcSAsim Jamshed /* Initialization */
63376404edcSAsim Jamshed ctx->maxevents = max_fds * 3;
63476404edcSAsim Jamshed ep = mtcp_epoll_create(mctx, ctx->maxevents);
63576404edcSAsim Jamshed if (ep < 0) {
63676404edcSAsim Jamshed TRACE_ERROR("Failed to create epoll struct!n");
63776404edcSAsim Jamshed exit(EXIT_FAILURE);
63876404edcSAsim Jamshed }
63976404edcSAsim Jamshed ctx->events = (struct mtcp_epoll_event *)
64076404edcSAsim Jamshed calloc(ctx->maxevents, sizeof(struct mtcp_epoll_event));
64176404edcSAsim Jamshed if (!ctx->events) {
64276404edcSAsim Jamshed TRACE_ERROR("Failed to allocate events!\n");
64376404edcSAsim Jamshed exit(EXIT_FAILURE);
64476404edcSAsim Jamshed }
64576404edcSAsim Jamshed ctx->ep = ep;
64676404edcSAsim Jamshed
64776404edcSAsim Jamshed ctx->wvars = (struct wget_vars *)calloc(max_fds, sizeof(struct wget_vars));
64876404edcSAsim Jamshed if (!ctx->wvars) {
64976404edcSAsim Jamshed TRACE_ERROR("Failed to create wget variables!\n");
65076404edcSAsim Jamshed exit(EXIT_FAILURE);
65176404edcSAsim Jamshed }
65276404edcSAsim Jamshed
65376404edcSAsim Jamshed ctx->started = ctx->done = ctx->pending = 0;
65476404edcSAsim Jamshed ctx->errors = ctx->incompletes = 0;
65576404edcSAsim Jamshed
65676404edcSAsim Jamshed *app_ctx = ctx;
65776404edcSAsim Jamshed
65876404edcSAsim Jamshed return;
65976404edcSAsim Jamshed }
66076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
66176404edcSAsim Jamshed static void
RunWget(mctx_t mctx,void ** app_ctx)66276404edcSAsim Jamshed RunWget(mctx_t mctx, void **app_ctx)
66376404edcSAsim Jamshed {
66476404edcSAsim Jamshed struct in_addr daddr_in;
66576404edcSAsim Jamshed struct timeval cur_tv, prev_tv;
66676404edcSAsim Jamshed int nevents;
66776404edcSAsim Jamshed int i;
66876404edcSAsim Jamshed
66976404edcSAsim Jamshed assert(mctx);
67076404edcSAsim Jamshed assert(*app_ctx);
67176404edcSAsim Jamshed
67276404edcSAsim Jamshed thread_context_t ctx = *app_ctx;
67376404edcSAsim Jamshed int core = ctx->core;
67476404edcSAsim Jamshed
67576404edcSAsim Jamshed daddr_in.s_addr = daddr;
67676404edcSAsim Jamshed fprintf(stderr, "Thread %d handles %d flows. connecting to %s:%u\n",
67776404edcSAsim Jamshed core, flows[core], inet_ntoa(daddr_in), ntohs(dport));
67876404edcSAsim Jamshed
67976404edcSAsim Jamshed gettimeofday(&cur_tv, NULL);
68076404edcSAsim Jamshed prev_tv = cur_tv;
68176404edcSAsim Jamshed
68276404edcSAsim Jamshed while (!done[core]) {
68376404edcSAsim Jamshed gettimeofday(&cur_tv, NULL);
68476404edcSAsim Jamshed
68576404edcSAsim Jamshed /* print statistics every second */
68676404edcSAsim Jamshed if (core == 0 && cur_tv.tv_sec > prev_tv.tv_sec) {
68776404edcSAsim Jamshed PrintStats();
68876404edcSAsim Jamshed prev_tv = cur_tv;
68976404edcSAsim Jamshed }
69076404edcSAsim Jamshed
69176404edcSAsim Jamshed while (/*ctx->pending*/ mtcp_get_connection_cnt(ctx->mctx) < concurrency && ctx->started < ctx->target) {
69276404edcSAsim Jamshed if (CreateConnection(ctx) < 0) {
69376404edcSAsim Jamshed done[core] = TRUE;
69476404edcSAsim Jamshed break;
69576404edcSAsim Jamshed }
69676404edcSAsim Jamshed }
69776404edcSAsim Jamshed
69876404edcSAsim Jamshed nevents = mtcp_epoll_wait(mctx, ctx->ep,
69976404edcSAsim Jamshed ctx->events, ctx->maxevents, ctx->pending ? -1 : 10);
70076404edcSAsim Jamshed ctx->stat.waits++;
70176404edcSAsim Jamshed
70276404edcSAsim Jamshed if (nevents < 0) {
70376404edcSAsim Jamshed if (errno != EINTR) {
70476404edcSAsim Jamshed TRACE_ERROR("mtcp_epoll_wait failed! ret: %d\n", nevents);
70576404edcSAsim Jamshed }
70676404edcSAsim Jamshed done[core] = TRUE;
70776404edcSAsim Jamshed break;
70876404edcSAsim Jamshed } else {
70976404edcSAsim Jamshed ctx->stat.events += nevents;
71076404edcSAsim Jamshed }
71176404edcSAsim Jamshed
71276404edcSAsim Jamshed for (i = 0; i < nevents; i++) {
71376404edcSAsim Jamshed
71476404edcSAsim Jamshed if (ctx->events[i].events & MOS_EPOLLERR) {
71576404edcSAsim Jamshed int err;
71676404edcSAsim Jamshed socklen_t len = sizeof(err);
71776404edcSAsim Jamshed
71876404edcSAsim Jamshed TRACE_APP("[CPU %d] Error on socket %d\n",
71976404edcSAsim Jamshed core, ctx->events[i].data.sockid);
72076404edcSAsim Jamshed ctx->stat.errors++;
72176404edcSAsim Jamshed ctx->errors++;
72276404edcSAsim Jamshed if (mtcp_getsockopt(mctx, ctx->events[i].data.sock,
72376404edcSAsim Jamshed SOL_SOCKET, SO_ERROR, (void *)&err, &len) == 0) {
72476404edcSAsim Jamshed if (err == ETIMEDOUT)
72576404edcSAsim Jamshed ctx->stat.timedout++;
72676404edcSAsim Jamshed }
72776404edcSAsim Jamshed CloseConnection(ctx, ctx->events[i].data.sock);
72876404edcSAsim Jamshed
72976404edcSAsim Jamshed } else if (ctx->events[i].events & MOS_EPOLLIN) {
73076404edcSAsim Jamshed HandleReadEvent(ctx,
73176404edcSAsim Jamshed ctx->events[i].data.sock,
73276404edcSAsim Jamshed &ctx->wvars[ctx->events[i].data.sock]);
73376404edcSAsim Jamshed
73476404edcSAsim Jamshed } else if (ctx->events[i].events == MOS_EPOLLOUT) {
73576404edcSAsim Jamshed struct wget_vars *wv = &ctx->wvars[ctx->events[i].data.sock];
73676404edcSAsim Jamshed
73776404edcSAsim Jamshed if (!wv->request_sent) {
73876404edcSAsim Jamshed SendHTTPRequest(ctx, ctx->events[i].data.sock, wv);
73976404edcSAsim Jamshed } else {
74076404edcSAsim Jamshed //TRACE_DBG("Request already sent.\n");
74176404edcSAsim Jamshed }
74276404edcSAsim Jamshed
74376404edcSAsim Jamshed } else {
74476404edcSAsim Jamshed TRACE_ERROR("Socket %d: event: %s\n",
74576404edcSAsim Jamshed ctx->events[i].data.sock,
74676404edcSAsim Jamshed EventToString(ctx->events[i].events));
74776404edcSAsim Jamshed assert(0);
74876404edcSAsim Jamshed }
74976404edcSAsim Jamshed }
75076404edcSAsim Jamshed
75176404edcSAsim Jamshed if (ctx->done >= ctx->target) {
75276404edcSAsim Jamshed fprintf(stdout, "Completed %d connections, "
75376404edcSAsim Jamshed "errors: %d incompletes: %d\n",
75476404edcSAsim Jamshed ctx->done, ctx->errors, ctx->incompletes);
75576404edcSAsim Jamshed break;
75676404edcSAsim Jamshed }
75776404edcSAsim Jamshed }
75876404edcSAsim Jamshed
75976404edcSAsim Jamshed TRACE_INFO("Wget thread %d waiting for mtcp to be destroyed.\n", core);
76076404edcSAsim Jamshed
76176404edcSAsim Jamshed g_stat[core] = NULL;
76276404edcSAsim Jamshed g_ctx[core] = NULL;
76376404edcSAsim Jamshed DestroyContext(ctx);
76476404edcSAsim Jamshed
76576404edcSAsim Jamshed return;
76676404edcSAsim Jamshed }
76776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
76876404edcSAsim Jamshed void
RunApplication(mctx_t mctx)76976404edcSAsim Jamshed RunApplication(mctx_t mctx)
77076404edcSAsim Jamshed {
77176404edcSAsim Jamshed void *app_ctx;
77276404edcSAsim Jamshed
77376404edcSAsim Jamshed app_ctx = (void *)calloc(1, sizeof(void *));
77476404edcSAsim Jamshed if (!app_ctx) {
77576404edcSAsim Jamshed TRACE_ERROR("calloc failure\n");
77676404edcSAsim Jamshed return;
77776404edcSAsim Jamshed }
77876404edcSAsim Jamshed
77976404edcSAsim Jamshed TRACE_INFO("run application on core %d\n", mctx->cpu);
78076404edcSAsim Jamshed InitWget(mctx, &(app_ctx));
78176404edcSAsim Jamshed RunWget(mctx, &(app_ctx));
78276404edcSAsim Jamshed }
78376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
78476404edcSAsim Jamshed void *
RunMTCP(void * arg)78576404edcSAsim Jamshed RunMTCP(void *arg)
78676404edcSAsim Jamshed {
78776404edcSAsim Jamshed int core = *(int *)arg;
78876404edcSAsim Jamshed mctx_t mctx;
78976404edcSAsim Jamshed
79076404edcSAsim Jamshed mtcp_core_affinitize(core);
79176404edcSAsim Jamshed
79276404edcSAsim Jamshed /* mTCP Initialization */
79376404edcSAsim Jamshed mctx = mtcp_create_context(core);
79476404edcSAsim Jamshed if (!mctx) {
79576404edcSAsim Jamshed pthread_exit(NULL);
79676404edcSAsim Jamshed TRACE_ERROR("Failed to craete mtcp context.\n");
79776404edcSAsim Jamshed return NULL;
79876404edcSAsim Jamshed }
79976404edcSAsim Jamshed
80076404edcSAsim Jamshed /* Run application here */
80176404edcSAsim Jamshed RunApplication(mctx);
80276404edcSAsim Jamshed
80376404edcSAsim Jamshed /* mTCP Tear Down */
80476404edcSAsim Jamshed mtcp_destroy_context(mctx);
80576404edcSAsim Jamshed pthread_exit(NULL);
80676404edcSAsim Jamshed
80776404edcSAsim Jamshed return NULL;
80876404edcSAsim Jamshed }
80976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
81076404edcSAsim Jamshed int
main(int argc,char ** argv)81176404edcSAsim Jamshed main(int argc, char **argv)
81276404edcSAsim Jamshed {
81376404edcSAsim Jamshed int ret, i;
81476404edcSAsim Jamshed int cores[MAX_CPUS];
81576404edcSAsim Jamshed char *fname = "config/mos.conf";
81676404edcSAsim Jamshed
81776404edcSAsim Jamshed int opt;
81876404edcSAsim Jamshed while ((opt = getopt(argc, argv, "f:")) != -1) {
81976404edcSAsim Jamshed switch (opt) {
82076404edcSAsim Jamshed case 'f':
82176404edcSAsim Jamshed fname = optarg;
82276404edcSAsim Jamshed break;
82376404edcSAsim Jamshed default:
82476404edcSAsim Jamshed printf("Usage: %s [-f config_file]\n", argv[0]);
82576404edcSAsim Jamshed return 0;
82676404edcSAsim Jamshed }
82776404edcSAsim Jamshed
82876404edcSAsim Jamshed }
82976404edcSAsim Jamshed
83076404edcSAsim Jamshed core_limit = sysconf(_SC_NPROCESSORS_ONLN);
83176404edcSAsim Jamshed
83276404edcSAsim Jamshed ret = mtcp_init(fname);
83376404edcSAsim Jamshed if (ret) {
83476404edcSAsim Jamshed TRACE_ERROR("Failed to initialize mtcp.\n");
83576404edcSAsim Jamshed exit(EXIT_FAILURE);
83676404edcSAsim Jamshed }
83776404edcSAsim Jamshed
83876404edcSAsim Jamshed mtcp_getconf(&g_mcfg);
83976404edcSAsim Jamshed
84076404edcSAsim Jamshed core_limit = g_mcfg.num_cores;
84176404edcSAsim Jamshed
84276404edcSAsim Jamshed GlbInitWget();
84376404edcSAsim Jamshed
84476404edcSAsim Jamshed for (i = 0; i < core_limit; i++) {
84576404edcSAsim Jamshed cores[i] = i;
84676404edcSAsim Jamshed
84776404edcSAsim Jamshed /* Run mtcp thread */
84876404edcSAsim Jamshed if ((g_mcfg.cpu_mask & (1L << i)) &&
84976404edcSAsim Jamshed pthread_create(&mtcp_thread[i], NULL, RunMTCP, (void *)&cores[i])) {
85076404edcSAsim Jamshed perror("pthread_create");
85176404edcSAsim Jamshed TRACE_ERROR("Failed to create msg_test thread.\n");
85276404edcSAsim Jamshed exit(-1);
85376404edcSAsim Jamshed }
85476404edcSAsim Jamshed }
85576404edcSAsim Jamshed
85676404edcSAsim Jamshed for (i = 0; i < core_limit; i++) {
85776404edcSAsim Jamshed if (g_mcfg.cpu_mask & (1L << i))
85876404edcSAsim Jamshed pthread_join(mtcp_thread[i], NULL);
85976404edcSAsim Jamshed TRACE_INFO("Message test thread %d joined.\n", i);
86076404edcSAsim Jamshed }
86176404edcSAsim Jamshed
86276404edcSAsim Jamshed mtcp_destroy();
86376404edcSAsim Jamshed return 0;
86476404edcSAsim Jamshed }
86576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
866