PageRenderTime 57ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc

https://github.com/dkurochkin/squid
C++ | 386 lines | 264 code | 77 blank | 45 comment | 18 complexity | 48a4fbeaedc3c69f2311946cf83ccd2e MD5 | raw file
  1. /*
  2. * $Id$
  3. *
  4. * DEBUG: section 79 Disk IO Routines
  5. * AUTHOR: Robert Collins
  6. *
  7. * SQUID Web Proxy Cache http://www.squid-cache.org/
  8. * ----------------------------------------------------------
  9. *
  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.
  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. * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
  34. */
  35. #include "squid.h"
  36. #include "DiskThreadsDiskFile.h"
  37. #include "Store.h"
  38. #include "Generic.h"
  39. #include "DiskIO/IORequestor.h"
  40. #include "DiskIO/ReadRequest.h"
  41. #include "DiskIO/WriteRequest.h"
  42. /* === PUBLIC =========================================================== */
  43. CBDATA_CLASS_INIT(DiskThreadsDiskFile);
  44. void *
  45. DiskThreadsDiskFile::operator new (size_t)
  46. {
  47. CBDATA_INIT_TYPE(DiskThreadsDiskFile);
  48. DiskThreadsDiskFile *result = cbdataAlloc(DiskThreadsDiskFile);
  49. /*
  50. * We used to call squidaio_init() here, but if the first transaction
  51. * is to unlink a file (e.g., if Squid starts up over the disk space
  52. * limit) then "squidaio" won't be initialized yet.
  53. */
  54. return result;
  55. }
  56. void
  57. DiskThreadsDiskFile::operator delete(void *address)
  58. {
  59. DiskThreadsDiskFile *t = static_cast<DiskThreadsDiskFile *>(address);
  60. cbdataFree(t);
  61. }
  62. DiskThreadsDiskFile::DiskThreadsDiskFile(char const *aPath, DiskThreadsIOStrategy *anIO):fd(-1), errorOccured (false), IO(anIO),
  63. inProgressIOs (0)
  64. {
  65. assert (aPath);
  66. debugs(79, 3, "UFSFile::UFSFile: " << aPath);
  67. path_ = xstrdup (aPath);
  68. }
  69. DiskThreadsDiskFile::~DiskThreadsDiskFile()
  70. {
  71. safe_free (path_);
  72. doClose();
  73. }
  74. void
  75. DiskThreadsDiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback)
  76. {
  77. statCounter.syscalls.disk.opens++;
  78. #if !ASYNC_OPEN
  79. fd = file_open(path_, flags);
  80. if (fd < 0) {
  81. debugs(79, 3, "DiskThreadsDiskFile::open: got failure (" << errno << ")");
  82. errorOccured = true;
  83. return;
  84. }
  85. #endif
  86. Opening_FD++;
  87. ioRequestor = callback;
  88. ++inProgressIOs;
  89. #if ASYNC_OPEN
  90. aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this);
  91. #else
  92. openDone(fd, NULL, fd, 0);
  93. #endif
  94. }
  95. void
  96. DiskThreadsDiskFile::read(ReadRequest * request)
  97. {
  98. debugs(79, 3, "DiskThreadsDiskFile::read: " << this << ", size " << request->len);
  99. assert (fd > -1);
  100. assert (ioRequestor.getRaw());
  101. statCounter.syscalls.disk.reads++;
  102. ++inProgressIOs;
  103. #if ASYNC_READ
  104. aioRead(fd, request->offset, request->len, ReadDone, new IoResult<ReadRequest>(this, request));
  105. #else
  106. file_read(fd, request->buf, request->len, request->offset, ReadDone, new IoResult<ReadRequest>(this, request));
  107. #endif
  108. }
  109. void
  110. DiskThreadsDiskFile::create(int flags, mode_t mode, RefCount<IORequestor> callback)
  111. {
  112. statCounter.syscalls.disk.opens++;
  113. #if !ASYNC_CREATE
  114. int fd = file_open(path_, flags);
  115. if (fd < 0) {
  116. debugs(79, 3, "DiskThreadsDiskFile::create: got failure (" << errno << ")");
  117. errorOccured = true;
  118. return;
  119. }
  120. #endif
  121. Opening_FD++;
  122. ioRequestor = callback;
  123. ++inProgressIOs;
  124. #if ASYNC_CREATE
  125. aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this);
  126. #else
  127. openDone (fd, NULL, fd, 0);
  128. #endif
  129. }
  130. bool
  131. DiskThreadsDiskFile::error() const
  132. {
  133. return errorOccured;
  134. }
  135. void
  136. DiskThreadsDiskFile::OpenDone(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno)
  137. {
  138. DiskThreadsDiskFile *myFile = static_cast<DiskThreadsDiskFile *>(cbdata);
  139. myFile->openDone (fd, buf, aio_return, aio_errno);
  140. }
  141. void
  142. DiskThreadsDiskFile::openDone(int unused, const char *unused2, int anFD, int errflag)
  143. {
  144. debugs(79, 3, "DiskThreadsDiskFile::openDone: FD " << anFD << ", errflag " << errflag);
  145. Opening_FD--;
  146. fd = anFD;
  147. if (errflag || fd < 0) {
  148. errno = errflag;
  149. debugs(79, 0, "DiskThreadsDiskFile::openDone: " << xstrerror());
  150. debugs(79, 1, "\t" << path_);
  151. errorOccured = true;
  152. } else {
  153. store_open_disk_fd++;
  154. commSetCloseOnExec(fd);
  155. fd_open(fd, FD_FILE, path_);
  156. }
  157. IORequestor::Pointer t = ioRequestor;
  158. --inProgressIOs;
  159. t->ioCompletedNotification();
  160. debugs(79, 3, "DiskThreadsDiskFile::openDone: exiting");
  161. }
  162. void DiskThreadsDiskFile::doClose()
  163. {
  164. if (fd > -1) {
  165. statCounter.syscalls.disk.closes++;
  166. #if ASYNC_CLOSE
  167. aioClose(fd);
  168. fd_close(fd);
  169. #else
  170. aioCancel(fd);
  171. file_close(fd);
  172. #endif
  173. store_open_disk_fd--;
  174. fd = -1;
  175. }
  176. }
  177. void
  178. DiskThreadsDiskFile::close()
  179. {
  180. debugs(79, 3, "DiskThreadsDiskFile::close: " << this << " closing for " << ioRequestor.getRaw());
  181. if (!ioInProgress()) {
  182. doClose();
  183. assert (ioRequestor != NULL);
  184. ioRequestor->closeCompleted();
  185. return;
  186. } else {
  187. debugs(79,0,HERE << "DiskThreadsDiskFile::close: " <<
  188. "did NOT close because ioInProgress() is true. now what?");
  189. }
  190. }
  191. bool
  192. DiskThreadsDiskFile::canRead() const
  193. {
  194. debugs(79, 3, "DiskThreadsDiskFile::canRead: fd is " << fd);
  195. return fd > -1;
  196. }
  197. void
  198. DiskThreadsDiskFile::write(WriteRequest * writeRequest)
  199. {
  200. debugs(79, 3, "DiskThreadsDiskFile::write: FD " << fd);
  201. statCounter.syscalls.disk.writes++;
  202. ++inProgressIOs;
  203. #if ASYNC_WRITE
  204. aioWrite(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(this, writeRequest),
  205. writeRequest->free_func);
  206. #else
  207. file_write(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(this, writeRequest),
  208. writeRequest->free_func);
  209. #endif
  210. }
  211. bool
  212. DiskThreadsDiskFile::canWrite() const
  213. {
  214. return fd > -1;
  215. }
  216. bool
  217. DiskThreadsDiskFile::ioInProgress() const
  218. {
  219. return inProgressIOs > 0;
  220. }
  221. /* === STATIC =========================================================== */
  222. #if ASYNC_READ
  223. void
  224. DiskThreadsDiskFile::ReadDone(int fd, void *my_data, const char *buf, int len, int errflag)
  225. #else
  226. void
  227. DiskThreadsDiskFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
  228. #endif
  229. {
  230. IoResult<ReadRequest> * result = static_cast<IoResult<ReadRequest> *>(my_data);
  231. assert (result);
  232. result->file->readDone(fd, buf, len, errflag, result->request);
  233. delete result;
  234. }
  235. void
  236. DiskThreadsDiskFile::readDone(int rvfd, const char *buf, int len, int errflag, RefCount<ReadRequest> request)
  237. {
  238. debugs(79, 3, "DiskThreadsDiskFile::readDone: FD " << rvfd);
  239. assert (fd == rvfd);
  240. ssize_t rlen;
  241. if (errflag) {
  242. debugs(79, 3, "DiskThreadsDiskFile::readDone: got failure (" << errflag << ")");
  243. rlen = -1;
  244. } else {
  245. rlen = (ssize_t) len;
  246. }
  247. #if ASYNC_READ
  248. /* translate errflag from errno to Squid disk error */
  249. errno = errflag;
  250. if (errflag)
  251. errflag = DISK_ERROR;
  252. else
  253. errflag = DISK_OK;
  254. #else
  255. if (errflag == DISK_EOF)
  256. errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */
  257. #endif
  258. --inProgressIOs;
  259. ioRequestor->readCompleted(buf, rlen, errflag, request);
  260. }
  261. void
  262. DiskThreadsDiskFile::
  263. #if ASYNC_WRITE
  264. WriteDone(int fd, void *my_data, const char *buf, int len, int errflag)
  265. #else
  266. WriteDone(int fd, int errflag, size_t len, void *my_data)
  267. #endif
  268. {
  269. IoResult<WriteRequest> * result = static_cast<IoResult<WriteRequest> *>(my_data);
  270. assert (result);
  271. result->file->writeDone(fd, errflag, len, result->request);
  272. delete result;
  273. }
  274. void
  275. DiskThreadsDiskFile::writeDone(int rvfd, int errflag, size_t len, RefCount<WriteRequest> request)
  276. {
  277. assert (rvfd == fd);
  278. static int loop_detect = 0;
  279. #if ASYNC_WRITE
  280. /* Translate from errno to Squid disk error */
  281. if (errflag)
  282. errflag = errflag == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
  283. else
  284. errflag = DISK_OK;
  285. #endif
  286. debugs(79, 3, "DiskThreadsDiskFile::writeDone: FD " << fd << ", len " << len << ", err=" << errflag);
  287. assert(++loop_detect < 10);
  288. --inProgressIOs;
  289. ioRequestor->writeCompleted(errflag, len, request);
  290. --loop_detect;
  291. }
  292. /** \cond AUTODOCS-IGNORE */
  293. template <class RT>
  294. cbdata_type IoResult<RT>::CBDATA_IoResult = CBDATA_UNKNOWN;
  295. /** \endcond */
  296. template<class RT>
  297. void *
  298. IoResult<RT>::operator new(size_t unused)
  299. {
  300. CBDATA_INIT_TYPE(IoResult);
  301. IoResult<RT> *result = cbdataAlloc(IoResult);
  302. return result;
  303. }
  304. template <class RT>
  305. void
  306. IoResult<RT>::operator delete(void *address)
  307. {
  308. cbdataFree(address);
  309. }