PageRenderTime 27ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/DiskIO/DiskDaemon/DiskdFile.cc

https://github.com/dkurochkin/squid
C++ | 427 lines | 323 code | 62 blank | 42 comment | 23 complexity | c886b0d5a0e8a2a861b8104c534bb20d MD5 | raw file
  1. /*
  2. * $Id$
  3. *
  4. * DEBUG: section 79 Squid-side DISKD I/O functions.
  5. * AUTHOR: Duane Wessels
  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 <sys/ipc.h>
  37. #include <sys/msg.h>
  38. #include <sys/shm.h>
  39. #include "DiskdFile.h"
  40. #include "ConfigOption.h"
  41. #include "diomsg.h"
  42. #include "DiskdIOStrategy.h"
  43. #include "DiskIO/IORequestor.h"
  44. #include "DiskIO/ReadRequest.h"
  45. #include "DiskIO/WriteRequest.h"
  46. CBDATA_CLASS_INIT(DiskdFile);
  47. void *
  48. DiskdFile::operator new(size_t unused)
  49. {
  50. CBDATA_INIT_TYPE(DiskdFile);
  51. DiskdFile *result = cbdataAlloc(DiskdFile);
  52. /* Mark result as being owned - we want the refcounter to do the delete
  53. * call */
  54. debugs(79, 3, "diskdFile with base " << result << " allocating");
  55. return result;
  56. }
  57. void
  58. DiskdFile::operator delete(void *address)
  59. {
  60. DiskdFile *t = static_cast<DiskdFile *>(address);
  61. debugs(79, 3, "diskdFile with base " << t << " deleting");
  62. cbdataFree(t);
  63. }
  64. DiskdFile::DiskdFile(char const *aPath, DiskdIOStrategy *anIO) : errorOccured (false), IO(anIO),
  65. inProgressIOs (0)
  66. {
  67. assert (aPath);
  68. debugs(79, 3, "DiskdFile::DiskdFile: " << aPath);
  69. path_ = xstrdup (aPath);
  70. id = diskd_stats.sio_id++;
  71. }
  72. DiskdFile::~DiskdFile()
  73. {
  74. assert (inProgressIOs == 0);
  75. safe_free (path_);
  76. }
  77. void
  78. DiskdFile::open(int flags, mode_t aMode, RefCount< IORequestor > callback)
  79. {
  80. debugs(79, 3, "DiskdFile::open: " << this << " opening for " << callback.getRaw());
  81. assert (ioRequestor.getRaw() == NULL);
  82. ioRequestor = callback;
  83. assert (callback.getRaw());
  84. mode = flags;
  85. ssize_t shm_offset;
  86. char *buf = (char *)IO->shm.get(&shm_offset);
  87. xstrncpy(buf, path_, SHMBUF_BLKSZ);
  88. ioAway();
  89. int x = IO->send(_MQD_OPEN,
  90. id,
  91. this,
  92. strlen(buf) + 1,
  93. mode,
  94. shm_offset,
  95. NULL);
  96. if (x < 0) {
  97. ioCompleted();
  98. errorOccured = true;
  99. // IO->shm.put (shm_offset);
  100. ioRequestor->ioCompletedNotification();
  101. ioRequestor = NULL;
  102. }
  103. diskd_stats.open.ops++;
  104. }
  105. void
  106. DiskdFile::create(int flags, mode_t aMode, RefCount< IORequestor > callback)
  107. {
  108. debugs(79, 3, "DiskdFile::create: " << this << " creating for " << callback.getRaw());
  109. assert (ioRequestor.getRaw() == NULL);
  110. ioRequestor = callback;
  111. assert (callback.getRaw());
  112. mode = flags;
  113. ssize_t shm_offset;
  114. char *buf = (char *)IO->shm.get(&shm_offset);
  115. xstrncpy(buf, path_, SHMBUF_BLKSZ);
  116. ioAway();
  117. int x = IO->send(_MQD_CREATE,
  118. id,
  119. this,
  120. strlen(buf) + 1,
  121. mode,
  122. shm_offset,
  123. NULL);
  124. if (x < 0) {
  125. ioCompleted();
  126. errorOccured = true;
  127. // IO->shm.put (shm_offset);
  128. debugs(79, 1, "storeDiskdSend CREATE: " << xstrerror());
  129. notifyClient();
  130. ioRequestor = NULL;
  131. return;
  132. }
  133. diskd_stats.create.ops++;
  134. }
  135. void
  136. DiskdFile::read(ReadRequest *aRead)
  137. {
  138. assert (ioRequestor.getRaw() != NULL);
  139. ssize_t shm_offset;
  140. char *rbuf = (char *)IO->shm.get(&shm_offset);
  141. assert(rbuf);
  142. ioAway();
  143. int x = IO->send(_MQD_READ,
  144. id,
  145. this,
  146. aRead->len,
  147. aRead->offset,
  148. shm_offset,
  149. aRead);
  150. if (x < 0) {
  151. ioCompleted();
  152. errorOccured = true;
  153. // IO->shm.put (shm_offset);
  154. debugs(79, 1, "storeDiskdSend READ: " << xstrerror());
  155. notifyClient();
  156. ioRequestor = NULL;
  157. return;
  158. }
  159. diskd_stats.read.ops++;
  160. }
  161. void
  162. DiskdFile::close()
  163. {
  164. debugs(79, 3, "DiskdFile::close: " << this << " closing for " << ioRequestor.getRaw());
  165. assert (ioRequestor.getRaw());
  166. ioAway();
  167. int x = IO->send(_MQD_CLOSE,
  168. id,
  169. this,
  170. 0,
  171. 0,
  172. -1,
  173. NULL);
  174. if (x < 0) {
  175. ioCompleted();
  176. errorOccured = true;
  177. debugs(79, 1, "storeDiskdSend CLOSE: " << xstrerror());
  178. notifyClient();
  179. ioRequestor = NULL;
  180. return;
  181. }
  182. diskd_stats.close.ops++;
  183. }
  184. bool
  185. DiskdFile::error() const
  186. {
  187. return errorOccured;
  188. }
  189. bool
  190. DiskdFile::canRead() const
  191. {
  192. return !error();
  193. }
  194. bool
  195. DiskdFile::canNotifyClient() const
  196. {
  197. if (!ioRequestor.getRaw()) {
  198. debugs(79, 3, "DiskdFile::canNotifyClient: No ioRequestor to notify");
  199. return false;
  200. }
  201. return true;
  202. }
  203. void
  204. DiskdFile::notifyClient()
  205. {
  206. if (!canNotifyClient()) {
  207. return;
  208. }
  209. ioRequestor->ioCompletedNotification();
  210. }
  211. void
  212. DiskdFile::completed(diomsg *M)
  213. {
  214. assert (M->newstyle);
  215. switch (M->mtype) {
  216. case _MQD_OPEN:
  217. openDone(M);
  218. break;
  219. case _MQD_CREATE:
  220. createDone(M);
  221. break;
  222. case _MQD_CLOSE:
  223. closeDone(M);
  224. break;
  225. case _MQD_READ:
  226. readDone(M);
  227. break;
  228. case _MQD_WRITE:
  229. writeDone(M);
  230. break;
  231. case _MQD_UNLINK:
  232. assert (0);
  233. break;
  234. default:
  235. assert(0);
  236. break;
  237. }
  238. }
  239. void
  240. DiskdFile::openDone(diomsg *M)
  241. {
  242. statCounter.syscalls.disk.opens++;
  243. debugs(79, 3, "storeDiskdOpenDone: status " << M->status);
  244. if (M->status < 0) {
  245. diskd_stats.open.fail++;
  246. errorOccured = true;
  247. } else {
  248. diskd_stats.open.success++;
  249. }
  250. ioCompleted();
  251. notifyClient();
  252. }
  253. void
  254. DiskdFile::createDone(diomsg *M)
  255. {
  256. statCounter.syscalls.disk.opens++;
  257. debugs(79, 3, "storeDiskdCreateDone: status " << M->status);
  258. if (M->status < 0) {
  259. diskd_stats.create.fail++;
  260. errorOccured = true;
  261. } else {
  262. diskd_stats.create.success++;
  263. }
  264. ioCompleted();
  265. notifyClient();
  266. }
  267. void
  268. DiskdFile::write(WriteRequest *aRequest)
  269. {
  270. debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len);
  271. ssize_t shm_offset;
  272. char *sbuf = (char *)IO->shm.get(&shm_offset);
  273. memcpy(sbuf, aRequest->buf, aRequest->len);
  274. if (aRequest->free_func)
  275. aRequest->free_func(const_cast<char *>(aRequest->buf));
  276. ioAway();
  277. int x = IO->send(_MQD_WRITE,
  278. id,
  279. this,
  280. aRequest->len,
  281. aRequest->offset,
  282. shm_offset,
  283. aRequest);
  284. if (x < 0) {
  285. ioCompleted();
  286. errorOccured = true;
  287. debugs(79, 1, "storeDiskdSend WRITE: " << xstrerror());
  288. // IO->shm.put (shm_offset);
  289. notifyClient();
  290. ioRequestor = NULL;
  291. return;
  292. }
  293. diskd_stats.write.ops++;
  294. }
  295. void
  296. DiskdFile::ioAway()
  297. {
  298. ++inProgressIOs;
  299. }
  300. void
  301. DiskdFile::ioCompleted()
  302. {
  303. --inProgressIOs;
  304. }
  305. void
  306. DiskdFile::closeDone(diomsg * M)
  307. {
  308. statCounter.syscalls.disk.closes++;
  309. debugs(79, 3, "DiskdFile::closeDone: status " << M->status);
  310. if (M->status < 0) {
  311. diskd_stats.close.fail++;
  312. errorOccured = true;
  313. } else {
  314. diskd_stats.close.success++;
  315. }
  316. ioCompleted();
  317. if (canNotifyClient())
  318. ioRequestor->closeCompleted();
  319. ioRequestor = NULL;
  320. }
  321. void
  322. DiskdFile::readDone(diomsg * M)
  323. {
  324. statCounter.syscalls.disk.reads++;
  325. debugs(79, 3, "DiskdFile::readDone: status " << M->status);
  326. assert (M->requestor);
  327. ReadRequest::Pointer readRequest = dynamic_cast<ReadRequest *>(M->requestor);
  328. /* remove the free protection */
  329. readRequest->RefCountDereference();
  330. if (M->status < 0) {
  331. diskd_stats.read.fail++;
  332. ioCompleted();
  333. errorOccured = true;
  334. ioRequestor->readCompleted(NULL, -1, DISK_ERROR, readRequest);
  335. return;
  336. }
  337. diskd_stats.read.success++;
  338. ioCompleted();
  339. ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK, readRequest);
  340. }
  341. void
  342. DiskdFile::writeDone(diomsg *M)
  343. {
  344. statCounter.syscalls.disk.writes++;
  345. debugs(79, 3, "storeDiskdWriteDone: status " << M->status);
  346. assert (M->requestor);
  347. WriteRequest::Pointer writeRequest = dynamic_cast<WriteRequest *>(M->requestor);
  348. /* remove the free protection */
  349. writeRequest->RefCountDereference();
  350. if (M->status < 0) {
  351. errorOccured = true;
  352. diskd_stats.write.fail++;
  353. ioCompleted();
  354. ioRequestor->writeCompleted (DISK_ERROR,0, writeRequest);
  355. return;
  356. }
  357. diskd_stats.write.success++;
  358. ioCompleted();
  359. ioRequestor->writeCompleted (DISK_OK,M->status, writeRequest);
  360. }
  361. bool
  362. DiskdFile::ioInProgress()const
  363. {
  364. return inProgressIOs != 0;
  365. }