STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
disk_allocator.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/mng/disk_allocator.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002-2004 Roman Dementiev <[email protected]>
7  * Copyright (C) 2007 Johannes Singler <[email protected]>
8  * Copyright (C) 2009, 2010 Andreas Beckmann <[email protected]>
9  * Copyright (C) 2013 Timo Bingmann <[email protected]>
10  *
11  * Distributed under the Boost Software License, Version 1.0.
12  * (See accompanying file LICENSE_1_0.txt or copy at
13  * http://www.boost.org/LICENSE_1_0.txt)
14  **************************************************************************/
15 
16 #ifndef STXXL_MNG_DISK_ALLOCATOR_HEADER
17 #define STXXL_MNG_DISK_ALLOCATOR_HEADER
18 
21 #include <stxxl/bits/io/file.h>
22 #include <stxxl/bits/mng/bid.h>
23 #include <stxxl/bits/mng/config.h>
24 #include <stxxl/bits/namespace.h>
25 #include <stxxl/bits/noncopyable.h>
26 #include <stxxl/bits/parallel.h>
27 #include <stxxl/bits/verbose.h>
28 
29 #include <algorithm>
30 #include <cassert>
31 #include <functional>
32 #include <map>
33 #include <ostream>
34 #include <utility>
35 
36 
38 
39 //! \ingroup mnglayer
40 //! \{
41 
42 class disk_allocator : private noncopyable
43 {
44  typedef std::pair<stxxl::int64, stxxl::int64> place;
45 
46  struct first_fit : public std::binary_function<place, stxxl::int64, bool>
47  {
48  bool operator () (
49  const place& entry,
50  const stxxl::int64 size) const
51  {
52  return (entry.second >= size);
53  }
54  };
55 
56  typedef std::map<stxxl::int64, stxxl::int64> sortseq;
57 
64  bool autogrow;
65 
66  void dump() const;
67 
68  void deallocation_error(
69  stxxl::int64 block_pos, stxxl::int64 block_size,
70  const sortseq::iterator& pred, const sortseq::iterator& succ) const;
71 
72  // expects the mutex to be locked to prevent concurrent access
73  void add_free_region(stxxl::int64 block_pos, stxxl::int64 block_size);
74 
75  // expects the mutex to be locked to prevent concurrent access
76  void grow_file(stxxl::int64 extend_bytes)
77  {
78  if (!extend_bytes)
79  return;
80 
81  storage->set_size(disk_bytes + extend_bytes);
82  add_free_region(disk_bytes, extend_bytes);
83  disk_bytes += extend_bytes;
84  }
85 
86 public:
87  disk_allocator(stxxl::file* storage, const disk_config& cfg)
88  : free_bytes(0),
89  disk_bytes(0),
90  cfg_bytes(cfg.size),
91  storage(storage),
92  autogrow(cfg.autogrow)
93  {
94  // initial growth to configured file size
95  grow_file(cfg.size);
96  }
97 
99  {
100  if (disk_bytes > cfg_bytes) { // reduce to original size
101  storage->set_size(cfg_bytes);
102  }
103  }
104 
105  inline int64 get_free_bytes() const
106  {
107  return free_bytes;
108  }
109 
110  inline int64 get_used_bytes() const
111  {
112  return disk_bytes - free_bytes;
113  }
114 
115  inline int64 get_total_bytes() const
116  {
117  return disk_bytes;
118  }
119 
120  template <unsigned BLK_SIZE>
122  {
123  new_blocks(bids.begin(), bids.end());
124  }
125 
126  template <unsigned BLK_SIZE>
127  void new_blocks(BID<BLK_SIZE>* begin, BID<BLK_SIZE>* end);
128 
129 #if 0
130  template <unsigned BLK_SIZE>
131  void delete_blocks(const BIDArray<BLK_SIZE>& bids)
132  {
133  for (unsigned i = 0; i < bids.size(); ++i)
134  delete_block(bids[i]);
135  }
136 #endif
137 
138  template <unsigned BLK_SIZE>
139  void delete_block(const BID<BLK_SIZE>& bid)
140  {
141  scoped_mutex_lock lock(mutex);
142 
143  STXXL_VERBOSE2("disk_allocator::delete_block<" << BLK_SIZE <<
144  ">(pos=" << bid.offset << ", size=" << bid.size <<
145  "), free:" << free_bytes << " total:" << disk_bytes);
146 
147  add_free_region(bid.offset, bid.size);
148  }
149 };
150 
151 template <unsigned BLK_SIZE>
152 void disk_allocator::new_blocks(BID<BLK_SIZE>* begin, BID<BLK_SIZE>* end)
153 {
154  stxxl::int64 requested_size = 0;
155 
156  for (typename BIDArray<BLK_SIZE>::iterator cur = begin; cur != end; ++cur)
157  {
158  STXXL_VERBOSE2("Asking for a block with size: " << (cur->size));
159  requested_size += cur->size;
160  }
161 
162  scoped_mutex_lock lock(mutex);
163 
164  STXXL_VERBOSE2("disk_allocator::new_blocks<BLK_SIZE>, BLK_SIZE = " << BLK_SIZE <<
165  ", free:" << free_bytes << " total:" << disk_bytes <<
166  ", blocks: " << (end - begin) <<
167  " begin: " << static_cast<void*>(begin) <<
168  " end: " << static_cast<void*>(end) <<
169  ", requested_size=" << requested_size);
170 
171  if (free_bytes < requested_size)
172  {
173  if (!autogrow) {
174  STXXL_ERRMSG("External memory block allocation error: " << requested_size <<
175  " bytes requested, " << free_bytes <<
176  " bytes free. Trying to extend the external memory space...");
177  }
178 
179  grow_file(requested_size);
180  }
181 
182  // dump();
183 
184  sortseq::iterator space;
185  space = std::find_if(free_space.begin(), free_space.end(),
186  bind2nd(first_fit(), requested_size) _STXXL_FORCE_SEQUENTIAL);
187 
188  if (space == free_space.end() && requested_size == BLK_SIZE)
189  {
190  assert(end - begin == 1);
191 
192  if (!autogrow) {
193  STXXL_ERRMSG("Warning: Severe external memory space fragmentation!");
194  dump();
195 
196  STXXL_ERRMSG("External memory block allocation error: " << requested_size <<
197  " bytes requested, " << free_bytes <<
198  " bytes free. Trying to extend the external memory space...");
199  }
200 
201  grow_file(BLK_SIZE);
202 
203  space = std::find_if(free_space.begin(), free_space.end(),
204  bind2nd(first_fit(), requested_size) _STXXL_FORCE_SEQUENTIAL);
205  }
206 
207  if (space != free_space.end())
208  {
209  stxxl::int64 region_pos = (*space).first;
210  stxxl::int64 region_size = (*space).second;
211  free_space.erase(space);
212  if (region_size > requested_size)
213  free_space[region_pos + requested_size] = region_size - requested_size;
214 
215  for (stxxl::int64 pos = region_pos; begin != end; ++begin)
216  {
217  begin->offset = pos;
218  pos += begin->size;
219  }
220  free_bytes -= requested_size;
221  //dump();
222 
223  return;
224  }
225 
226  // no contiguous region found
227  STXXL_VERBOSE1("Warning, when allocating an external memory space, no contiguous region found");
228  STXXL_VERBOSE1("It might harm the performance");
229 
230  assert(requested_size > BLK_SIZE);
231  assert(end - begin > 1);
232 
233  lock.unlock();
234 
235  BID<BLK_SIZE>* middle = begin + ((end - begin) / 2);
236  new_blocks(begin, middle);
237  new_blocks(middle, end);
238 }
239 
240 //! \}
241 
243 
244 #endif // !STXXL_MNG_DISK_ALLOCATOR_HEADER
245 // vim: et:ts=4:sw=4
stxxl::int64 disk_bytes
long long int int64
Definition: types.h:40
void delete_block(const BID< BLK_SIZE > &bid)
stxxl::int64 cfg_bytes
stxxl::file * storage
stxxl::int64 free_bytes
void unlock()
unlock mutex hold prematurely
Definition: mutex.h:127
int64 get_used_bytes() const
#define STXXL_VERBOSE2(x)
Definition: verbose.h:107
Block size.
Definition: bid.h:46
size_type size() const
return number of items in vector
iterator end()
return mutable iterator beyond last element
std::map< stxxl::int64, stxxl::int64 > sortseq
std::pair< stxxl::int64, stxxl::int64 > place
void grow_file(stxxl::int64 extend_bytes)
Defines interface of file.
Definition: file.h:52
Encapsulate the configuration of one &quot;disk&quot;. The disk is actually a file I/O object which block_manag...
Definition: config.h:35
Block identifier class.
Definition: bid.h:42
iterator begin()
return mutable iterator to first element
Definition: simple_vector.h:92
Aquire a lock that&#39;s valid until the end of scope.
Definition: mutex.h:106
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
int64 get_total_bytes() const
#define STXXL_VERBOSE1(x)
Definition: verbose.h:99
int64 get_free_bytes() const
void new_blocks(BIDArray< BLK_SIZE > &bids)
#define STXXL_ERRMSG(x)
Definition: verbose.h:79
disk_allocator(stxxl::file *storage, const disk_config &cfg)
stxxl::int64 offset
offset within the file of the block
Definition: bid.h:51
#define _STXXL_FORCE_SEQUENTIAL
Definition: parallel.h:51
uint64 size
file size to initially allocate
Definition: config.h:45
#define STXXL_END_NAMESPACE
Definition: namespace.h:17