]> git.ipfire.org Git - thirdparty/squid.git/blame - src/DiskIO/DiskThreads/aiops.cc
Added usage of configure results
[thirdparty/squid.git] / src / DiskIO / DiskThreads / aiops.cc
CommitLineData
cd748f27 1/*
985c86bc 2 * $Id: aiops.cc,v 1.7 2006/05/08 23:38:34 robertc Exp $
cd748f27 3 *
4 * DEBUG: section 43 AIOPS
5 * AUTHOR: Stewart Forster <slf@connect.com.au>
6 *
2b6662ba 7 * SQUID Web Proxy Cache http://www.squid-cache.org/
cd748f27 8 * ----------------------------------------------------------
9 *
2b6662ba 10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
cd748f27 18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 */
34
e4116bdb 35#ifndef _REENTRANT
36#error "_REENTRANT MUST be defined to build squid async io support."
37#endif
38
cd748f27 39#include "squid.h"
b9ae18aa 40#include "DiskThreads.h"
cd748f27 41
42#include <stdio.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <fcntl.h>
46#include <pthread.h>
47#include <errno.h>
48#include <dirent.h>
49#include <signal.h>
50#if HAVE_SCHED_H
51#include <sched.h>
52#endif
56410c89 53#include "CommIO.h"
985c86bc 54#include "SquidTime.h"
cd748f27 55
56#define RIDICULOUS_LENGTH 4096
57
c04d4f40 58enum _squidaio_thread_status {
cd748f27 59 _THREAD_STARTING = 0,
60 _THREAD_WAITING,
61 _THREAD_BUSY,
62 _THREAD_FAILED,
63 _THREAD_DONE
64};
c04d4f40 65typedef enum _squidaio_thread_status squidaio_thread_status;
cd748f27 66
62e76326 67typedef struct squidaio_request_t
68{
69
c04d4f40 70 struct squidaio_request_t *next;
71 squidaio_request_type request_type;
cd748f27 72 int cancelled;
73 char *path;
74 int oflag;
75 mode_t mode;
76 int fd;
77 char *bufferp;
cd748f27 78 int buflen;
79 off_t offset;
80 int whence;
81 int ret;
82 int err;
62e76326 83
cd748f27 84 struct stat *tmpstatp;
62e76326 85
cd748f27 86 struct stat *statp;
c04d4f40 87 squidaio_result_t *resultp;
62e76326 88}
89
90squidaio_request_t;
cd748f27 91
62e76326 92typedef struct squidaio_request_queue_t
93{
55f0e6f7 94 pthread_mutex_t mutex;
95 pthread_cond_t cond;
c04d4f40 96 squidaio_request_t *volatile head;
97 squidaio_request_t *volatile *volatile tailp;
55f0e6f7 98 unsigned long requests;
f0debecb 99 unsigned long blocked; /* main failed to lock the queue */
62e76326 100}
101
102squidaio_request_queue_t;
55f0e6f7 103
c04d4f40 104typedef struct squidaio_thread_t squidaio_thread_t;
62e76326 105
106struct squidaio_thread_t
107{
c04d4f40 108 squidaio_thread_t *next;
cd748f27 109 pthread_t thread;
c04d4f40 110 squidaio_thread_status status;
62e76326 111
c04d4f40 112 struct squidaio_request_t *current_req;
55f0e6f7 113 unsigned long requests;
114};
cd748f27 115
c04d4f40 116static void squidaio_queue_request(squidaio_request_t *);
117static void squidaio_cleanup_request(squidaio_request_t *);
118static void *squidaio_thread_loop(void *);
119static void squidaio_do_open(squidaio_request_t *);
120static void squidaio_do_read(squidaio_request_t *);
121static void squidaio_do_write(squidaio_request_t *);
122static void squidaio_do_close(squidaio_request_t *);
123static void squidaio_do_stat(squidaio_request_t *);
efa3acd1 124#if USE_TRUNCATE
c04d4f40 125static void squidaio_do_truncate(squidaio_request_t *);
efa3acd1 126#else
127static void squidaio_do_unlink(squidaio_request_t *);
128#endif
cd748f27 129#if AIO_OPENDIR
c04d4f40 130static void *squidaio_do_opendir(squidaio_request_t *);
cd748f27 131#endif
c04d4f40 132static void squidaio_debug(squidaio_request_t *);
133static void squidaio_poll_queues(void);
cd748f27 134
c04d4f40 135static squidaio_thread_t *threads = NULL;
136static int squidaio_initialised = 0;
cd748f27 137
55f0e6f7 138
58cd5bbd 139#define AIO_LARGE_BUFS 16384
140#define AIO_MEDIUM_BUFS AIO_LARGE_BUFS >> 1
141#define AIO_SMALL_BUFS AIO_LARGE_BUFS >> 2
142#define AIO_TINY_BUFS AIO_LARGE_BUFS >> 3
55f0e6f7 143#define AIO_MICRO_BUFS 128
58cd5bbd 144
b001e822 145static MemAllocatorProxy *squidaio_large_bufs = NULL; /* 16K */
146static MemAllocatorProxy *squidaio_medium_bufs = NULL; /* 8K */
147static MemAllocatorProxy *squidaio_small_bufs = NULL; /* 4K */
148static MemAllocatorProxy *squidaio_tiny_bufs = NULL; /* 2K */
149static MemAllocatorProxy *squidaio_micro_bufs = NULL; /* 128K */
58cd5bbd 150
cd748f27 151static int request_queue_len = 0;
b001e822 152static MemAllocatorProxy *squidaio_request_pool = NULL;
153static MemAllocatorProxy *squidaio_thread_pool = NULL;
c04d4f40 154static squidaio_request_queue_t request_queue;
62e76326 155
156static struct
157{
c04d4f40 158 squidaio_request_t *head, **tailp;
62e76326 159}
f0debecb 160
62e76326 161request_queue2 = {
162
163 NULL, &request_queue2.head
164 };
c04d4f40 165static squidaio_request_queue_t done_queue;
62e76326 166
167static struct
168{
c04d4f40 169 squidaio_request_t *head, **tailp;
62e76326 170}
f0debecb 171
62e76326 172done_requests = {
173
174 NULL, &done_requests.head
175 };
cd748f27 176static pthread_attr_t globattr;
5e5c622b 177#if HAVE_SCHED_H
62e76326 178
cd748f27 179static struct sched_param globsched;
5e5c622b 180#endif
cd748f27 181static pthread_t main_thread;
182
b001e822 183static MemAllocatorProxy *
c04d4f40 184squidaio_get_pool(int size)
58cd5bbd 185{
b001e822 186 MemAllocatorProxy *p;
62e76326 187
58cd5bbd 188 if (size <= AIO_LARGE_BUFS) {
62e76326 189 if (size <= AIO_MICRO_BUFS)
190 p = squidaio_micro_bufs;
191 else if (size <= AIO_TINY_BUFS)
192 p = squidaio_tiny_bufs;
193 else if (size <= AIO_SMALL_BUFS)
194 p = squidaio_small_bufs;
195 else if (size <= AIO_MEDIUM_BUFS)
196 p = squidaio_medium_bufs;
197 else
198 p = squidaio_large_bufs;
58cd5bbd 199 } else
62e76326 200 p = NULL;
201
58cd5bbd 202 return p;
203}
204
211f1d0b 205void *
c04d4f40 206squidaio_xmalloc(int size)
58cd5bbd 207{
208 void *p;
b001e822 209 MemAllocatorProxy *pool;
58cd5bbd 210
c04d4f40 211 if ((pool = squidaio_get_pool(size)) != NULL) {
b001e822 212 p = pool->alloc();
58cd5bbd 213 } else
62e76326 214 p = xmalloc(size);
58cd5bbd 215
216 return p;
217}
218
55f0e6f7 219static char *
c04d4f40 220squidaio_xstrdup(const char *str)
55f0e6f7 221{
222 char *p;
f0debecb 223 int len = strlen(str) + 1;
55f0e6f7 224
e6ccf245 225 p = (char *)squidaio_xmalloc(len);
55f0e6f7 226 strncpy(p, str, len);
227
228 return p;
229}
230
211f1d0b 231void
c04d4f40 232squidaio_xfree(void *p, int size)
58cd5bbd 233{
b001e822 234 MemAllocatorProxy *pool;
58cd5bbd 235
c04d4f40 236 if ((pool = squidaio_get_pool(size)) != NULL) {
b001e822 237 pool->free(p);
58cd5bbd 238 } else
62e76326 239 xfree(p);
58cd5bbd 240}
241
55f0e6f7 242static void
c04d4f40 243squidaio_xstrfree(char *str)
55f0e6f7 244{
b001e822 245 MemAllocatorProxy *pool;
f0debecb 246 int len = strlen(str) + 1;
55f0e6f7 247
c04d4f40 248 if ((pool = squidaio_get_pool(len)) != NULL) {
b001e822 249 pool->free(str);
55f0e6f7 250 } else
62e76326 251 xfree(str);
55f0e6f7 252}
253
d06925a4 254void
c04d4f40 255squidaio_init(void)
cd748f27 256{
257 int i;
c04d4f40 258 squidaio_thread_t *threadp;
cd748f27 259
c04d4f40 260 if (squidaio_initialised)
62e76326 261 return;
cd748f27 262
263 pthread_attr_init(&globattr);
62e76326 264
cd748f27 265#if HAVE_PTHREAD_ATTR_SETSCOPE
62e76326 266
cd748f27 267 pthread_attr_setscope(&globattr, PTHREAD_SCOPE_SYSTEM);
62e76326 268
cd748f27 269#endif
5e5c622b 270#if HAVE_SCHED_H
62e76326 271
cd748f27 272 globsched.sched_priority = 1;
62e76326 273
5e5c622b 274#endif
62e76326 275
cd748f27 276 main_thread = pthread_self();
62e76326 277
5e5c622b 278#if HAVE_SCHED_H && HAVE_PTHREAD_SETSCHEDPARAM
62e76326 279
cd748f27 280 pthread_setschedparam(main_thread, SCHED_OTHER, &globsched);
62e76326 281
cd748f27 282#endif
5e5c622b 283#if HAVE_SCHED_H
62e76326 284
cd748f27 285 globsched.sched_priority = 2;
62e76326 286
5e5c622b 287#endif
288#if HAVE_SCHED_H && HAVE_PTHREAD_ATTR_SETSCHEDPARAM
62e76326 289
cd748f27 290 pthread_attr_setschedparam(&globattr, &globsched);
62e76326 291
cd748f27 292#endif
293
55f0e6f7 294 /* Initialize request queue */
295 if (pthread_mutex_init(&(request_queue.mutex), NULL))
62e76326 296 fatal("Failed to create mutex");
297
55f0e6f7 298 if (pthread_cond_init(&(request_queue.cond), NULL))
62e76326 299 fatal("Failed to create condition variable");
300
55f0e6f7 301 request_queue.head = NULL;
62e76326 302
55f0e6f7 303 request_queue.tailp = &request_queue.head;
62e76326 304
55f0e6f7 305 request_queue.requests = 0;
62e76326 306
55f0e6f7 307 request_queue.blocked = 0;
308
309 /* Initialize done queue */
310 if (pthread_mutex_init(&(done_queue.mutex), NULL))
62e76326 311 fatal("Failed to create mutex");
312
55f0e6f7 313 if (pthread_cond_init(&(done_queue.cond), NULL))
62e76326 314 fatal("Failed to create condition variable");
315
55f0e6f7 316 done_queue.head = NULL;
62e76326 317
55f0e6f7 318 done_queue.tailp = &done_queue.head;
62e76326 319
55f0e6f7 320 done_queue.requests = 0;
62e76326 321
55f0e6f7 322 done_queue.blocked = 0;
cd748f27 323
55f0e6f7 324 /* Create threads and get them to sit in their wait loop */
b001e822 325 squidaio_thread_pool = new MemAllocatorProxy("aio_thread", sizeof(squidaio_thread_t));
62e76326 326
9fbbe256 327 assert(NUMTHREADS);
62e76326 328
cd748f27 329 for (i = 0; i < NUMTHREADS; i++) {
b001e822 330 threadp = (squidaio_thread_t *)squidaio_thread_pool->alloc();
62e76326 331 threadp->status = _THREAD_STARTING;
332 threadp->current_req = NULL;
333 threadp->requests = 0;
334 threadp->next = threads;
335 threads = threadp;
336
337 if (pthread_create(&threadp->thread, &globattr, squidaio_thread_loop, threadp)) {
338 fprintf(stderr, "Thread creation failed\n");
339 threadp->status = _THREAD_FAILED;
340 continue;
341 }
cd748f27 342 }
343
344 /* Create request pool */
b001e822 345 squidaio_request_pool = new MemAllocatorProxy("aio_request", sizeof(squidaio_request_t));
62e76326 346
b001e822 347 squidaio_large_bufs = new MemAllocatorProxy("squidaio_large_bufs", AIO_LARGE_BUFS);
62e76326 348
b001e822 349 squidaio_medium_bufs = new MemAllocatorProxy("squidaio_medium_bufs", AIO_MEDIUM_BUFS);
62e76326 350
b001e822 351 squidaio_small_bufs = new MemAllocatorProxy("squidaio_small_bufs", AIO_SMALL_BUFS);
62e76326 352
b001e822 353 squidaio_tiny_bufs = new MemAllocatorProxy("squidaio_tiny_bufs", AIO_TINY_BUFS);
62e76326 354
b001e822 355 squidaio_micro_bufs = new MemAllocatorProxy("squidaio_micro_bufs", AIO_MICRO_BUFS);
c04d4f40 356
357 squidaio_initialised = 1;
cd748f27 358}
359
d06925a4 360void
361squidaio_shutdown(void)
362{
363 if (!squidaio_initialised)
364 return;
365
366 /* This is the same as in squidaio_sync */
367 do {
368 squidaio_poll_queues();
369 } while (request_queue_len > 0);
370
371 CommIO::NotifyIOClose();
372
373 squidaio_initialised = 0;
374}
cd748f27 375
376static void *
c04d4f40 377squidaio_thread_loop(void *ptr)
cd748f27 378{
e6ccf245 379 squidaio_thread_t *threadp = (squidaio_thread_t *)ptr;
c04d4f40 380 squidaio_request_t *request;
e6ccf245 381 sigset_t newSig;
cd748f27 382
383 /*
384 * Make sure to ignore signals which may possibly get sent to
385 * the parent squid thread. Causes havoc with mutex's and
386 * condition waits otherwise
387 */
388
e6ccf245 389 sigemptyset(&newSig);
390 sigaddset(&newSig, SIGPIPE);
391 sigaddset(&newSig, SIGCHLD);
cd748f27 392#ifdef _SQUID_LINUX_THREADS_
62e76326 393
e6ccf245 394 sigaddset(&newSig, SIGQUIT);
395 sigaddset(&newSig, SIGTRAP);
cd748f27 396#else
62e76326 397
e6ccf245 398 sigaddset(&newSig, SIGUSR1);
399 sigaddset(&newSig, SIGUSR2);
cd748f27 400#endif
62e76326 401
e6ccf245 402 sigaddset(&newSig, SIGHUP);
403 sigaddset(&newSig, SIGTERM);
404 sigaddset(&newSig, SIGINT);
405 sigaddset(&newSig, SIGALRM);
406 pthread_sigmask(SIG_BLOCK, &newSig, NULL);
cd748f27 407
cd748f27 408 while (1) {
62e76326 409 threadp->current_req = request = NULL;
410 request = NULL;
411 /* Get a request to process */
412 threadp->status = _THREAD_WAITING;
413 pthread_mutex_lock(&request_queue.mutex);
414
415 while (!request_queue.head) {
416 pthread_cond_wait(&request_queue.cond, &request_queue.mutex);
417 }
418
419 request = request_queue.head;
420
421 if (request)
422 request_queue.head = request->next;
423
424 if (!request_queue.head)
425 request_queue.tailp = &request_queue.head;
426
427 pthread_mutex_unlock(&request_queue.mutex);
428
429 /* process the request */
430 threadp->status = _THREAD_BUSY;
431
432 request->next = NULL;
433
434 threadp->current_req = request;
435
436 errno = 0;
437
438 if (!request->cancelled) {
439 switch (request->request_type) {
440
441 case _AIO_OP_OPEN:
442 squidaio_do_open(request);
443 break;
444
445 case _AIO_OP_READ:
446 squidaio_do_read(request);
447 break;
448
449 case _AIO_OP_WRITE:
450 squidaio_do_write(request);
451 break;
452
453 case _AIO_OP_CLOSE:
454 squidaio_do_close(request);
455 break;
456
efa3acd1 457#if USE_TRUNCATE
62e76326 458
459 case _AIO_OP_TRUNCATE:
460 squidaio_do_truncate(request);
461 break;
efa3acd1 462#else
463
464 case _AIO_OP_UNLINK:
465 squidaio_do_unlink(request);
466 break;
467
468#endif
cd748f27 469#if AIO_OPENDIR /* Opendir not implemented yet */
62e76326 470
471 case _AIO_OP_OPENDIR:
472 squidaio_do_opendir(request);
473 break;
cd748f27 474#endif
62e76326 475
476 case _AIO_OP_STAT:
477 squidaio_do_stat(request);
478 break;
479
480 default:
481 request->ret = -1;
482 request->err = EINVAL;
483 break;
484 }
485 } else { /* cancelled */
486 request->ret = -1;
487 request->err = EINTR;
488 }
489
490 threadp->status = _THREAD_DONE;
491 /* put the request in the done queue */
492 pthread_mutex_lock(&done_queue.mutex);
493 *done_queue.tailp = request;
494 done_queue.tailp = &request->next;
495 pthread_mutex_unlock(&done_queue.mutex);
496 CommIO::NotifyIOCompleted();
497 threadp->requests++;
55f0e6f7 498 } /* while forever */
62e76326 499
cd748f27 500 return NULL;
c04d4f40 501} /* squidaio_thread_loop */
cd748f27 502
503static void
c04d4f40 504squidaio_queue_request(squidaio_request_t * request)
cd748f27 505{
cd748f27 506 static int high_start = 0;
99cce4cb 507 debug(43, 9) ("squidaio_queue_request: %p type=%d result=%p\n",
62e76326 508 request, request->request_type, request->resultp);
cd748f27 509 /* Mark it as not executed (failing result, no error) */
55f0e6f7 510 request->ret = -1;
511 request->err = 0;
512 /* Internal housekeeping */
513 request_queue_len += 1;
514 request->resultp->_data = request;
515 /* Play some tricks with the request_queue2 queue */
516 request->next = NULL;
62e76326 517
40173038 518 if (pthread_mutex_trylock(&request_queue.mutex) == 0) {
62e76326 519 if (request_queue2.head) {
520 /* Grab blocked requests */
521 *request_queue.tailp = request_queue2.head;
522 request_queue.tailp = request_queue2.tailp;
523 }
524
525 /* Enqueue request */
526 *request_queue.tailp = request;
527
528 request_queue.tailp = &request->next;
529
530 pthread_cond_signal(&request_queue.cond);
531
532 pthread_mutex_unlock(&request_queue.mutex);
533
534 if (request_queue2.head) {
535 /* Clear queue of blocked requests */
536 request_queue2.head = NULL;
537 request_queue2.tailp = &request_queue2.head;
538 }
40173038 539 } else {
62e76326 540 /* Oops, the request queue is blocked, use request_queue2 */
541 *request_queue2.tailp = request;
542 request_queue2.tailp = &request->next;
55f0e6f7 543 }
62e76326 544
55f0e6f7 545 if (request_queue2.head) {
62e76326 546 static int filter = 0;
547 static int filter_limit = 8;
548
549 if (++filter >= filter_limit) {
550 filter_limit += filter;
551 filter = 0;
552 debug(43, 1) ("squidaio_queue_request: WARNING - Queue congestion\n");
553 }
cd748f27 554 }
62e76326 555
cd748f27 556 /* Warn if out of threads */
55f0e6f7 557 if (request_queue_len > MAGIC1) {
62e76326 558 static int last_warn = 0;
559 static int queue_high, queue_low;
560
561 if (high_start == 0) {
562 high_start = squid_curtime;
563 queue_high = request_queue_len;
564 queue_low = request_queue_len;
565 }
566
567 if (request_queue_len > queue_high)
568 queue_high = request_queue_len;
569
570 if (request_queue_len < queue_low)
571 queue_low = request_queue_len;
572
573 if (squid_curtime >= (last_warn + 15) &&
574 squid_curtime >= (high_start + 5)) {
575 debug(43, 1) ("squidaio_queue_request: WARNING - Disk I/O overloading\n");
576
577 if (squid_curtime >= (high_start + 15))
578 debug(43, 1) ("squidaio_queue_request: Queue Length: current=%d, high=%d, low=%d, duration=%ld\n",
579 request_queue_len, queue_high, queue_low, (long int) (squid_curtime - high_start));
580
581 last_warn = squid_curtime;
582 }
cd748f27 583 } else {
62e76326 584 high_start = 0;
cd748f27 585 }
62e76326 586
55f0e6f7 587 /* Warn if seriously overloaded */
cd748f27 588 if (request_queue_len > RIDICULOUS_LENGTH) {
62e76326 589 debug(43, 0) ("squidaio_queue_request: Async request queue growing uncontrollably!\n");
590 debug(43, 0) ("squidaio_queue_request: Syncing pending I/O operations.. (blocking)\n");
591 squidaio_sync();
592 debug(43, 0) ("squidaio_queue_request: Synced\n");
cd748f27 593 }
c04d4f40 594} /* squidaio_queue_request */
cd748f27 595
cd748f27 596static void
c04d4f40 597squidaio_cleanup_request(squidaio_request_t * requestp)
cd748f27 598{
c04d4f40 599 squidaio_result_t *resultp = requestp->resultp;
cd748f27 600 int cancelled = requestp->cancelled;
601
602 /* Free allocated structures and copy data back to user space if the */
603 /* request hasn't been cancelled */
62e76326 604
cd748f27 605 switch (requestp->request_type) {
62e76326 606
cd748f27 607 case _AIO_OP_STAT:
62e76326 608
609 if (!cancelled && requestp->ret == 0)
610
611 xmemcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat));
612
613 squidaio_xfree(requestp->tmpstatp, sizeof(struct stat));
614
615 squidaio_xstrfree(requestp->path);
616
617 break;
618
cd748f27 619 case _AIO_OP_OPEN:
62e76326 620 if (cancelled && requestp->ret >= 0)
621 /* The open() was cancelled but completed */
622 close(requestp->ret);
623
624 squidaio_xstrfree(requestp->path);
625
626 break;
627
cd748f27 628 case _AIO_OP_CLOSE:
62e76326 629 if (cancelled && requestp->ret < 0)
630 /* The close() was cancelled and never got executed */
631 close(requestp->fd);
632
633 break;
634
cd748f27 635 case _AIO_OP_UNLINK:
62e76326 636
15a47d1d 637 case _AIO_OP_TRUNCATE:
62e76326 638
cd748f27 639 case _AIO_OP_OPENDIR:
62e76326 640 squidaio_xstrfree(requestp->path);
641
642 break;
643
cd748f27 644 case _AIO_OP_READ:
62e76326 645 break;
646
cd748f27 647 case _AIO_OP_WRITE:
62e76326 648 break;
649
cd748f27 650 default:
62e76326 651 break;
cd748f27 652 }
62e76326 653
cd748f27 654 if (resultp != NULL && !cancelled) {
62e76326 655 resultp->aio_return = requestp->ret;
656 resultp->aio_errno = requestp->err;
cd748f27 657 }
62e76326 658
b001e822 659 squidaio_request_pool->free(requestp);
c04d4f40 660} /* squidaio_cleanup_request */
cd748f27 661
662
663int
c04d4f40 664squidaio_cancel(squidaio_result_t * resultp)
cd748f27 665{
e6ccf245 666 squidaio_request_t *request = (squidaio_request_t *)resultp->_data;
cd748f27 667
55f0e6f7 668 if (request && request->resultp == resultp) {
62e76326 669 debug(43, 9) ("squidaio_cancel: %p type=%d result=%p\n",
670 request, request->request_type, request->resultp);
671 request->cancelled = 1;
672 request->resultp = NULL;
673 resultp->_data = NULL;
674 resultp->result_type = _AIO_OP_NONE;
675 return 0;
55f0e6f7 676 }
62e76326 677
cd748f27 678 return 1;
c04d4f40 679} /* squidaio_cancel */
cd748f27 680
681
682int
c04d4f40 683squidaio_open(const char *path, int oflag, mode_t mode, squidaio_result_t * resultp)
cd748f27 684{
c04d4f40 685 squidaio_request_t *requestp;
cd748f27 686
b001e822 687 requestp = (squidaio_request_t *)squidaio_request_pool->alloc();
62e76326 688
c04d4f40 689 requestp->path = (char *) squidaio_xstrdup(path);
62e76326 690
cd748f27 691 requestp->oflag = oflag;
62e76326 692
cd748f27 693 requestp->mode = mode;
62e76326 694
cd748f27 695 requestp->resultp = resultp;
62e76326 696
cd748f27 697 requestp->request_type = _AIO_OP_OPEN;
62e76326 698
cd748f27 699 requestp->cancelled = 0;
62e76326 700
12e137b0 701 resultp->result_type = _AIO_OP_OPEN;
cd748f27 702
c04d4f40 703 squidaio_queue_request(requestp);
62e76326 704
cd748f27 705 return 0;
706}
707
708
709static void
c04d4f40 710squidaio_do_open(squidaio_request_t * requestp)
cd748f27 711{
712 requestp->ret = open(requestp->path, requestp->oflag, requestp->mode);
713 requestp->err = errno;
714}
715
716
717int
c04d4f40 718squidaio_read(int fd, char *bufp, int bufs, off_t offset, int whence, squidaio_result_t * resultp)
cd748f27 719{
c04d4f40 720 squidaio_request_t *requestp;
cd748f27 721
b001e822 722 requestp = (squidaio_request_t *)squidaio_request_pool->alloc();
62e76326 723
cd748f27 724 requestp->fd = fd;
62e76326 725
cd748f27 726 requestp->bufferp = bufp;
62e76326 727
cd748f27 728 requestp->buflen = bufs;
62e76326 729
cd748f27 730 requestp->offset = offset;
62e76326 731
cd748f27 732 requestp->whence = whence;
62e76326 733
cd748f27 734 requestp->resultp = resultp;
62e76326 735
cd748f27 736 requestp->request_type = _AIO_OP_READ;
62e76326 737
cd748f27 738 requestp->cancelled = 0;
62e76326 739
12e137b0 740 resultp->result_type = _AIO_OP_READ;
cd748f27 741
c04d4f40 742 squidaio_queue_request(requestp);
62e76326 743
cd748f27 744 return 0;
745}
746
747
748static void
c04d4f40 749squidaio_do_read(squidaio_request_t * requestp)
cd748f27 750{
751 lseek(requestp->fd, requestp->offset, requestp->whence);
211f1d0b 752 requestp->ret = read(requestp->fd, requestp->bufferp, requestp->buflen);
cd748f27 753 requestp->err = errno;
754}
755
756
757int
c04d4f40 758squidaio_write(int fd, char *bufp, int bufs, off_t offset, int whence, squidaio_result_t * resultp)
cd748f27 759{
c04d4f40 760 squidaio_request_t *requestp;
cd748f27 761
b001e822 762 requestp = (squidaio_request_t *)squidaio_request_pool->alloc();
62e76326 763
cd748f27 764 requestp->fd = fd;
62e76326 765
d06925a4 766 requestp->bufferp = bufp;
62e76326 767
cd748f27 768 requestp->buflen = bufs;
62e76326 769
cd748f27 770 requestp->offset = offset;
62e76326 771
cd748f27 772 requestp->whence = whence;
62e76326 773
cd748f27 774 requestp->resultp = resultp;
62e76326 775
cd748f27 776 requestp->request_type = _AIO_OP_WRITE;
62e76326 777
cd748f27 778 requestp->cancelled = 0;
62e76326 779
12e137b0 780 resultp->result_type = _AIO_OP_WRITE;
cd748f27 781
c04d4f40 782 squidaio_queue_request(requestp);
62e76326 783
cd748f27 784 return 0;
785}
786
787
788static void
c04d4f40 789squidaio_do_write(squidaio_request_t * requestp)
cd748f27 790{
d06925a4 791 requestp->ret = write(requestp->fd, requestp->bufferp, requestp->buflen);
cd748f27 792 requestp->err = errno;
793}
794
795
796int
c04d4f40 797squidaio_close(int fd, squidaio_result_t * resultp)
cd748f27 798{
c04d4f40 799 squidaio_request_t *requestp;
cd748f27 800
b001e822 801 requestp = (squidaio_request_t *)squidaio_request_pool->alloc();
62e76326 802
cd748f27 803 requestp->fd = fd;
62e76326 804
cd748f27 805 requestp->resultp = resultp;
62e76326 806
cd748f27 807 requestp->request_type = _AIO_OP_CLOSE;
62e76326 808
cd748f27 809 requestp->cancelled = 0;
62e76326 810
12e137b0 811 resultp->result_type = _AIO_OP_CLOSE;
cd748f27 812
c04d4f40 813 squidaio_queue_request(requestp);
62e76326 814
cd748f27 815 return 0;
816}
817
818
819static void
c04d4f40 820squidaio_do_close(squidaio_request_t * requestp)
cd748f27 821{
822 requestp->ret = close(requestp->fd);
823 requestp->err = errno;
824}
825
826
827int
62e76326 828
c04d4f40 829squidaio_stat(const char *path, struct stat *sb, squidaio_result_t * resultp)
cd748f27 830{
c04d4f40 831 squidaio_request_t *requestp;
cd748f27 832
b001e822 833 requestp = (squidaio_request_t *)squidaio_request_pool->alloc();
62e76326 834
c04d4f40 835 requestp->path = (char *) squidaio_xstrdup(path);
62e76326 836
cd748f27 837 requestp->statp = sb;
62e76326 838
c04d4f40 839 requestp->tmpstatp = (struct stat *) squidaio_xmalloc(sizeof(struct stat));
62e76326 840
cd748f27 841 requestp->resultp = resultp;
62e76326 842
cd748f27 843 requestp->request_type = _AIO_OP_STAT;
62e76326 844
cd748f27 845 requestp->cancelled = 0;
62e76326 846
12e137b0 847 resultp->result_type = _AIO_OP_STAT;
cd748f27 848
c04d4f40 849 squidaio_queue_request(requestp);
62e76326 850
cd748f27 851 return 0;
852}
853
854
855static void
c04d4f40 856squidaio_do_stat(squidaio_request_t * requestp)
cd748f27 857{
858 requestp->ret = stat(requestp->path, requestp->tmpstatp);
859 requestp->err = errno;
860}
861
862
efa3acd1 863#if USE_TRUNCATE
cd748f27 864int
efa3acd1 865squidaio_truncate(const char *path, off_t length, squidaio_result_t * resultp)
cd748f27 866{
c04d4f40 867 squidaio_request_t *requestp;
cd748f27 868
b001e822 869 requestp = (squidaio_request_t *)squidaio_request_pool->alloc();
62e76326 870
efa3acd1 871 requestp->path = (char *) squidaio_xstrdup(path);
872
873 requestp->offset = length;
62e76326 874
cd748f27 875 requestp->resultp = resultp;
62e76326 876
efa3acd1 877 requestp->request_type = _AIO_OP_TRUNCATE;
62e76326 878
cd748f27 879 requestp->cancelled = 0;
62e76326 880
efa3acd1 881 resultp->result_type = _AIO_OP_TRUNCATE;
cd748f27 882
c04d4f40 883 squidaio_queue_request(requestp);
62e76326 884
cd748f27 885 return 0;
886}
887
888
889static void
efa3acd1 890squidaio_do_truncate(squidaio_request_t * requestp)
cd748f27 891{
efa3acd1 892 requestp->ret = truncate(requestp->path, requestp->offset);
cd748f27 893 requestp->err = errno;
894}
895
efa3acd1 896
897#else
15a47d1d 898int
efa3acd1 899squidaio_unlink(const char *path, squidaio_result_t * resultp)
15a47d1d 900{
c04d4f40 901 squidaio_request_t *requestp;
15a47d1d 902
b001e822 903 requestp = (squidaio_request_t *)squidaio_request_pool->alloc();
62e76326 904
efa3acd1 905 requestp->path = squidaio_xstrdup(path);
62e76326 906
15a47d1d 907 requestp->resultp = resultp;
62e76326 908
efa3acd1 909 requestp->request_type = _AIO_OP_UNLINK;
62e76326 910
15a47d1d 911 requestp->cancelled = 0;
62e76326 912
efa3acd1 913 resultp->result_type = _AIO_OP_UNLINK;
15a47d1d 914
c04d4f40 915 squidaio_queue_request(requestp);
62e76326 916
15a47d1d 917 return 0;
918}
919
920
921static void
efa3acd1 922squidaio_do_unlink(squidaio_request_t * requestp)
15a47d1d 923{
efa3acd1 924 requestp->ret = unlink(requestp->path);
15a47d1d 925 requestp->err = errno;
926}
927
efa3acd1 928#endif
cd748f27 929
930#if AIO_OPENDIR
c04d4f40 931/* XXX squidaio_opendir NOT implemented yet.. */
cd748f27 932
933int
c04d4f40 934squidaio_opendir(const char *path, squidaio_result_t * resultp)
cd748f27 935{
c04d4f40 936 squidaio_request_t *requestp;
cd748f27 937 int len;
938
b001e822 939 requestp = squidaio_request_pool->alloc();
62e76326 940
12e137b0 941 resultp->result_type = _AIO_OP_OPENDIR;
62e76326 942
cd748f27 943 return -1;
944}
945
946static void
c04d4f40 947squidaio_do_opendir(squidaio_request_t * requestp)
cd748f27 948{
949 /* NOT IMPLEMENTED */
950}
951
952#endif
953
55f0e6f7 954static void
c04d4f40 955squidaio_poll_queues(void)
55f0e6f7 956{
957 /* kick "overflow" request queue */
62e76326 958
55f0e6f7 959 if (request_queue2.head &&
62e76326 960 pthread_mutex_trylock(&request_queue.mutex) == 0) {
961 *request_queue.tailp = request_queue2.head;
962 request_queue.tailp = request_queue2.tailp;
963 pthread_cond_signal(&request_queue.cond);
964 pthread_mutex_unlock(&request_queue.mutex);
965 request_queue2.head = NULL;
966 request_queue2.tailp = &request_queue2.head;
55f0e6f7 967 }
62e76326 968
55f0e6f7 969 /* poll done queue */
970 if (done_queue.head && pthread_mutex_trylock(&done_queue.mutex) == 0) {
62e76326 971
972 struct squidaio_request_t *requests = done_queue.head;
973 done_queue.head = NULL;
974 done_queue.tailp = &done_queue.head;
975 pthread_mutex_unlock(&done_queue.mutex);
976 *done_requests.tailp = requests;
977 request_queue_len -= 1;
978
979 while (requests->next) {
980 requests = requests->next;
981 request_queue_len -= 1;
982 }
983
984 done_requests.tailp = &requests->next;
55f0e6f7 985 }
55f0e6f7 986}
cd748f27 987
c04d4f40 988squidaio_result_t *
989squidaio_poll_done(void)
cd748f27 990{
c04d4f40 991 squidaio_request_t *request;
992 squidaio_result_t *resultp;
cd748f27 993 int cancelled;
55f0e6f7 994 int polled = 0;
cd748f27 995
62e76326 996AIO_REPOLL:
55f0e6f7 997 request = done_requests.head;
62e76326 998
55f0e6f7 999 if (request == NULL && !polled) {
62e76326 1000 CommIO::ResetNotifications();
1001 squidaio_poll_queues();
1002 polled = 1;
1003 request = done_requests.head;
55f0e6f7 1004 }
62e76326 1005
55f0e6f7 1006 if (!request) {
62e76326 1007 return NULL;
cd748f27 1008 }
62e76326 1009
99cce4cb 1010 debug(43, 9) ("squidaio_poll_done: %p type=%d result=%p\n",
62e76326 1011 request, request->request_type, request->resultp);
55f0e6f7 1012 done_requests.head = request->next;
62e76326 1013
55f0e6f7 1014 if (!done_requests.head)
62e76326 1015 done_requests.tailp = &done_requests.head;
1016
55f0e6f7 1017 resultp = request->resultp;
62e76326 1018
55f0e6f7 1019 cancelled = request->cancelled;
62e76326 1020
c04d4f40 1021 squidaio_debug(request);
62e76326 1022
55f0e6f7 1023 debug(43, 5) ("DONE: %d -> %d\n", request->ret, request->err);
62e76326 1024
c04d4f40 1025 squidaio_cleanup_request(request);
62e76326 1026
cd748f27 1027 if (cancelled)
62e76326 1028 goto AIO_REPOLL;
1029
cd748f27 1030 return resultp;
c04d4f40 1031} /* squidaio_poll_done */
cd748f27 1032
1033int
c04d4f40 1034squidaio_operations_pending(void)
cd748f27 1035{
55f0e6f7 1036 return request_queue_len + (done_requests.head ? 1 : 0);
cd748f27 1037}
1038
1039int
c04d4f40 1040squidaio_sync(void)
cd748f27 1041{
55f0e6f7 1042 /* XXX This might take a while if the queue is large.. */
62e76326 1043
cd748f27 1044 do {
62e76326 1045 squidaio_poll_queues();
cd748f27 1046 } while (request_queue_len > 0);
62e76326 1047
c04d4f40 1048 return squidaio_operations_pending();
cd748f27 1049}
1050
1051int
c04d4f40 1052squidaio_get_queue_len(void)
cd748f27 1053{
1054 return request_queue_len;
1055}
1056
1057static void
c04d4f40 1058squidaio_debug(squidaio_request_t * request)
cd748f27 1059{
55f0e6f7 1060 switch (request->request_type) {
62e76326 1061
cd748f27 1062 case _AIO_OP_OPEN:
62e76326 1063 debug(43, 5) ("OPEN of %s to FD %d\n", request->path, request->ret);
1064 break;
1065
cd748f27 1066 case _AIO_OP_READ:
62e76326 1067 debug(43, 5) ("READ on fd: %d\n", request->fd);
1068 break;
1069
cd748f27 1070 case _AIO_OP_WRITE:
62e76326 1071 debug(43, 5) ("WRITE on fd: %d\n", request->fd);
1072 break;
1073
cd748f27 1074 case _AIO_OP_CLOSE:
62e76326 1075 debug(43, 5) ("CLOSE of fd: %d\n", request->fd);
1076 break;
1077
cd748f27 1078 case _AIO_OP_UNLINK:
62e76326 1079 debug(43, 5) ("UNLINK of %s\n", request->path);
1080 break;
1081
15a47d1d 1082 case _AIO_OP_TRUNCATE:
62e76326 1083 debug(43, 5) ("UNLINK of %s\n", request->path);
1084 break;
1085
cd748f27 1086 default:
62e76326 1087 break;
cd748f27 1088 }
1089}
b0465494 1090
1091void
1092squidaio_stats(StoreEntry * sentry)
1093{
1094 squidaio_thread_t *threadp;
1095 int i;
1096
1097 if (!squidaio_initialised)
1098 return;
1099
1100 storeAppendPrintf(sentry, "\n\nThreads Status:\n");
1101
1102 storeAppendPrintf(sentry, "#\tID\t# Requests\n");
1103
1104 threadp = threads;
1105
1106 for (i = 0; i < NUMTHREADS; i++) {
691aef5a 1107 storeAppendPrintf(sentry, "%i\t0x%lx\t%ld\n", i + 1, (unsigned long)threadp->thread, threadp->requests);
b0465494 1108 threadp = threadp->next;
1109 }
1110}