浏览代码

Add libaria2 tutorial

Tatsuhiro Tsujikawa 12 年之前
父节点
当前提交
42d3408b50
共有 2 个文件被更改,包括 193 次插入3 次删除
  1. 192 2
      doc/manual-src/en/libaria2.rst
  2. 1 1
      examples/libaria2ex.cc

+ 192 - 2
doc/manual-src/en/libaria2.rst

@@ -11,8 +11,198 @@ libaria2: C++ library interface to aria2
 
 The libaria2 is a C++ library and offers the core functionality of
 aria2. The library takes care of all networking and downloading stuff,
-so its usage is very straight forward right now. See *libaria2ex.cc*
-in *examples* directory to see how to use API.
+so its usage is very straight forward right now. See the following
+Tutorial section to see how to use API.
+
+Tutorial
+--------
+
+This section is a step by step guide to create a program to download
+files using libaria2. The complete source is located at
+*libaria2ex.cc* in *examples* directory.
+
+The *libaria2ex* program takes one or more URIs and downloads each of
+them in parellel. The usage is::
+
+    Usage: libaria2ex URI [URI...]
+
+      Download given URIs in parallel in the current directory.
+
+The source code uses C++11 features, so C++11 enabled compiler is
+required. GCC 4.7 works well here.
+
+OK, let's look into the source code. First, include aria2.h header
+file::
+
+    #include <aria2/aria2.h>
+
+Skip to the ``main()`` function. After checking command-line
+arguments, we initialize libaria2::
+
+    aria2::libraryInit();
+
+And create aria2 session object::
+
+    aria2::Session* session;
+    // Create default configuration. The libaria2 takes care of signal
+    // handling.
+    aria2::SessionConfig config;
+    // Add event callback
+    config.downloadEventCallback = downloadEventCallback;
+    session = aria2::sessionNew(aria2::KeyVals(), config);
+
+:type:`Session` ``session`` is an aria2 session object. You need this
+object through out the download process. Please keep in mind that only
+one :type:`Session` object can be allowed per process due to the heavy
+use of static objects in aria2 code base. :type:`SessionConfig`
+``config`` holds configuration for the session object. The constructor
+initializes it with the default values. In this setup,
+:member:`SessionConfig::keepRunning` is ``false`` which means
+:func:`run()` returns when all downloads are processed, just like
+aria2c utility without RPC enabled.  And
+:member:`SessionConfig::useSignalHandler` is ``true``, which means
+libaria2 will setup signal handlers and catches certain signals to
+halt download process gracefully. We also setup event handler callback
+function ``downloadEventCallback``.  It will be called when an event
+occurred such as download is started, completed, etc. In this example
+program, we handle 2 events: download completion and error. For each
+event, we print the GID of the download and several other
+information::
+
+  int downloadEventCallback(aria2::Session* session, aria2::DownloadEvent event,
+			    const aria2::A2Gid& gid, void* userData)
+  {
+    switch(event) {
+    case aria2::EVENT_ON_DOWNLOAD_COMPLETE:
+      std::cerr << "COMPLETE";
+      break;
+    case aria2::EVENT_ON_DOWNLOAD_ERROR:
+      std::cerr << "ERROR";
+      break;
+    default:
+      return 0;
+    }
+    std::cerr << " [" << aria2::gidToHex(gid) << "] ";
+    ...
+  }
+
+The ``userData`` object is specified by
+:member:`SessionConfig::userData`. In this example, we does not
+specify it, so it is ``nullptr``.
+
+The first argument to :func:`sessionNew()` is ``aria2::KeyVals()``.
+This type is used in API to specify vector of key/value pairs, mostly
+representing aria2 options. For example, specify an option
+``file-allocation`` to ``none``::
+
+    aria2::KeyVals options;
+    options.push_back(aria2::KeyVals("file-allocation", "none"));
+
+The first argument of :func:`sessionNew()` is analogous to the
+command-line argument to aria2c program. In the example program, we
+provide no options, so just pass empty vector.
+
+After the creation of session object, let's add downloads given in the
+command-line::
+
+    // Add download item to session
+    for(int i = 1; i < argc; ++i) {
+      std::vector<std::string> uris = {argv[i]};
+      aria2::KeyVals options;
+      rv = aria2::addUri(session, nullptr, uris, options);
+      if(rv < 0) {
+	std::cerr << "Failed to add download " << uris[0] << std::endl;
+      }
+    }
+
+We iterate command-line arguments and add each of them as a separate
+download. :func:`addUri()` can take one or more URIs to download
+several sources, just like aria2c does, but in this example, we just
+give just one URI. We provide no particular option for the download,
+so pass the empty vector as options. The second argument of
+:func:`addUri()` takes a pointer to :type:`A2Gid`. If it is not
+``NULL``, the function assigns the GID of the new download to it.  In
+this example code, we have no interest for it, so just pass
+``nullptr``.
+
+We setup everything at this stage. So let's start download.  To
+perform the download, call :func:`run()` repeatedly until it returns
+the value other than ``1``::
+
+    for(;;) {
+      rv = aria2::run(session, aria2::RUN_ONCE);
+      if(rv != 1) {
+	break;
+      }
+      ...
+    }
+
+Here, we call :func:`run()` with :c:macro:`RUN_ONCE`. It means
+:func:`run()` returns after one event polling and its action handling
+or polling timeout (which is approximately 1 second). If :func:`run()`
+returns ``1``, it means the download is in progress and the
+application must call it again. If it returns ``0``, then no download
+is left (or it is stopped by signal handler or :func:`shutdown()`).
+If the function catches error, it returns ``-1``.  The good point of
+using :c:macro:`RUN_ONCE` is that the application can use libaria2 API
+when :func:`run()` returns. In the example program, we print the
+progress of the download in every no less than 500 millisecond::
+
+    // Print progress information once per 500ms
+    if(count >= 500) {
+      start = now;
+      aria2::GlobalStat gstat = aria2::getGlobalStat(session);
+      std::cerr << "Overall #Active:" << gstat.numActive
+                << " #waiting:" << gstat.numWaiting
+                << " D:" << gstat.downloadSpeed/1024 << "KiB/s"
+                << " U:"<< gstat.uploadSpeed/1024 << "KiB/s " << std::endl;
+      std::vector<aria2::A2Gid> gids = aria2::getActiveDownload(session);
+      for(const auto& gid : gids) {
+        aria2::DownloadHandle* dh = aria2::getDownloadHandle(session, gid);
+        if(dh) {
+          std::cerr << "    [" << aria2::gidToHex(gid) << "] "
+                    << dh->getCompletedLength() << "/"
+                    << dh->getTotalLength() << "("
+                    << (dh->getTotalLength() > 0 ?
+                        (100*dh->getCompletedLength()/dh->getTotalLength())
+                        : 0) << "%)"
+                    << " D:"
+                    << dh->getDownloadSpeed()/1024 << "KiB/s, U:"
+                    << dh->getUploadSpeed()/1024 << "KiB/s"
+                    << std::endl;
+          aria2::deleteDownloadHandle(dh);
+        }
+      }
+    }
+
+We first call :func:`getGlobalStat()` function to get global
+statistics of the downloads. Then, call :func:`getActiveDownload()`
+function to get the vector of active download's GID. For each GID, we
+retrieve :class:`DownloadHandle` object using
+:func:`getDownloadHandle` function and get detailed infromation.
+Please don't forget to delete :class:`DownloadHandle` after the use
+and before the next call of :func:`run()`.  Keep in mind that the life
+time of :class:`DownloadHandle` object is before the next call of
+:func:`run()` function.
+
+After the loop, finalize download calling :func:`sessionFinal()`
+function and call :func:`libraryDeinit()` to release resources for the
+library::
+
+    rv = aria2::sessionFinal(session);
+    aria2::libraryDeinit();
+    return rv;
+
+Calling :func:`sessionFinal()` is important because it performs
+post-download action, including saving sessions and destroys session
+object. So failing to call this function will lead to lose the
+download progress and memory leak. The :func:`sessionFinal()` returns
+the code defined in :ref:`exit-status`. aria2c program also returns
+the same value as exist status, so do the same in this tiny example
+program.
+
+See also *libaria2wx.cc* which uses wx GUI component as UI and use
+background thread to run download.
 
 API Reference
 -------------

+ 1 - 1
examples/libaria2ex.cc

@@ -95,7 +95,7 @@ int main(int argc, char** argv)
   for(int i = 1; i < argc; ++i) {
     std::vector<std::string> uris = {argv[i]};
     aria2::KeyVals options;
-    rv = aria2::addUri(session, 0, uris, options);
+    rv = aria2::addUri(session, nullptr, uris, options);
     if(rv < 0) {
       std::cerr << "Failed to add download " << uris[0] << std::endl;
     }