schedbase.h

Go to the documentation of this file.
00001 /**
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /** \file schedbase.h    Interface for SchedBase class */
00020 
00021 #ifndef __SCHEDBASE_H__
00022 #define __SCHEDBASE_H__
00023 
00024 #include <hn/osdep.h>
00025 #include <hn/hnfwd.h>
00026 #include <hn/rangelist.h>
00027 #include <hn/event.h>
00028 
00029 namespace Detail {
00030         struct UploadReqMap;
00031         struct DownloadReqMap;
00032         struct ConnReqMap;
00033 }
00034 
00035 /**
00036  * SchedBase implements the third level of hydranode networking scheduler.
00037  * This class performs the actual bandwidth and connections dividing between
00038  * requests in it's main scheduler loop. It is derived from EventTableBase,
00039  * and as such will be run during each event loop, performing bandwidth requests
00040  * handling.
00041  */
00042 class DLLEXPORT SchedBase : public EventTableBase {
00043 public:
00044         //! Singleton class - accessor to the only instance (created on demand)
00045         static SchedBase& instance();
00046 
00047         //! @name Accessors for various limits and other internal variables
00048         //@{
00049         void     setUpLimit(uint32_t amount)   { m_upLimit = amount;   }
00050         void     setDownLimit(uint32_t amount) { m_downLimit = amount; }
00051         uint32_t getUpLimit()         const { return m_upLimit;     }
00052         uint32_t getDownLimit()       const { return m_downLimit;   }
00053         uint32_t getConnLimit()       const { return m_connLimit;   }
00054         uint64_t getTotalUpstream()   const { return m_totalUp;     }
00055         uint64_t getTotalDownstream() const { return m_totalDown;   }
00056         uint32_t getUpSpeed();      //!< Current upload speed
00057         uint32_t getDownSpeed();    //!< Current download speed
00058         //! \returns Number of current TCP connections
00059         uint32_t getConnCount() const { return m_connCnt; }
00060         //@}
00061 
00062         //! Get number of pending connection requests
00063         size_t getConnReqCount() const;
00064         //! Get number of pending upload requests
00065         size_t getUploadReqCount() const;
00066         //! Get number of pending download requests
00067         size_t getDownloadReqCount() const;
00068 
00069         template<typename Module, typename ImplPtr>
00070         static float getScore(ImplPtr s) {
00071                 return Module::getPriority() + s->getPriority();
00072         }
00073 private:
00074         friend class HydraNode;
00075 
00076         //! @name Singleton
00077         //@{
00078         SchedBase();
00079         ~SchedBase();
00080         SchedBase(const SchedBase&);
00081         SchedBase& operator=(const SchedBase&);
00082         //@}
00083 
00084         //! Called by HydraNode on application shutdown
00085         void exit();
00086 
00087 public:
00088         //! Request base, only contains score of the request
00089         class DLLEXPORT ReqBase {
00090         public:
00091                 ReqBase(float score);
00092                 virtual ~ReqBase();
00093 
00094                 //! Perform notification of frontend(s)
00095                 virtual void notify() const = 0;
00096 
00097                 float getScore() const { return m_score; }
00098 
00099                 //! Make this request invalid, to be deleted as soon as possible
00100                 void invalidate() { m_valid = false; }
00101 
00102                 //! Check the validity of this request
00103                 bool isValid() const { return m_valid; }
00104 
00105                 //! Change validity
00106                 void setValid(bool v) { m_valid = v; }
00107         private:
00108                 float m_score;      //!< Score of this request
00109                 bool  m_valid;      //!< Validity of this request
00110         };
00111 
00112         //! Request of type upload
00113         class DLLEXPORT UploadReqBase : public ReqBase {
00114         public:
00115                 UploadReqBase(float score);
00116                 virtual ~UploadReqBase();
00117                 virtual uint32_t doSend(uint32_t amount) = 0;
00118                 virtual uint32_t getPending() const = 0;
00119         };
00120         //! Request of type download
00121         class DLLEXPORT DownloadReqBase : public ReqBase {
00122         public:
00123                 DownloadReqBase(float score);
00124                 virtual ~DownloadReqBase();
00125                 virtual uint32_t doRecv(uint32_t amount) = 0;
00126         };
00127         //! Request of type connection
00128         class DLLEXPORT ConnReqBase : public ReqBase {
00129         public:
00130                 enum ConnRet {
00131                         REMOVE = 1,   //!< Request should be removed
00132                         NOTIFY = 2,   //!< notify() should be called
00133                         ADDCONN = 4   //!< Connection has been added
00134                 };
00135 
00136                 ConnReqBase(float score);
00137                 virtual ~ConnReqBase();
00138 
00139                 /**
00140                  * Perform connection attempt
00141                  *
00142                  * @return Bitfield of values from ConnRet enumeration
00143                  */
00144                 virtual int doConn() = 0;
00145         };
00146 
00147 private:
00148         //! @name Request sets
00149         //@{
00150         boost::scoped_ptr<Detail::UploadReqMap>   m_uploadReqs;
00151         boost::scoped_ptr<Detail::DownloadReqMap> m_downloadReqs;
00152         boost::scoped_ptr<Detail::ConnReqMap>     m_connReqs;
00153         //@}
00154 
00155         //! @name Main networking loop and helper functions
00156         //@{
00157         void handleEvents();
00158         void handleDownloads();
00159         void handleUploads();
00160         void handleConnections();
00161         //@}
00162 
00163         //! @name Get the amount of free bandwidth/connections at this moment
00164         //@{
00165         uint32_t getFreeDown();
00166         uint32_t getFreeUp();
00167         bool     getConnection();
00168         //@}
00169 
00170         void addUpStream(uint32_t amount);   //! Add upstream data
00171         void addDownStream(uint32_t amount); //! Add downstream data
00172 
00173         /**
00174          * Trace-logs an error
00175          *
00176          * @param where       Where the error happened
00177          * @param what        What error happened
00178          */
00179         void error(const boost::format &where, const std::string &what);
00180 
00181         //! Keeps current tick value - to reduce getTick() calls somewhat
00182         uint64_t m_curTick;
00183 
00184         //! @name Various limits and counts
00185         //@{
00186         uint32_t m_upLimit;      //!< upstream limit
00187         uint32_t m_downLimit;    //!< downstream limit
00188         uint32_t m_connLimit;    //!< open connections limit
00189         uint32_t m_connCnt;      //!< open connections count
00190         uint64_t m_totalUp;      //!< overall total uploaded
00191         uint64_t m_totalDown;    //!< overall total downloaded
00192         uint64_t m_lastDownReset;//!< Last time download speed counter was reset
00193         uint64_t m_lastUpReset;  //!< Last time upload speed counter was reset
00194         uint32_t m_recentDown;   //!< Downloaded data since last counter reset
00195         uint32_t m_recentUp;     //!< Uploaded data since last counter reset
00196         std::deque<uint32_t> m_upList;   //!< Last 10 upload speed counters
00197         std::deque<uint32_t> m_downList; //!< Last 10 download speed counters
00198         uint32_t m_curUpSpeed;   //!< Current, e.g. last seconds, upspeed
00199         uint32_t m_curDownSpeed; //!< Current, e.g. last seconds, downspeed
00200         //@}
00201 
00202         /**
00203          * Ip addresses in this list are not affected by speed limits; traffic
00204          * to these addresses is not counted towards total traffic. Normally,
00205          * this list contains localhost and LAN ip addresses.
00206          */
00207         RangeList32 m_noSpeedLimit;
00208 public:
00209         //! @name Internal stuff - add new requests
00210         //@{
00211         void addUploadReq(UploadReqBase *r);
00212         void addDloadReq(DownloadReqBase *r);
00213         void addConnReq(ConnReqBase *r);
00214         //@}
00215 
00216         //! @name Modify open connection count
00217         //@{
00218         void addConn() { ++m_connCnt; }
00219         void delConn() { --m_connCnt; }
00220         //@}
00221 
00222         /**
00223          * Check if speed limiting should be applied to specified IP address.
00224          *
00225          * @param ip      Ip address being interested in
00226          * @return        True if limiting should be applied, false otherwise
00227          */
00228         bool isLimited(uint32_t ip) {
00229                 return !m_noSpeedLimit.contains(ip);
00230         }
00231 
00232         static const uint32_t INPUT_BUFSIZE = 100*1024;
00233 };
00234 
00235 #endif