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