Browse Source

2010-04-11 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Added aria2.pauseAll, aria2.forcePauseAll and aria2.unpauseAll
	XML-RPC method.
	* doc/aria2c.1.txt
	* src/XmlRpcMethodFactory.cc
	* src/XmlRpcMethodImpl.cc
	* src/XmlRpcMethodImpl.h
	* test/XmlRpcMethodTest.cc
Tatsuhiro Tsujikawa 15 years ago
parent
commit
15bb26cac8
8 changed files with 252 additions and 31 deletions
  1. 10 0
      ChangeLog
  2. 22 6
      doc/aria2c.1
  3. 22 8
      doc/aria2c.1.html
  4. 26 4
      doc/aria2c.1.txt
  5. 6 0
      src/XmlRpcMethodFactory.cc
  6. 72 13
      src/XmlRpcMethodImpl.cc
  7. 33 0
      src/XmlRpcMethodImpl.h
  8. 61 0
      test/XmlRpcMethodTest.cc

+ 10 - 0
ChangeLog

@@ -1,3 +1,13 @@
+2010-04-11  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Added aria2.pauseAll, aria2.forcePauseAll and aria2.unpauseAll
+	XML-RPC method.
+	* doc/aria2c.1.txt
+	* src/XmlRpcMethodFactory.cc
+	* src/XmlRpcMethodImpl.cc
+	* src/XmlRpcMethodImpl.h
+	* test/XmlRpcMethodTest.cc
+
 2010-04-11  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 2010-04-11  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 
 	Added aria2.forcePause XML-RPC command.
 	Added aria2.forcePause XML-RPC command.

+ 22 - 6
doc/aria2c.1

@@ -2,12 +2,12 @@
 .\"     Title: aria2c
 .\"     Title: aria2c
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 04/09/2010
+.\"      Date: 04/11/2010
 .\"    Manual: Aria2 Manual
 .\"    Manual: Aria2 Manual
 .\"    Source: Aria2 1.9.1a
 .\"    Source: Aria2 1.9.1a
 .\"  Language: English
 .\"  Language: English
 .\"
 .\"
-.TH "ARIA2C" "1" "04/09/2010" "Aria2 1\&.9\&.1a" "Aria2 Manual"
+.TH "ARIA2C" "1" "04/11/2010" "Aria2 1\&.9\&.1a" "Aria2 Manual"
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
@@ -2631,12 +2631,28 @@ This method removes the download denoted by \fIgid\fR\&. This method behaves jus
 .sp
 .sp
 \fBaria2\&.pause\fR \fIgid\fR
 \fBaria2\&.pause\fR \fIgid\fR
 .sp
 .sp
-This method pauses the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. The status of paused download becomes "paused" and the download is placed on the first position of waiting queue\&. As long as the status is "paused", the download is not started\&. To change status to "waiting", use \fBaria2\&.unpause\fR method\&. This method returns GID of paused download\&.
+This method pauses the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. The status of paused download becomes "paused"\&. If the download is active, the download is placed on the first position of waiting queue\&. As long as the status is "paused", the download is not started\&. To change status to "waiting", use \fBaria2\&.unpause\fR method\&. This method returns GID of paused download\&.
+.sp
+\fBaria2\&.pauseAll\fR
+.sp
+This method is equal to calling \fBaria2\&.pause\fR for every active/waiting download\&. This methods returns "OK" for success\&.
+.sp
+\fBaria2\&.forcePause\fR \fIpid\fR
+.sp
+This method pauses the download denoted by \fIgid\fR\&. This method behaves just like \fBaria2\&.pause\fR except that this method pauses download without any action which takes time such as contacting BitTorrent tracker\&.
+.sp
+\fBaria2\&.forcePauseAll\fR
+.sp
+This method is equal to calling \fBaria2\&.forcePause\fR for every active/waiting download\&. This methods returns "OK" for success\&.
 .sp
 .sp
 \fBaria2\&.unpause\fR \fIgid\fR
 \fBaria2\&.unpause\fR \fIgid\fR
 .sp
 .sp
 This method changes the status of the download denoted by \fIgid\fR from "paused" to "waiting"\&. This makes the download eligible to restart\&. \fIgid\fR is of type string\&. This method returns GID of unpaused download\&.
 This method changes the status of the download denoted by \fIgid\fR from "paused" to "waiting"\&. This makes the download eligible to restart\&. \fIgid\fR is of type string\&. This method returns GID of unpaused download\&.
 .sp
 .sp
+\fBaria2\&.unpauseAll\fR
+.sp
+This method is equal to calling \fBaria2\&.unpause\fR for every active/waiting download\&. This methods returns "OK" for success\&.
+.sp
 \fBaria2\&.tellStatus\fR \fIgid\fR
 \fBaria2\&.tellStatus\fR \fIgid\fR
 .sp
 .sp
 This method returns download progress of the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. The response is of type struct and it contains following keys\&. The value type is string\&.
 This method returns download progress of the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. The response is of type struct and it contains following keys\&. The value type is string\&.
@@ -3167,7 +3183,7 @@ aria2 uses 5 connections to download 1 file by default\&. \-s1 limits the number
 .ps -1
 .ps -1
 .br
 .br
 .sp
 .sp
-To pause a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&. You can change URIs as long as they are pointing to the same file\&.
+To stop a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&. You can change URIs as long as they are pointing to the same file\&.
 .sp .5v
 .sp .5v
 .RE
 .RE
 .RE
 .RE
@@ -3383,7 +3399,7 @@ aria2c \-p \-\-lowest\-speed\-limit=4000 file\&.metalink
 .ps -1
 .ps -1
 .br
 .br
 .sp
 .sp
-To pause a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&.
+To stop a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&.
 .sp .5v
 .sp .5v
 .RE
 .RE
 .RE
 .RE
@@ -3527,7 +3543,7 @@ aria2c \-\-max\-upload\-limit=40K file\&.torrent
 .ps -1
 .ps -1
 .br
 .br
 .sp
 .sp
-To pause a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&.
+To stop a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&.
 .sp .5v
 .sp .5v
 .RE
 .RE
 .RE
 .RE

+ 22 - 8
doc/aria2c.1.html

@@ -3102,16 +3102,30 @@ download without any action which takes time such as contacting
 BitTorrent tracker.</p></div>
 BitTorrent tracker.</p></div>
 <div class="paragraph"><p><strong>aria2.pause</strong> <em>gid</em></p></div>
 <div class="paragraph"><p><strong>aria2.pause</strong> <em>gid</em></p></div>
 <div class="paragraph"><p>This method pauses the download denoted by <em>gid</em>. <em>gid</em> is of type
 <div class="paragraph"><p>This method pauses the download denoted by <em>gid</em>. <em>gid</em> is of type
-string. The status of paused download becomes "paused" and the
-download is placed on the first position of waiting queue.  As long as
-the status is "paused", the download is not started.  To change status
-to "waiting", use <strong>aria2.unpause</strong> method.
+string. The status of paused download becomes "paused".  If the
+download is active, the download is placed on the first position of
+waiting queue.  As long as the status is "paused", the download is not
+started.  To change status to "waiting", use <strong>aria2.unpause</strong> method.
 This method returns GID of paused download.</p></div>
 This method returns GID of paused download.</p></div>
+<div class="paragraph"><p><strong>aria2.pauseAll</strong></p></div>
+<div class="paragraph"><p>This method is equal to calling <strong>aria2.pause</strong> for every active/waiting
+download. This methods returns "OK" for success.</p></div>
+<div class="paragraph"><p><strong>aria2.forcePause</strong> <em>pid</em></p></div>
+<div class="paragraph"><p>This method pauses the download denoted by <em>gid</em>.  This method
+behaves just like <strong>aria2.pause</strong> except that this method pauses
+download without any action which takes time such as contacting
+BitTorrent tracker.</p></div>
+<div class="paragraph"><p><strong>aria2.forcePauseAll</strong></p></div>
+<div class="paragraph"><p>This method is equal to calling <strong>aria2.forcePause</strong> for every
+active/waiting download. This methods returns "OK" for success.</p></div>
 <div class="paragraph"><p><strong>aria2.unpause</strong> <em>gid</em></p></div>
 <div class="paragraph"><p><strong>aria2.unpause</strong> <em>gid</em></p></div>
 <div class="paragraph"><p>This method changes the status of the download denoted by <em>gid</em> from
 <div class="paragraph"><p>This method changes the status of the download denoted by <em>gid</em> from
 "paused" to "waiting". This makes the download eligible to restart.
 "paused" to "waiting". This makes the download eligible to restart.
 <em>gid</em> is of type string.  This method returns GID of unpaused
 <em>gid</em> is of type string.  This method returns GID of unpaused
 download.</p></div>
 download.</p></div>
+<div class="paragraph"><p><strong>aria2.unpauseAll</strong></p></div>
+<div class="paragraph"><p>This method is equal to calling <strong>aria2.unpause</strong> for every active/waiting
+download. This methods returns "OK" for success.</p></div>
 <div class="paragraph"><p><strong>aria2.tellStatus</strong> <em>gid</em></p></div>
 <div class="paragraph"><p><strong>aria2.tellStatus</strong> <em>gid</em></p></div>
 <div class="paragraph"><p>This method returns download progress of the download denoted by
 <div class="paragraph"><p>This method returns download progress of the download denoted by
 <em>gid</em>. <em>gid</em> is of type string. The response is of type struct and it
 <em>gid</em>. <em>gid</em> is of type string. The response is of type struct and it
@@ -3794,7 +3808,7 @@ pprint(r)</tt></pre>
 <td class="icon">
 <td class="icon">
 <div class="title">Note</div>
 <div class="title">Note</div>
 </td>
 </td>
-<td class="content">To pause a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory. You can change URIs as long as they are pointing to the same file.</td>
+<td class="content">To stop a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory. You can change URIs as long as they are pointing to the same file.</td>
 </tr></table>
 </tr></table>
 </div>
 </div>
 <h4 id="_download_a_file_from_2_different_http_servers">Download a file from 2 different HTTP servers</h4>
 <h4 id="_download_a_file_from_2_different_http_servers">Download a file from 2 different HTTP servers</h4>
@@ -3870,7 +3884,7 @@ variables. See <strong>ENVIRONMENT</strong> section.</td>
 <td class="icon">
 <td class="icon">
 <div class="title">Note</div>
 <div class="title">Note</div>
 </td>
 </td>
-<td class="content">To pause a download, press Ctrl-C.
+<td class="content">To stop a download, press Ctrl-C.
 You can resume the transfer by running aria2c with the same argument in the same
 You can resume the transfer by running aria2c with the same argument in the same
 directory.</td>
 directory.</td>
 </tr></table>
 </tr></table>
@@ -3922,7 +3936,7 @@ directory.</td>
 <td class="icon">
 <td class="icon">
 <div class="title">Note</div>
 <div class="title">Note</div>
 </td>
 </td>
-<td class="content">To pause a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory.</td>
+<td class="content">To stop a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory.</td>
 </tr></table>
 </tr></table>
 </div>
 </div>
 <h4 id="_download_using_bittorrent_magnet_uri">Download using BitTorrent Magnet URI</h4>
 <h4 id="_download_using_bittorrent_magnet_uri">Download using BitTorrent Magnet URI</h4>
@@ -4174,7 +4188,7 @@ files in the program, then also delete it here.</p></div>
 <div id="footnotes"><hr /></div>
 <div id="footnotes"><hr /></div>
 <div id="footer">
 <div id="footer">
 <div id="footer-text">
 <div id="footer-text">
-Last updated 2010-04-09 00:32:31 JST
+Last updated 2010-04-11 23:42:41 JST
 </div>
 </div>
 </div>
 </div>
 </body>
 </body>

+ 26 - 4
doc/aria2c.1.txt

@@ -1371,12 +1371,29 @@ BitTorrent tracker.
 *aria2.pause* 'gid'
 *aria2.pause* 'gid'
 
 
 This method pauses the download denoted by 'gid'. 'gid' is of type
 This method pauses the download denoted by 'gid'. 'gid' is of type
-string. The status of paused download becomes "paused" and the
-download is placed on the first position of waiting queue.  As long as
-the status is "paused", the download is not started.  To change status
-to "waiting", use *aria2.unpause* method.
+string. The status of paused download becomes "paused".  If the
+download is active, the download is placed on the first position of
+waiting queue.  As long as the status is "paused", the download is not
+started.  To change status to "waiting", use *aria2.unpause* method.
 This method returns GID of paused download.
 This method returns GID of paused download.
 
 
+*aria2.pauseAll*
+
+This method is equal to calling *aria2.pause* for every active/waiting
+download. This methods returns "OK" for success.
+
+*aria2.forcePause* 'pid'
+
+This method pauses the download denoted by 'gid'.  This method
+behaves just like *aria2.pause* except that this method pauses
+download without any action which takes time such as contacting
+BitTorrent tracker.
+
+*aria2.forcePauseAll*
+
+This method is equal to calling *aria2.forcePause* for every
+active/waiting download. This methods returns "OK" for success.
+
 *aria2.unpause* 'gid'
 *aria2.unpause* 'gid'
 
 
 This method changes the status of the download denoted by 'gid' from
 This method changes the status of the download denoted by 'gid' from
@@ -1384,6 +1401,11 @@ This method changes the status of the download denoted by 'gid' from
 'gid' is of type string.  This method returns GID of unpaused
 'gid' is of type string.  This method returns GID of unpaused
 download.
 download.
 
 
+*aria2.unpauseAll*
+
+This method is equal to calling *aria2.unpause* for every active/waiting
+download. This methods returns "OK" for success.
+
 *aria2.tellStatus* 'gid'
 *aria2.tellStatus* 'gid'
 
 
 This method returns download progress of the download denoted by
 This method returns download progress of the download denoted by

+ 6 - 0
src/XmlRpcMethodFactory.cc

@@ -62,8 +62,14 @@ XmlRpcMethodFactory::create(const std::string& methodName)
     return SharedHandle<XmlRpcMethod>(new PauseXmlRpcMethod());
     return SharedHandle<XmlRpcMethod>(new PauseXmlRpcMethod());
   } else if(methodName == ForcePauseXmlRpcMethod::getMethodName()) {
   } else if(methodName == ForcePauseXmlRpcMethod::getMethodName()) {
     return SharedHandle<XmlRpcMethod>(new ForcePauseXmlRpcMethod());
     return SharedHandle<XmlRpcMethod>(new ForcePauseXmlRpcMethod());
+  } else if(methodName == PauseAllXmlRpcMethod::getMethodName()) {
+    return SharedHandle<XmlRpcMethod>(new PauseAllXmlRpcMethod());
+  } else if(methodName == ForcePauseAllXmlRpcMethod::getMethodName()) {
+    return SharedHandle<XmlRpcMethod>(new ForcePauseAllXmlRpcMethod());
   } else if(methodName == UnpauseXmlRpcMethod::getMethodName()) {
   } else if(methodName == UnpauseXmlRpcMethod::getMethodName()) {
     return SharedHandle<XmlRpcMethod>(new UnpauseXmlRpcMethod());
     return SharedHandle<XmlRpcMethod>(new UnpauseXmlRpcMethod());
+  } else if(methodName == UnpauseAllXmlRpcMethod::getMethodName()) {
+    return SharedHandle<XmlRpcMethod>(new UnpauseAllXmlRpcMethod());
   } else if(methodName == ForceRemoveXmlRpcMethod::getMethodName()) {
   } else if(methodName == ForceRemoveXmlRpcMethod::getMethodName()) {
     return SharedHandle<XmlRpcMethod>(new ForceRemoveXmlRpcMethod());
     return SharedHandle<XmlRpcMethod>(new ForceRemoveXmlRpcMethod());
   } else if(methodName == ChangePositionXmlRpcMethod::getMethodName()) {
   } else if(methodName == ChangePositionXmlRpcMethod::getMethodName()) {

+ 72 - 13
src/XmlRpcMethodImpl.cc

@@ -348,17 +348,28 @@ BDE ForceRemoveXmlRpcMethod::process
   return removeDownload(req, e, true);
   return removeDownload(req, e, true);
 }
 }
 
 
-static void pauseRequestGroup
-(const SharedHandle<RequestGroup>& group, bool forcePause)
+static bool pauseRequestGroup
+(const SharedHandle<RequestGroup>& group, bool reserved,  bool forcePause)
 {
 {
-  // Call setHaltRequested before setPauseRequested because
-  // setHaltRequested calls setPauseRequested(false) internally.
-  if(forcePause) {
-    group->setForceHaltRequested(true, RequestGroup::USER_REQUEST);
+  if((reserved && !group->isPauseRequested()) ||
+     (!reserved &&
+      !group->isForceHaltRequested() &&
+      ((forcePause && group->isHaltRequested() && group->isPauseRequested()) ||
+       (!group->isHaltRequested() && !group->isPauseRequested())))) {
+    if(!reserved) {
+      // Call setHaltRequested before setPauseRequested because
+      // setHaltRequested calls setPauseRequested(false) internally.
+      if(forcePause) {
+        group->setForceHaltRequested(true, RequestGroup::USER_REQUEST);
+      } else {
+        group->setHaltRequested(true, RequestGroup::USER_REQUEST);
+      }
+    }
+    group->setPauseRequested(true);
+    return true;
   } else {
   } else {
-    group->setHaltRequested(true, RequestGroup::USER_REQUEST);
+    return false;
   }
   }
-  group->setPauseRequested(true);
 }
 }
 
 
 static BDE pauseDownload
 static BDE pauseDownload
@@ -370,15 +381,19 @@ static BDE pauseDownload
     throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
     throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
   }
   }
   gid_t gid = util::parseLLInt(params[0].s());
   gid_t gid = util::parseLLInt(params[0].s());
-  SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
-  if(group.isNull() || group->isHaltRequested()) {
+  bool reserved = false;
+  SharedHandle<RequestGroup> group = e->_requestGroupMan->findRequestGroup(gid);
+  if(group.isNull()) {
+    reserved = true;
+    group = e->_requestGroupMan->findReservedGroup(gid);
+  }
+  if(!group.isNull() && pauseRequestGroup(group, reserved, forcePause)) {
+    return createGIDResponse(gid);
+  } else {
     throw DL_ABORT_EX
     throw DL_ABORT_EX
       (StringFormat("GID#%s cannot be paused now",
       (StringFormat("GID#%s cannot be paused now",
                     util::itos(gid).c_str()).str());
                     util::itos(gid).c_str()).str());
-  } else {
-    pauseRequestGroup(group, forcePause);
   }
   }
-  return createGIDResponse(gid);
 }
 }
 
 
 BDE PauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
 BDE PauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
@@ -391,6 +406,39 @@ BDE ForcePauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
   return pauseDownload(req, e, true);
   return pauseDownload(req, e, true);
 }
 }
 
 
+template<typename InputIterator>
+static void pauseRequestGroups
+(InputIterator first, InputIterator last, bool reserved, bool forcePause)
+{
+  for(; first != last; ++first) {
+    pauseRequestGroup(*first, reserved, forcePause);
+  }
+}
+
+static BDE pauseAllDownloads
+(const XmlRpcRequest& req, DownloadEngine* e, bool forcePause)
+{
+  const std::deque<SharedHandle<RequestGroup> >& groups =
+    e->_requestGroupMan->getRequestGroups();
+  pauseRequestGroups(groups.begin(), groups.end(), false, forcePause);
+  const std::deque<SharedHandle<RequestGroup> >& reservedGroups =
+    e->_requestGroupMan->getReservedGroups();
+  pauseRequestGroups(reservedGroups.begin(), reservedGroups.end(),
+                     true, forcePause);
+  return BDE_OK;
+}
+
+BDE PauseAllXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
+{
+  return pauseAllDownloads(req, e, false);
+}
+
+BDE ForcePauseAllXmlRpcMethod::process
+(const XmlRpcRequest& req, DownloadEngine* e)
+{
+  return pauseAllDownloads(req, e, true);
+}
+
 BDE UnpauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
 BDE UnpauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
   const BDE& params = req._params;
   const BDE& params = req._params;
@@ -411,6 +459,17 @@ BDE UnpauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
   return createGIDResponse(gid);
   return createGIDResponse(gid);
 }
 }
 
 
+BDE UnpauseAllXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
+{
+  const std::deque<SharedHandle<RequestGroup> >& groups =
+    e->_requestGroupMan->getReservedGroups();
+  std::for_each(groups.begin(), groups.end(),
+                std::bind2nd(mem_fun_sh(&RequestGroup::setPauseRequested),
+                             false));
+  e->_requestGroupMan->requestQueueCheck();    
+  return BDE_OK;
+}
+
 static void createUriEntry(BDE& uriList, const SharedHandle<FileEntry>& file)
 static void createUriEntry(BDE& uriList, const SharedHandle<FileEntry>& file)
 {
 {
   {
   {

+ 33 - 0
src/XmlRpcMethodImpl.h

@@ -106,6 +106,28 @@ public:
   }
   }
 };
 };
 
 
+class PauseAllXmlRpcMethod:public XmlRpcMethod {
+protected:
+  virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
+public:
+  static const std::string& getMethodName()
+  {
+    static std::string methodName = "aria2.pauseAll";
+    return methodName;
+  }
+};
+
+class ForcePauseAllXmlRpcMethod:public XmlRpcMethod {
+protected:
+  virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
+public:
+  static const std::string& getMethodName()
+  {
+    static std::string methodName = "aria2.forcePauseAll";
+    return methodName;
+  }
+};
+
 class UnpauseXmlRpcMethod:public XmlRpcMethod {
 class UnpauseXmlRpcMethod:public XmlRpcMethod {
 protected:
 protected:
   virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
   virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
@@ -117,6 +139,17 @@ public:
   }
   }
 };
 };
 
 
+class UnpauseAllXmlRpcMethod:public XmlRpcMethod {
+protected:
+  virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
+public:
+  static const std::string& getMethodName()
+  {
+    static std::string methodName = "aria2.unpauseAll";
+    return methodName;
+  }
+};
+
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT
 class AddTorrentXmlRpcMethod:public XmlRpcMethod {
 class AddTorrentXmlRpcMethod:public XmlRpcMethod {
 protected:
 protected:

+ 61 - 0
test/XmlRpcMethodTest.cc

@@ -20,6 +20,7 @@
 #include "FeatureConfig.h"
 #include "FeatureConfig.h"
 #include "util.h"
 #include "util.h"
 #include "array_fun.h"
 #include "array_fun.h"
+#include "download_helper.h"
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT
 # include "BtRegistry.h"
 # include "BtRegistry.h"
 # include "BtRuntime.h"
 # include "BtRuntime.h"
@@ -77,6 +78,7 @@ class XmlRpcMethodTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testGetSessionInfo);
   CPPUNIT_TEST(testGetSessionInfo);
   CPPUNIT_TEST(testChangeUri);
   CPPUNIT_TEST(testChangeUri);
   CPPUNIT_TEST(testChangeUri_fail);
   CPPUNIT_TEST(testChangeUri_fail);
+  CPPUNIT_TEST(testPause);
   CPPUNIT_TEST(testSystemMulticall);
   CPPUNIT_TEST(testSystemMulticall);
   CPPUNIT_TEST(testSystemMulticall_fail);
   CPPUNIT_TEST(testSystemMulticall_fail);
   CPPUNIT_TEST_SUITE_END();
   CPPUNIT_TEST_SUITE_END();
@@ -139,6 +141,7 @@ public:
   void testGetSessionInfo();
   void testGetSessionInfo();
   void testChangeUri();
   void testChangeUri();
   void testChangeUri_fail();
   void testChangeUri_fail();
+  void testPause();
   void testSystemMulticall();
   void testSystemMulticall();
   void testSystemMulticall_fail();
   void testSystemMulticall_fail();
 };
 };
@@ -920,6 +923,64 @@ void XmlRpcMethodTest::testGetSessionInfo()
                        res._param["sessionId"].s());
                        res._param["sessionId"].s());
 }
 }
 
 
+void XmlRpcMethodTest::testPause()
+{
+  const std::string URIS[] = {
+    "http://url1",
+    "http://url2",
+    "http://url3",
+  };
+  std::vector<std::string> uris(vbegin(URIS), vend(URIS));
+  _option->put(PREF_FORCE_SEQUENTIAL, V_TRUE);
+  std::vector<SharedHandle<RequestGroup> > groups;
+  createRequestGroupForUri(groups, _option, uris);
+  CPPUNIT_ASSERT_EQUAL((size_t)3, groups.size());  
+  _e->_requestGroupMan->addReservedGroup(groups);
+  {
+    PauseXmlRpcMethod m;
+    XmlRpcRequest req(PauseXmlRpcMethod::getMethodName(), BDE::list());
+    req._params << std::string("1");
+    XmlRpcResponse res = m.execute(req, _e.get());
+    CPPUNIT_ASSERT_EQUAL(0, res._code);
+  }
+  CPPUNIT_ASSERT(groups[0]->isPauseRequested());
+  {
+    UnpauseXmlRpcMethod m;
+    XmlRpcRequest req(UnpauseXmlRpcMethod::getMethodName(), BDE::list());
+    req._params << std::string("1");
+    XmlRpcResponse res = m.execute(req, _e.get());
+    CPPUNIT_ASSERT_EQUAL(0, res._code);
+  }
+  CPPUNIT_ASSERT(!groups[0]->isPauseRequested());
+  {
+    PauseAllXmlRpcMethod m;
+    XmlRpcRequest req(PauseAllXmlRpcMethod::getMethodName(), BDE::list());
+    XmlRpcResponse res = m.execute(req, _e.get());
+    CPPUNIT_ASSERT_EQUAL(0, res._code);
+  }
+  for(size_t i = 0; i < groups.size(); ++i) {
+    CPPUNIT_ASSERT(groups[i]->isPauseRequested());
+  }
+  {
+    UnpauseAllXmlRpcMethod m;
+    XmlRpcRequest req(UnpauseAllXmlRpcMethod::getMethodName(), BDE::list());
+    XmlRpcResponse res = m.execute(req, _e.get());
+    CPPUNIT_ASSERT_EQUAL(0, res._code);
+  }
+  for(size_t i = 0; i < groups.size(); ++i) {
+    CPPUNIT_ASSERT(!groups[i]->isPauseRequested());
+  }
+  {
+    ForcePauseAllXmlRpcMethod m;
+    XmlRpcRequest req(ForcePauseAllXmlRpcMethod::getMethodName(), BDE::list());
+    XmlRpcResponse res = m.execute(req, _e.get());
+    CPPUNIT_ASSERT_EQUAL(0, res._code);
+  }
+  for(size_t i = 0; i < groups.size(); ++i) {
+    CPPUNIT_ASSERT(groups[i]->isPauseRequested());
+  }
+}
+
 void XmlRpcMethodTest::testSystemMulticall()
 void XmlRpcMethodTest::testSystemMulticall()
 {
 {
   SystemMulticallXmlRpcMethod m;
   SystemMulticallXmlRpcMethod m;