00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef STXXL_MNG_HEADER
00016 #define STXXL_MNG_HEADER
00017
00018 #include <memory>
00019 #include <iostream>
00020 #include <iomanip>
00021 #include <fstream>
00022 #include <vector>
00023 #include <map>
00024 #include <algorithm>
00025 #include <string>
00026 #include <cstdlib>
00027
00028 #ifdef STXXL_BOOST_CONFIG
00029 #include <boost/config.hpp>
00030 #endif
00031
00032 #ifdef BOOST_MSVC
00033 #include <memory.h>
00034 #endif
00035
00036 #include <stxxl/bits/io/request.h>
00037 #include <stxxl/bits/io/file.h>
00038 #include <stxxl/bits/noncopyable.h>
00039 #include <stxxl/bits/singleton.h>
00040 #include <stxxl/bits/mng/bid.h>
00041 #include <stxxl/bits/mng/diskallocator.h>
00042 #include <stxxl/bits/mng/block_alloc.h>
00043 #include <stxxl/bits/mng/config.h>
00044
00045
00046 __STXXL_BEGIN_NAMESPACE
00047
00052
00054
00057 class block_manager : public singleton<block_manager>
00058 {
00059 friend class singleton<block_manager>;
00060
00061 DiskAllocator ** disk_allocators;
00062 file ** disk_files;
00063
00064 unsigned ndisks;
00065 block_manager();
00066
00067 protected:
00068 template <class BIDType, class DiskAssignFunctor, class BIDIteratorClass>
00069 void new_blocks_int(
00070 const unsigned_type nblocks,
00071 const DiskAssignFunctor & functor,
00072 unsigned_type offset,
00073 BIDIteratorClass out);
00074
00075 public:
00077
00087 template <class DiskAssignFunctor, class BIDIteratorClass>
00088 void new_blocks(
00089 const DiskAssignFunctor & functor,
00090 BIDIteratorClass bidbegin,
00091 BIDIteratorClass bidend,
00092 unsigned_type offset = 0)
00093 {
00094 typedef typename std::iterator_traits<BIDIteratorClass>::value_type bid_type;
00095 new_blocks_int<bid_type>(std::distance(bidbegin, bidend), functor, offset, bidbegin);
00096 }
00097
00109 template <class BlockType, class DiskAssignFunctor, class BIDIteratorClass>
00110 void new_blocks(
00111 const unsigned_type nblocks,
00112 const DiskAssignFunctor & functor,
00113 BIDIteratorClass out,
00114 unsigned_type offset = 0)
00115 {
00116 typedef typename BlockType::bid_type bid_type;
00117 new_blocks_int<bid_type>(nblocks, functor, offset, out);
00118 }
00119
00128 template <typename DiskAssignFunctor, unsigned BLK_SIZE>
00129 void new_block(const DiskAssignFunctor & functor, BID<BLK_SIZE> & bid, unsigned_type offset = 0)
00130 {
00131 new_blocks_int<BID<BLK_SIZE> >(1, functor, offset, &bid);
00132 }
00133
00135
00139 template <class BIDIteratorClass>
00140 void delete_blocks(const BIDIteratorClass & bidbegin, const BIDIteratorClass & bidend);
00141
00144 template <unsigned BLK_SIZE>
00145 void delete_block(const BID<BLK_SIZE> & bid);
00146
00147 ~block_manager();
00148 };
00149
00150
00151 template <class BIDType, class DiskAssignFunctor, class OutputIterator>
00152 void block_manager::new_blocks_int(
00153 const unsigned_type nblocks,
00154 const DiskAssignFunctor & functor,
00155 unsigned_type offset,
00156 OutputIterator out)
00157 {
00158 typedef BIDType bid_type;
00159 typedef BIDArray<bid_type::t_size> bid_array_type;
00160
00161 int_type * bl = new int_type[ndisks];
00162 bid_array_type * disk_bids = new bid_array_type[ndisks];
00163 file ** disk_ptrs = new file *[nblocks];
00164
00165 memset(bl, 0, ndisks * sizeof(int_type));
00166
00167 unsigned_type i;
00168 for (i = 0; i < nblocks; ++i)
00169 {
00170 const int disk = functor(offset + i);
00171 disk_ptrs[i] = disk_files[disk];
00172 bl[disk]++;
00173 }
00174
00175 for (i = 0; i < ndisks; ++i)
00176 {
00177 if (bl[i])
00178 {
00179 disk_bids[i].resize(bl[i]);
00180 const stxxl::int64 old_capacity =
00181 disk_allocators[i]->get_total_bytes();
00182 const stxxl::int64 new_capacity =
00183 disk_allocators[i]->new_blocks(disk_bids[i]);
00184 if (old_capacity != new_capacity)
00185 {
00186
00187 disk_files[i]->set_size(new_capacity);
00188 if (new_capacity != disk_allocators[i]->get_total_bytes())
00189 STXXL_ERRMSG("File resizing failed: actual size " << disk_allocators[i]->get_total_bytes() << " != requested size " << new_capacity);
00190 }
00191 }
00192 }
00193
00194 memset(bl, 0, ndisks * sizeof(int_type));
00195
00196 OutputIterator it = out;
00197 for (i = 0; i != nblocks; ++it, ++i)
00198 {
00199 const int disk = disk_ptrs[i]->get_allocator_id();
00200 bid_type bid(disk_ptrs[i], disk_bids[disk][bl[disk]++].offset);
00201 *it = bid;
00202 STXXL_VERBOSE_BLOCK_LIFE_CYCLE("BLC:new " << FMT_BID(bid));
00203 }
00204
00205 delete[] bl;
00206 delete[] disk_bids;
00207 delete[] disk_ptrs;
00208 }
00209
00210
00211 template <unsigned BLK_SIZE>
00212 void block_manager::delete_block(const BID<BLK_SIZE> & bid)
00213 {
00214
00215
00216 if (!bid.is_managed())
00217 return;
00218 STXXL_VERBOSE_BLOCK_LIFE_CYCLE("BLC:delete " << FMT_BID(bid));
00219 assert(bid.storage->get_allocator_id() >= 0);
00220 disk_allocators[bid.storage->get_allocator_id()]->delete_block(bid);
00221 disk_files[bid.storage->get_allocator_id()]->discard(bid.offset, bid.size);
00222 }
00223
00224
00225 template <class BIDIteratorClass>
00226 void block_manager::delete_blocks(
00227 const BIDIteratorClass & bidbegin,
00228 const BIDIteratorClass & bidend)
00229 {
00230 for (BIDIteratorClass it = bidbegin; it != bidend; it++)
00231 {
00232 delete_block(*it);
00233 }
00234 }
00235
00236
00237 #ifndef STXXL_DEFAULT_BLOCK_SIZE
00238 #define STXXL_DEFAULT_BLOCK_SIZE(type) (2 * 1024 * 1024) // use traits
00239 #endif
00240
00242
00243 __STXXL_END_NAMESPACE
00244
00245 #endif // !STXXL_MNG_HEADER
00246