/** * Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef boost::shared_ptr<PartData::UsedRange> UsedRangePtr; class PartData { public: PartData(const std::string &name, uint64_t size); //! Allows modules to register chunk availability maps, so PartData //! can decide the lowest-available chunk to be returned from get* //! methods void addChunkMask(uint32_t chunkSize, std::vector<bool> chunks); //! @name Getters //! All of these take size argument, which indicates how large the //! resulting used range should be. This should match whatever the //! module passes to addChunkMask() in order for getLeastAvailFree() //! to work properly (it relies on that data). //! @{ //! Gets a truly random unused range. UsedRangePtr getRandomFree(uint32_t size); //! Gets next unused range, starting from beginning UsedRangePtr getNextFree(uint32_t size); //! Gets the currnetly least available range UsedRangePtr getLeastAvailFree(uint32_t size); //!@} //! Write method simply writes data starting at specified offset. If //! there are no locks currently on the range, and the range is indeed //! incomplete, everything works. If something goes wrong, exceptions //! will be generated. void write(uint64_t beginOffset, const std::string &data); //! Check for completeness, either the entire file (used internally), or //! a specific subrange (also used internally). Public only for //! completeness. bool isComplete(); bool isComplete(Range64 subRange); private: //! Copying part files is not allowed PartData(const PartData&); PartData& operator=(const PartData&); //! Only allowed by SharedFile ~PartData(); //! UsedRange concept is similar to many thread libraries lock object //! concepts - you retrieve one via get() methods in PartData, and when //! it is destroyed, it takes care that all used/locked ranges do get //! freed properly. This object may only be used when wrapped in //! boost::shared_ptr. class UsedRange : public Range64 { public: //! Hard-lock a subrange. Note that the lock is freed when this //! UsedRange object is destroyed, when the locked range is //! populated via write() method, or via explicit free() call. void lock(Range64 subRange); //! Free a previosly hard-locked range void free(Range64 subRange); //! Identical method as in PartData class, this is provided for //! completeness. void write(uint64_t beginOffset, const std::string &data); private: friend class boost::checked_deleter; friend class PartData; //! Allowed only by PartData. UsedRange keeps a pointer back to //! its parent object, and also sets up event handers as //! neccesery to ensure the pointer remains valid. UsedRange(PartData *parent); //! Destruction is only allowed by PartData (not used) and //! boost::checked_deleter, which is used by shared_ptr wrapper. ~UsedRange(); //! copying is not allowed UsedRange(const UsedRange&); UsedRange& operator=(const UsedRange&); //! Ranges that are locked within this usedrange RangeList64 m_locked; }; //! All that are complete RangeList64 m_complete; //! We keep weak references to all used ranges we have given out, for //! cases where we end up needing to return one of these (e.g. no other //! range can be found). RangeList<boost::weak_ptr<UsedRange> > m_used; //! Availability map. Outer key is chunksize, internal vector contains //! number of times a chunk has been seen on net. std::map<uint32_t, std::vector<uint32_t> > m_avail; };