1 /* 2 * swarmmanager.h 3 * 4 * Arno: Classes for managing FileTransfers, that is, load them into memory or 5 * release them when idle. This is called activation/deactivation. 6 * This manager only manages FileTransfers, LiveTransfers are unmanaged, 7 * i.e., always activated. 8 * 9 * The activation/deactivation progress is hidden behind the swift API, 10 * one should not use the SwarmManager directly. 11 * 12 * ARNOTODO: tracker registration. The current implementation works if it 13 * runs the primary seeder which is also the tracker for a swarm. Clients 14 * that contact it will activate the swarm. Once a swarm no longer has 15 * clients is can be deactivated (not currently implemented). 16 * 17 * However, to be a non-primary seeder (i.e., not the tracker) a new 18 * mechanism needs to be implemented that registers a swarm at a tracker 19 * while being deactivated (activate only when clients come). In the present 20 * swift design registration requires a Channel to be open to the tracker. This 21 * design may need to be changed to allow for a BitTorrent register-for-30-mins 22 * -and-disconnect style. 23 * 24 * Current implementation will deactivate: 25 * - when SetMaximumActiveSwarms() is exceeded (Thomas) 26 * - when idle for more than SECONDS_UNUSED_UNTIL_SWARM_MAY_BE_DEACTIVATED. 27 * Idle is when no Read(), Write() or DATA send or receive (Arno) 28 * (see ContentTransfer::GlobalCleanCallback). 29 * 30 * Note that FileTransfers with the zero-state implementation are actually 31 * unloaded (=no FileTransfer object and no admin in SwarmManager) when idle, 32 * see zerostate.cpp. This is orthogonal to idle deactivation. 33 * 34 * Created by Thomas Schaap 35 * Copyright 2009-2016 TECHNISCHE UNIVERSITEIT DELFT. All rights reserved. 36 * 37 */ 38 39 #include <time.h> 40 #include <vector> 41 #include <list> 42 #include "hashtree.h" 43 44 namespace swift 45 { 46 class SwarmManager; 47 48 class SwarmData 49 { 50 protected: 51 int id_; 52 Sha1Hash rootHash_; 53 bool active_; 54 tint latestUse_; 55 bool stateToBeRemoved_; 56 bool contentToBeRemoved_; 57 FileTransfer* ft_; 58 std::string filename_; 59 std::string trackerurl_; 60 bool forceCheckDiskVSHash_; 61 popt_cont_int_prot_t contIntProtMethod_; 62 uint32_t chunkSize_; 63 bool zerostate_; 64 double cachedMaxSpeeds_[2]; 65 bool cachedStorageReady_; 66 std::list<std::string> cachedStorageFilenames_; 67 uint64_t cachedSize_; 68 bool cachedIsComplete_; 69 uint64_t cachedComplete_; 70 std::string cachedOSPathName_; 71 std::list< std::pair<ProgressCallback, uint8_t> > cachedCallbacks_; //ARNOTODO: how does this work? 72 uint64_t cachedSeqComplete_; // Only for offset = 0 73 bool cached_; 74 std::string metadir_; 75 public: 76 SwarmData(const std::string filename, const Sha1Hash& rootHash, const std::string trackerurl, 77 bool force_check_diskvshash, popt_cont_int_prot_t cipm, bool zerostate, uint32_t chunk_size, 78 const std::string metadata=""); 79 SwarmData(const SwarmData& sd); 80 81 ~SwarmData(); 82 83 bool Touch(bool onlyifactive=true); 84 bool IsActive(); 85 const Sha1Hash& RootHash(); 86 int Id(); 87 FileTransfer* GetTransfer(bool touch = true); 88 std::string& Filename(); 89 std::string Tracker(); 90 uint32_t ChunkSize(); 91 bool IsZeroState(); 92 std::string Metadir(); 93 94 // Find out cached values of non-active swarms 95 uint64_t Size(); 96 bool IsComplete(); 97 uint64_t Complete(); 98 uint64_t SeqComplete(int64_t offset = 0); 99 std::string OSPathName(); 100 101 void SetMaxSpeed(data_direction_t ddir, double speed); 102 void AddProgressCallback(ProgressCallback cb, uint8_t agg); 103 void RemoveProgressCallback(ProgressCallback cb); 104 105 friend class SwarmManager; 106 }; 107 108 class SwarmManager 109 { 110 protected: 111 SwarmManager(); 112 ~SwarmManager(); 113 114 115 // Singleton 116 static SwarmManager instance_; 117 118 // Structures to keep track of all the swarms known to this manager 119 // That's two lists of swarms, indeed. 120 // The first allows very fast lookups 121 // - hash table (bucket is rootHash.bits[0]&63) containing lists ordered by rootHash (binary search possible) 122 // The second allows very fast access by numeric identifier (used in toplevel API) 123 // - just a vector with a new element for each new one, and a list of available indices 124 std::vector< std::vector<SwarmData*> > knownSwarms_; 125 std::vector<SwarmData*> swarmList_; 126 struct UnusedIndex { 127 int index; 128 tint since; 129 }; 130 std::list<struct UnusedIndex> unusedIndices_; 131 132 // Structures and functions for deferred removal of active swarms 133 struct event* eventCheckToBeRemoved_; 134 static void CheckSwarmsToBeRemovedCallback(evutil_socket_t fd, short events, void* arg); 135 void CheckSwarmsToBeRemoved(); 136 137 // Looking up swarms by rootHash, internal functions 138 int GetSwarmLocation(const std::vector<SwarmData*>& list, const Sha1Hash& rootHash); 139 SwarmData* GetSwarmData(const Sha1Hash& rootHash); 140 141 // Internal activation method 142 SwarmData* ActivateSwarm(SwarmData* swarm); 143 void BuildSwarm(SwarmData* swarm); 144 145 // Internal method to find the oldest swarm and deactivate it 146 bool DeactivateSwarm(); 147 void DeactivateSwarm(SwarmData* swarm, int activeLoc); 148 149 // Structures to keep track of active swarms 150 int maxActiveSwarms_; 151 int activeSwarmCount_; 152 std::vector<SwarmData*> activeSwarms_; 153 154 #if SWARMMANAGER_ASSERT_INVARIANTS 155 void invariant(); 156 #endif 157 public: 158 // Singleton 159 static SwarmManager& GetManager(); 160 161 // Add and remove swarms 162 SwarmData* AddSwarm(const std::string filename, const Sha1Hash& rootHash, const std::string trackerurl, 163 bool force_check_diskvshash, popt_cont_int_prot_t cipm, bool zerostate, bool activate, uint32_t chunk_size, 164 std::string metadir); 165 SwarmData* AddSwarm(const SwarmData& swarm, bool activate=true); 166 void RemoveSwarm(const Sha1Hash& rootHash, bool removeState = false, bool removeContent = false); 167 168 // Find a swam, either by id or root hash 169 SwarmData* FindSwarm(int id); 170 SwarmData* FindSwarm(const Sha1Hash& rootHash); 171 172 // Activate a swarm, so it can be used (not active swarms can't be read from/written to) 173 SwarmData* ActivateSwarm(const Sha1Hash& rootHash); 174 void DeactivateSwarm(const Sha1Hash& rootHash); 175 176 // Manage maximum of active swarms 177 int GetMaximumActiveSwarms(); 178 void SetMaximumActiveSwarms(int newMaxActiveSwarms); 179 180 // Arno 181 tdlist_t GetTransferDescriptors(); 182 // Arno: Called periodically to deactivate unused swarms, even if max not reached 183 void DeactivateIdleSwarms(); 184 185 class Iterator : public std::iterator<std::input_iterator_tag, SwarmData*> 186 { 187 protected: 188 int transfer_; 189 public: 190 Iterator(); 191 Iterator(int transfer); 192 Iterator(const Iterator& other); 193 Iterator& operator++(); 194 Iterator operator++(int); 195 bool operator==(const Iterator& other); 196 bool operator!=(const Iterator& other); 197 SwarmData* operator*(); 198 }; 199 friend class Iterator; 200 Iterator begin(); 201 Iterator end(); 202 }; 203 } 204