async_io.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:10k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: async_io.c,v 1.31 1999/02/01 05:57:05 wessels Exp $
  3.  *
  4.  * DEBUG: section 32    Asynchronous Disk I/O
  5.  * AUTHOR: Pete Bentley <pete@demon.net>
  6.  * AUTHOR: Stewart Forster <slf@connect.com.au>
  7.  *
  8.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  9.  * ----------------------------------------------------------
  10.  *
  11.  *  Squid is the result of efforts by numerous individuals from the
  12.  *  Internet community.  Development is led by Duane Wessels of the
  13.  *  National Laboratory for Applied Network Research and funded by the
  14.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  15.  *  Duane Wessels and the University of California San Diego.  Please
  16.  *  see the COPYRIGHT file for full details.  Squid incorporates
  17.  *  software developed and/or copyrighted by other sources.  Please see
  18.  *  the CREDITS file for full details.
  19.  *
  20.  *  This program is free software; you can redistribute it and/or modify
  21.  *  it under the terms of the GNU General Public License as published by
  22.  *  the Free Software Foundation; either version 2 of the License, or
  23.  *  (at your option) any later version.
  24.  *  
  25.  *  This program is distributed in the hope that it will be useful,
  26.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  27.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28.  *  GNU General Public License for more details.
  29.  *  
  30.  *  You should have received a copy of the GNU General Public License
  31.  *  along with this program; if not, write to the Free Software
  32.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  33.  *
  34.  */
  35. #include "squid.h"
  36. #if USE_ASYNC_IO
  37. #define _AIO_OPEN 0
  38. #define _AIO_READ 1
  39. #define _AIO_WRITE 2
  40. #define _AIO_CLOSE 3
  41. #define _AIO_UNLINK 4
  42. #define _AIO_OPENDIR 5
  43. #define _AIO_STAT 6
  44. typedef struct aio_ctrl_t {
  45.     struct aio_ctrl_t *next;
  46.     int fd;
  47.     int operation;
  48.     AIOCB *done_handler;
  49.     void *done_handler_data;
  50.     aio_result_t result;
  51.     void *tag;
  52. } aio_ctrl_t;
  53. struct {
  54.     int open;
  55.     int close;
  56.     int cancel;
  57.     int write;
  58.     int read;
  59.     int stat;
  60.     int unlink;
  61.     int check_callback;
  62. } aio_counts;
  63. typedef struct aio_unlinkq_t {
  64.     char *path;
  65.     struct aio_unlinkq_t *next;
  66. } aio_unlinkq_t;
  67. static aio_ctrl_t *used_list = NULL;
  68. static int initialised = 0;
  69. static OBJH aioStats;
  70. static MemPool *aio_ctrl_pool;
  71. static void
  72. aioInit()
  73. {
  74.     if (initialised)
  75. return;
  76.     aio_ctrl_pool = memPoolCreate("aio_ctrl", sizeof(aio_ctrl_t));
  77.     cachemgrRegister("aio_counts", "Async IO Function Counters",
  78. aioStats, 0, 1);
  79.     initialised = 1;
  80. }
  81. void
  82. aioOpen(const char *path, int oflag, mode_t mode, AIOCB * callback, void *callback_data, void *tag)
  83. {
  84.     aio_ctrl_t *ctrlp;
  85.     int ret;
  86.     if (!initialised)
  87. aioInit();
  88.     aio_counts.open++;
  89.     ctrlp = memPoolAlloc(aio_ctrl_pool);
  90.     ctrlp->fd = -2;
  91.     ctrlp->tag = tag;
  92.     ctrlp->done_handler = callback;
  93.     ctrlp->done_handler_data = callback_data;
  94.     ctrlp->operation = _AIO_OPEN;
  95.     if (aio_open(path, oflag, mode, &(ctrlp->result)) < 0) {
  96. ret = open(path, oflag, mode);
  97. if (callback)
  98.     (callback) (ctrlp->fd, callback_data, ret, errno);
  99. memPoolFree(aio_ctrl_pool, ctrlp);
  100. return;
  101.     }
  102.     ctrlp->next = used_list;
  103.     used_list = ctrlp;
  104.     return;
  105. }
  106. void
  107. aioClose(int fd)
  108. {
  109.     aio_ctrl_t *ctrlp;
  110.     if (!initialised)
  111. aioInit();
  112.     aio_counts.close++;
  113.     aioCancel(fd, NULL);
  114.     ctrlp = memPoolAlloc(aio_ctrl_pool);
  115.     ctrlp->fd = fd;
  116.     ctrlp->tag = NULL;
  117.     ctrlp->done_handler = NULL;
  118.     ctrlp->done_handler_data = NULL;
  119.     ctrlp->operation = _AIO_CLOSE;
  120.     if (aio_close(fd, &(ctrlp->result)) < 0) {
  121. close(fd); /* Can't create thread - do a normal close */
  122. memPoolFree(aio_ctrl_pool, ctrlp);
  123. fd_was_closed(fd);
  124. return;
  125.     }
  126.     ctrlp->next = used_list;
  127.     used_list = ctrlp;
  128.     return;
  129. }
  130. void
  131. aioCancel(int fd, void *tag)
  132. {
  133.     aio_ctrl_t *curr;
  134.     aio_ctrl_t *prev;
  135.     aio_ctrl_t *next;
  136.     if (!initialised)
  137. aioInit();
  138.     aio_counts.cancel++;
  139.     prev = NULL;
  140.     curr = used_list;
  141.     for (curr = used_list;; curr = next) {
  142. while (curr != NULL) {
  143.     if (curr->fd == fd)
  144. break;
  145.     if (tag != NULL && curr->tag == tag)
  146. break;
  147.     prev = curr;
  148.     curr = curr->next;
  149. }
  150. if (curr == NULL)
  151.     break;
  152. aio_cancel(&(curr->result));
  153. if (curr->done_handler)
  154.     (curr->done_handler) (fd, curr->done_handler_data, -2, -2);
  155. next = curr->next;
  156. if (prev == NULL)
  157.     used_list = next;
  158. else
  159.     prev->next = next;
  160. memPoolFree(aio_ctrl_pool, curr);
  161.     }
  162. }
  163. void
  164. aioWrite(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data)
  165. {
  166.     aio_ctrl_t *ctrlp;
  167.     int seekmode;
  168.     if (!initialised)
  169. aioInit();
  170.     aio_counts.write++;
  171.     for (ctrlp = used_list; ctrlp != NULL; ctrlp = ctrlp->next)
  172. if (ctrlp->fd == fd)
  173.     break;
  174.     if (ctrlp != NULL) {
  175. errno = EWOULDBLOCK;
  176. if (callback)
  177.     (callback) (fd, callback_data, -1, errno);
  178. return;
  179.     }
  180.     ctrlp = memPoolAlloc(aio_ctrl_pool);
  181.     ctrlp->fd = fd;
  182.     ctrlp->tag = NULL;
  183.     ctrlp->done_handler = callback;
  184.     ctrlp->done_handler_data = callback_data;
  185.     ctrlp->operation = _AIO_WRITE;
  186.     if (offset >= 0)
  187. seekmode = SEEK_SET;
  188.     else {
  189. seekmode = SEEK_END;
  190. offset = 0;
  191.     }
  192.     if (aio_write(fd, bufp, len, offset, seekmode, &(ctrlp->result)) < 0) {
  193. if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL)
  194.     errno = EWOULDBLOCK;
  195. if (callback)
  196.     (callback) (fd, callback_data, -1, errno);
  197. memPoolFree(aio_ctrl_pool, ctrlp);
  198. return;
  199.     }
  200.     ctrlp->next = used_list;
  201.     used_list = ctrlp;
  202.     return;
  203. } /* aioWrite */
  204. void
  205. aioRead(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data)
  206. {
  207.     aio_ctrl_t *ctrlp;
  208.     int seekmode;
  209.     if (!initialised)
  210. aioInit();
  211.     aio_counts.read++;
  212.     for (ctrlp = used_list; ctrlp != NULL; ctrlp = ctrlp->next)
  213. if (ctrlp->fd == fd)
  214.     break;
  215.     if (ctrlp != NULL) {
  216. errno = EWOULDBLOCK;
  217. if (callback)
  218.     (callback) (fd, callback_data, -1, errno);
  219. return;
  220.     }
  221.     ctrlp = memPoolAlloc(aio_ctrl_pool);
  222.     ctrlp->fd = fd;
  223.     ctrlp->tag = NULL;
  224.     ctrlp->done_handler = callback;
  225.     ctrlp->done_handler_data = callback_data;
  226.     ctrlp->operation = _AIO_READ;
  227.     if (offset >= 0)
  228. seekmode = SEEK_SET;
  229.     else {
  230. seekmode = SEEK_CUR;
  231. offset = 0;
  232.     }
  233.     if (aio_read(fd, bufp, len, offset, seekmode, &(ctrlp->result)) < 0) {
  234. if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL)
  235.     errno = EWOULDBLOCK;
  236. if (callback)
  237.     (callback) (fd, callback_data, -1, errno);
  238. memPoolFree(aio_ctrl_pool, ctrlp);
  239. return;
  240.     }
  241.     ctrlp->next = used_list;
  242.     used_list = ctrlp;
  243.     return;
  244. } /* aioRead */
  245. void
  246. aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data, void *tag)
  247. {
  248.     aio_ctrl_t *ctrlp;
  249.     if (!initialised)
  250. aioInit();
  251.     aio_counts.stat++;
  252.     ctrlp = memPoolAlloc(aio_ctrl_pool);
  253.     ctrlp->fd = -2;
  254.     ctrlp->tag = tag;
  255.     ctrlp->done_handler = callback;
  256.     ctrlp->done_handler_data = callback_data;
  257.     ctrlp->operation = _AIO_STAT;
  258.     if (aio_stat(path, sb, &(ctrlp->result)) < 0) {
  259. if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL)
  260.     errno = EWOULDBLOCK;
  261. if (callback)
  262.     (callback) (ctrlp->fd, callback_data, -1, errno);
  263. memPoolFree(aio_ctrl_pool, ctrlp);
  264. return;
  265.     }
  266.     ctrlp->next = used_list;
  267.     used_list = ctrlp;
  268.     return;
  269. } /* aioStat */
  270. void
  271. aioUnlink(const char *pathname, AIOCB * callback, void *callback_data)
  272. {
  273.     aio_ctrl_t *ctrlp;
  274.     char *path;
  275.     if (!initialised)
  276. aioInit();
  277.     aio_counts.unlink++;
  278.     ctrlp = memPoolAlloc(aio_ctrl_pool);
  279.     ctrlp->fd = -2;
  280.     ctrlp->done_handler = callback;
  281.     ctrlp->done_handler_data = callback_data;
  282.     ctrlp->operation = _AIO_UNLINK;
  283.     path = xstrdup(pathname);
  284.     if (aio_unlink(path, &(ctrlp->result)) < 0) {
  285. int ret = unlink(path);
  286. (callback) (ctrlp->fd, callback_data, ret, errno);
  287. memPoolFree(aio_ctrl_pool, ctrlp);
  288. xfree(path);
  289. return;
  290.     }
  291.     ctrlp->next = used_list;
  292.     used_list = ctrlp;
  293.     xfree(path);
  294. } /* aioUnlink */
  295. void
  296. aioCheckCallbacks()
  297. {
  298.     aio_result_t *resultp;
  299.     aio_ctrl_t *ctrlp;
  300.     aio_ctrl_t *prev;
  301.     if (!initialised)
  302. aioInit();
  303.     aio_counts.check_callback++;
  304.     for (;;) {
  305. if ((resultp = aio_poll_done()) == NULL)
  306.     break;
  307. prev = NULL;
  308. for (ctrlp = used_list; ctrlp != NULL; prev = ctrlp, ctrlp = ctrlp->next)
  309.     if (&(ctrlp->result) == resultp)
  310. break;
  311. if (ctrlp == NULL)
  312.     continue;
  313. if (prev == NULL)
  314.     used_list = ctrlp->next;
  315. else
  316.     prev->next = ctrlp->next;
  317. if (ctrlp->done_handler)
  318.     (ctrlp->done_handler) (ctrlp->fd, ctrlp->done_handler_data,
  319. ctrlp->result.aio_return, ctrlp->result.aio_errno);
  320. if (ctrlp->operation == _AIO_CLOSE)
  321.     fd_was_closed(ctrlp->fd);
  322. memPoolFree(aio_ctrl_pool, ctrlp);
  323.     }
  324. }
  325. void
  326. aioStats(StoreEntry * sentry)
  327. {
  328.     storeAppendPrintf(sentry, "ASYNC IO Counters:n");
  329.     storeAppendPrintf(sentry, "opent%dn", aio_counts.open);
  330.     storeAppendPrintf(sentry, "closet%dn", aio_counts.close);
  331.     storeAppendPrintf(sentry, "cancelt%dn", aio_counts.cancel);
  332.     storeAppendPrintf(sentry, "writet%dn", aio_counts.write);
  333.     storeAppendPrintf(sentry, "readt%dn", aio_counts.read);
  334.     storeAppendPrintf(sentry, "statt%dn", aio_counts.stat);
  335.     storeAppendPrintf(sentry, "unlinkt%dn", aio_counts.unlink);
  336.     storeAppendPrintf(sentry, "check_callbackt%dn", aio_counts.check_callback);
  337. }
  338. /* Flush all pending I/O */
  339. void
  340. aioSync(void)
  341. {
  342.     if (!initialised)
  343. return; /* nothing to do then */
  344.     /* Flush all pending operations */
  345.     debug(32, 1) ("aioSync: flushing pending I/O operationsn");
  346.     do {
  347. aioCheckCallbacks();
  348.     } while (aio_operations_pending());
  349.     debug(32, 1) ("aioSync: donen");
  350. }
  351. #endif /* USE_ASYNC_IO */