AbstractCommand.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - a simple utility for downloading files faster
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. /* copyright --> */
  22. #include "AbstractCommand.h"
  23. #include "DlAbortEx.h"
  24. #include "DlRetryEx.h"
  25. #include "InitiateConnectionCommandFactory.h"
  26. #include "Util.h"
  27. #include "message.h"
  28. #include "SleepCommand.h"
  29. #include "prefs.h"
  30. AbstractCommand::AbstractCommand(int cuid, Request* req, DownloadEngine* e, const Socket* s):
  31. Command(cuid), req(req), e(e), checkSocketIsReadable(false), checkSocketIsWritable(false) {
  32. if(s != NULL) {
  33. socket = new Socket(*s);
  34. setReadCheckSocket(socket);
  35. } else {
  36. socket = NULL;
  37. }
  38. timeout = this->e->option->getAsInt(PREF_TIMEOUT);
  39. }
  40. AbstractCommand::~AbstractCommand() {
  41. setReadCheckSocket(NULL);
  42. setWriteCheckSocket(NULL);
  43. if(socket != NULL) {
  44. delete(socket);
  45. }
  46. }
  47. bool AbstractCommand::execute() {
  48. try {
  49. if(checkSocketIsReadable && readCheckTarget->isReadable(0) ||
  50. checkSocketIsWritable && writeCheckTarget->isWritable(0) ||
  51. !checkSocketIsReadable && !checkSocketIsWritable) {
  52. checkPoint.reset();
  53. Segment seg = { 0, 0, 0, false };
  54. if(e->segmentMan->downloadStarted) {
  55. // get segment information in order to set Range header.
  56. if(!e->segmentMan->getSegment(seg, cuid)) {
  57. // no segment available
  58. logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid);
  59. return true;
  60. }
  61. }
  62. return executeInternal(seg);
  63. } else {
  64. if(checkPoint.elapsed(timeout)) {
  65. throw new DlRetryEx(EX_TIME_OUT);
  66. }
  67. e->commands.push_back(this);
  68. return false;
  69. }
  70. } catch(DlAbortEx* err) {
  71. logger->error(MSG_DOWNLOAD_ABORTED, err, cuid);
  72. onAbort(err);
  73. delete(err);
  74. req->resetUrl();
  75. e->segmentMan->errors++;
  76. return true;
  77. } catch(DlRetryEx* err) {
  78. logger->error(MSG_RESTARTING_DOWNLOAD, err, cuid);
  79. req->addTryCount();
  80. bool isAbort = e->option->getAsInt(PREF_MAX_TRIES) != 0 &&
  81. req->getTryCount() >= e->option->getAsInt(PREF_MAX_TRIES);
  82. if(isAbort) {
  83. onAbort(err);
  84. }
  85. delete(err);
  86. if(isAbort) {
  87. logger->error(MSG_MAX_TRY, cuid, req->getTryCount());
  88. e->segmentMan->errors++;
  89. return true;
  90. } else {
  91. return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));
  92. }
  93. }
  94. }
  95. bool AbstractCommand::prepareForRetry(int wait) {
  96. Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, e);
  97. if(wait == 0) {
  98. e->commands.push_back(command);
  99. } else {
  100. SleepCommand* scom = new SleepCommand(cuid, e, command, wait);
  101. e->commands.push_back(scom);
  102. }
  103. return true;
  104. }
  105. void AbstractCommand::onAbort(Exception* ex) {
  106. logger->debug(MSG_UNREGISTER_CUID, cuid);
  107. e->segmentMan->unregisterId(cuid);
  108. }
  109. void AbstractCommand::setReadCheckSocket(Socket* socket) {
  110. if(socket == NULL) {
  111. if(checkSocketIsReadable) {
  112. e->deleteSocketForReadCheck(readCheckTarget);
  113. checkSocketIsReadable = false;
  114. readCheckTarget = NULL;
  115. }
  116. } else {
  117. if(checkSocketIsReadable) {
  118. if(readCheckTarget != socket) {
  119. e->deleteSocketForReadCheck(readCheckTarget);
  120. e->addSocketForReadCheck(socket, this);
  121. readCheckTarget = socket;
  122. }
  123. } else {
  124. e->addSocketForReadCheck(socket, this);
  125. checkSocketIsReadable = true;
  126. readCheckTarget = socket;
  127. }
  128. }
  129. }
  130. void AbstractCommand::setWriteCheckSocket(Socket* socket) {
  131. if(socket == NULL) {
  132. if(checkSocketIsWritable) {
  133. e->deleteSocketForWriteCheck(writeCheckTarget);
  134. checkSocketIsWritable = false;
  135. writeCheckTarget = NULL;
  136. }
  137. } else {
  138. if(checkSocketIsWritable) {
  139. if(writeCheckTarget != socket) {
  140. e->deleteSocketForWriteCheck(writeCheckTarget);
  141. e->addSocketForWriteCheck(socket, this);
  142. writeCheckTarget = socket;
  143. }
  144. } else {
  145. e->addSocketForWriteCheck(socket, this);
  146. checkSocketIsWritable = true;
  147. writeCheckTarget = socket;
  148. }
  149. }
  150. }