kwave  18.07.70
Kwave::SwapFile Class Reference

#include <SwapFile.h>

Collaboration diagram for Kwave::SwapFile:
Collaboration graph

Public Member Functions

 SwapFile (const QString &name)
 
virtual ~SwapFile ()
 
bool allocate (size_t size)
 
void * address () const
 
size_t size () const
 
int mapCount () const
 
size_t pagesize () const
 
bool resize (size_t size)
 
void * map ()
 
int unmap ()
 
int read (unsigned int offset, void *buffer, unsigned int length)
 
int write (unsigned int offset, const void *buffer, unsigned int length)
 

Private Member Functions

void close ()
 

Private Attributes

QTemporaryFile m_file
 
void * m_address
 
size_t m_size
 
size_t m_pagesize
 
int m_map_count
 

Detailed Description

Definition at line 32 of file SwapFile.h.

Constructor & Destructor Documentation

◆ SwapFile()

Kwave::SwapFile::SwapFile ( const QString &  name)
explicit

Constructor

Parameters
namefull path to the swap file, actually a template that must contain 6 "X" characters at the end!

Definition at line 37 of file SwapFile.cpp.

References g_instances, m_pagesize, and Kwave::toInt().

38  :m_file(name), m_address(Q_NULLPTR), m_size(0), m_pagesize(0), m_map_count(0)
39 {
40  // determine the system's native page size
41 #if defined(HAVE_GETPAGESIZE)
42  if (!m_pagesize) m_pagesize = getpagesize();
43 #endif
44 #if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
45  if (!m_pagesize) m_pagesize = sysconf(_SC_PAGESIZE);
46 #endif
47 
48  // fallback: assume 4kB pagesize
49  if (Kwave::toInt(m_pagesize) <= 0) {
50  qWarning("SwapFile: unable to determine page size, using fallback");
51  m_pagesize = (4 << 10);
52  }
53 
54  g_instances++;
55 }
const char name[16]
Definition: memcpy.c:510
size_t m_pagesize
Definition: SwapFile.h:135
int toInt(T x)
Definition: Utils.h:127
size_t m_size
Definition: SwapFile.h:132
void * m_address
Definition: SwapFile.h:129
static unsigned int g_instances
Definition: SwapFile.cpp:28
QTemporaryFile m_file
Definition: SwapFile.h:126
Here is the call graph for this function:

◆ ~SwapFile()

Kwave::SwapFile::~SwapFile ( )
virtual

Destructor

Definition at line 58 of file SwapFile.cpp.

References close(), and g_instances.

59 {
60  close();
61  g_instances--;
62 }
static unsigned int g_instances
Definition: SwapFile.cpp:28
Here is the call graph for this function:

Member Function Documentation

◆ address()

void* Kwave::SwapFile::address ( ) const
inline

Returns the address of the allocated memory or 0 if nothing has been allocated.

Definition at line 58 of file SwapFile.h.

References m_address.

Referenced by Kwave::MemoryManager::map(), and Kwave::MemoryManager::readFrom().

58 { return m_address; }
void * m_address
Definition: SwapFile.h:129
Here is the caller graph for this function:

◆ allocate()

bool Kwave::SwapFile::allocate ( size_t  size)

Allocates virtual memory by creating an empty swap file. Must be mapped into memory before used.

Parameters
sizenumber of bytes to allocate
Returns
true if succeeded, false if failed

Definition at line 65 of file SwapFile.cpp.

References close(), DBG, m_address, m_file, m_pagesize, m_size, size(), and Kwave::toUint().

Referenced by Kwave::MemoryManager::allocateVirtual().

66 {
67  Q_ASSERT(!m_address); // MUST NOT be mapped !
68  if (m_address) return false;
69 
70  if (m_size) close();
71 // qDebug("SwapFile::allocate(%u), instances: %u",
72 // Kwave::toUint(size), g_instances);
73 
74  // try to create the temporary file
75  if (!m_file.open()) {
76  qWarning("SwapFile(%s) -> open failed", DBG(m_file.fileName()));
77  return false;
78  }
79 
80  // when it is created, also try to unlink it so that it will always
81  // be removed, even if the application crashes !
82 #ifdef HAVE_UNLINK
83  unlink(m_file.fileName().toLocal8Bit().data());
84 #endif /* HAVE_UNLINK */
85 
86  // round up the new size to a full page
87  size_t rounded = Kwave::round_up<size_t>(size, m_pagesize);
88 
89  // touch each new page in order to *really* allocate the disk space
90  size_t offset = 0;
91  while (offset < rounded) {
92  // qDebug("SwapFile: touching at offset 0x%08X",
93  // Kwave::toUint(offset));
94  m_file.seek(offset);
95  m_file.putChar(0);
96  m_file.flush();
97  if (m_file.pos() != static_cast<qint64>(offset + 1)) {
98  qWarning("SwapFile::allocate(): seek failed. DISK FULL !?");
99  return false;
100  }
101  offset += m_pagesize;
102  }
103 
104  m_file.seek(rounded - 1);
105  m_file.putChar(0);
106  m_file.flush();
107  if (m_file.pos() + 1 < static_cast<qint64>(size)) {
108  qWarning("SwapFile::allocate(%d MB) failed, DISK FULL ?",
109  Kwave::toUint(size >> 20));
110  m_size = 0;
111  return false;
112  }
113 
114  // now the size is valid
115  m_size = size;
116 
117 // qDebug("SwapFile::allocate(%d kB)",size >> 10);
118  return true;
119 }
size_t m_pagesize
Definition: SwapFile.h:135
size_t size() const
Definition: SwapFile.h:64
size_t m_size
Definition: SwapFile.h:132
#define DBG(qs)
Definition: String.h:55
unsigned int toUint(T x)
Definition: Utils.h:109
void * m_address
Definition: SwapFile.h:129
QTemporaryFile m_file
Definition: SwapFile.h:126
Here is the call graph for this function:
Here is the caller graph for this function:

◆ close()

void Kwave::SwapFile::close ( )
private

Frees the allocated memory by unmapping and deleting the swap file.

Definition at line 187 of file SwapFile.cpp.

References DBG, m_address, m_file, m_map_count, and m_size.

Referenced by allocate(), pagesize(), resize(), and ~SwapFile().

188 {
189  Q_ASSERT(!m_map_count);
190  if (m_address) m_file.unmap(static_cast<uchar *>(m_address));
191  m_address = Q_NULLPTR;
192  m_size = 0;
193 
194  m_file.resize(0);
195  if (m_file.isOpen()) m_file.close();
196 
197  if (m_file.exists(m_file.fileName())) {
198  if (!m_file.remove()) {
199  qWarning("SwapFile(%s) -> remove FAILED", DBG(m_file.fileName()));
200  }
201  }
202 
203 }
size_t m_size
Definition: SwapFile.h:132
#define DBG(qs)
Definition: String.h:55
void * m_address
Definition: SwapFile.h:129
QTemporaryFile m_file
Definition: SwapFile.h:126
Here is the caller graph for this function:

◆ map()

void * Kwave::SwapFile::map ( )

Map the memory and return the physical address.

Returns
pointer to the mapped area or null if failed

Definition at line 206 of file SwapFile.cpp.

References DBG, m_address, m_file, m_map_count, and m_size.

Referenced by Kwave::MemoryManager::map(), and pagesize().

207 {
208 // qDebug(" SwapFile::map() - m_size=%u", m_size);
209 
210  // shortcut if already mapped
211  if (m_map_count) {
212  m_map_count++;
213  Q_ASSERT(m_address);
214  return m_address;
215  }
216 
217  m_file.flush();
218 
219  m_address = m_file.map(0, m_size, QFile::NoOptions);
220 
221  // map -1 to null pointer
222  if (m_address == reinterpret_cast<void *>(-1)) m_address = Q_NULLPTR;
223 
224  // if succeeded, increase map reference counter
225  if (m_address) {
226  m_map_count++;
227  } else {
228  qWarning("SwapFile(%s) -> map FAILED", DBG(m_file.fileName()));
229  }
230 
231  return m_address;
232 }
size_t m_size
Definition: SwapFile.h:132
#define DBG(qs)
Definition: String.h:55
void * m_address
Definition: SwapFile.h:129
QTemporaryFile m_file
Definition: SwapFile.h:126
Here is the caller graph for this function:

◆ mapCount()

int Kwave::SwapFile::mapCount ( ) const
inline

returns the map count

Definition at line 67 of file SwapFile.h.

References m_map_count.

Referenced by Kwave::MemoryManager::free(), Kwave::MemoryManager::map(), Kwave::MemoryManager::readFrom(), Kwave::MemoryManager::unmap(), and Kwave::MemoryManager::unmapFromCache().

67 { return m_map_count; }
Here is the caller graph for this function:

◆ pagesize()

size_t Kwave::SwapFile::pagesize ( ) const
inline

Returns the size of one storage unit in bytes

Definition at line 72 of file SwapFile.h.

References close(), m_pagesize, map(), read(), resize(), unmap(), and write().

72 { return m_pagesize; }
size_t m_pagesize
Definition: SwapFile.h:135
Here is the call graph for this function:

◆ read()

int Kwave::SwapFile::read ( unsigned int  offset,
void *  buffer,
unsigned int  length 
)

Read bytes into a buffer

Parameters
offsetoffset within the file [bytes]
bufferpointer to a buffer that is to be filled
lengthnumber of bytes to read
Returns
number of read bytes or < 0 if failed

Definition at line 258 of file SwapFile.cpp.

References m_file, and Kwave::toInt().

Referenced by Kwave::MemoryManager::convertToPhysical(), pagesize(), and Kwave::MemoryManager::readFrom().

260 {
261  // seek to the given offset
262  if (!m_file.seek(offset)) return -1;
263 
264  // read into the buffer
265  if (!m_file.flush()) return -1;
266 
267  if (length > INT_MAX) length = INT_MAX;
268  return Kwave::toInt(
269  m_file.read(reinterpret_cast<char *>(buffer), length)
270  );
271 }
int toInt(T x)
Definition: Utils.h:127
QTemporaryFile m_file
Definition: SwapFile.h:126
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resize()

bool Kwave::SwapFile::resize ( size_t  size)

Resizes the allocated swap file.

Parameters
sizethe new size
Returns
true if successful or false if failed

Definition at line 122 of file SwapFile.cpp.

References BLOCK_SIZE, close(), m_address, m_file, m_map_count, m_pagesize, m_size, MINIMUM_SIZE, and size().

Referenced by pagesize(), and Kwave::MemoryManager::resize().

123 {
124  Q_ASSERT(!m_address); // MUST NOT be mappped !
125  Q_ASSERT(!m_map_count);
126  if (m_address || m_map_count) return false;
127  if (size == m_size) return true; // nothing to do
128 
129  // special case: shutdown
130  if (size == 0) {
131  close();
132  return true;
133  }
134 
135  // this file seems to be a growing one:
136  // round up the new size to a full block
137  size_t rounded = Kwave::round_up<size_t>(size, BLOCK_SIZE);
138 
139  // optimization: if rounded size already matches -> done
140  if (rounded == m_size) {
141 // qDebug("SwapFile::resize(%u MB) -> skipped, already big enough",
142 // Kwave::toUint(size >> 20));
143  return true;
144  }
145 
146  // do not shrink below minimum size
147  if ((size < m_size) && (size < MINIMUM_SIZE)) {
148 // qDebug("SwapFile::resize(%u MB) -> skipped, limited by min size",
149 // Kwave::toUint(size >> 20));
150  return true;
151  }
152 
153  // resize the file
154  // qDebug("SwapFile::resize(%u)", size);
155 
156  // touch each new page in order to *really* allocate the disk space
157  size_t offset = static_cast<size_t>((m_size + m_pagesize - 1) / m_pagesize);
158  while (offset < rounded) {
159 // qDebug("SwapFile: touching at offset 0x%08X",
160 // Kwave::toUint(offset));
161  m_file.seek(offset);
162  m_file.putChar(0);
163  m_file.flush();
164  if (m_file.pos() != static_cast<qint64>(offset + 1)) {
165  qWarning("SwapFile::resize(): seek failed. DISK FULL !?");
166  return false;
167  }
168  offset += m_pagesize;
169  }
170 
171  bool ok = true;
172  ok &= m_file.resize(rounded);
173  ok &= m_file.seek(rounded - 1);
174  ok &= m_file.putChar(0);
175  ok &= m_file.flush();
176  if (ok) {
177  m_size = rounded;
178  } else {
179  qWarning("SwapFile::resize(): failed. DISK FULL !?");
180  }
181 
182 // qDebug("SwapFile::resize() to size=%u", m_size);
183  return ok;
184 }
#define BLOCK_SIZE
Definition: SwapFile.cpp:34
#define MINIMUM_SIZE
Definition: SwapFile.cpp:31
size_t m_pagesize
Definition: SwapFile.h:135
size_t size() const
Definition: SwapFile.h:64
size_t m_size
Definition: SwapFile.h:132
void * m_address
Definition: SwapFile.h:129
QTemporaryFile m_file
Definition: SwapFile.h:126
Here is the call graph for this function:
Here is the caller graph for this function:

◆ size()

size_t Kwave::SwapFile::size ( ) const
inline

◆ unmap()

int Kwave::SwapFile::unmap ( )

Unmap a memory area, previously mapped with map()

Returns
current reference count

Definition at line 235 of file SwapFile.cpp.

References DBG, m_address, m_file, m_map_count, and m_size.

Referenced by pagesize(), Kwave::MemoryManager::unmap(), and Kwave::MemoryManager::unmapFromCache().

236 {
237  Q_ASSERT(m_address);
238  Q_ASSERT(m_size);
239  Q_ASSERT(m_map_count);
240 
241  // first decrease refcount and do nothing if not zero
242  if (!m_map_count) return 0;
243  if (--m_map_count) return m_map_count;
244 
245  // really do the unmap
246  if (m_size && m_address) {
247 // qDebug(" --- SwapFile::unmap() (%p)", this);
248  if (!m_file.unmap(static_cast<uchar *>(m_address))) {
249  qWarning("SwapFile(%s) -> unmap FAILED", DBG(m_file.fileName()));
250  }
251  }
252 
253  m_address = Q_NULLPTR;
254  return m_map_count;
255 }
size_t m_size
Definition: SwapFile.h:132
#define DBG(qs)
Definition: String.h:55
void * m_address
Definition: SwapFile.h:129
QTemporaryFile m_file
Definition: SwapFile.h:126
Here is the caller graph for this function:

◆ write()

int Kwave::SwapFile::write ( unsigned int  offset,
const void *  buffer,
unsigned int  length 
)

Write bytes from a buffer

Parameters
offsetoffset within the file [bytes]
bufferpointer to a buffer with data
lengthnumber of bytes to write
Returns
number of written bytes or < 0 if failed

Definition at line 274 of file SwapFile.cpp.

References m_file, and Kwave::toInt().

Referenced by Kwave::MemoryManager::convertToVirtual(), pagesize(), and Kwave::MemoryManager::writeTo().

276 {
277  // seek to the given offset
278  if (!m_file.seek(offset)) return -1;
279 
280  // write data from the buffer
281  if (length > INT_MAX) length = INT_MAX;
282  return Kwave::toInt(
283  m_file.write(reinterpret_cast<const char *>(buffer), length)
284  );
285 }
int toInt(T x)
Definition: Utils.h:127
QTemporaryFile m_file
Definition: SwapFile.h:126
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_address

void* Kwave::SwapFile::m_address
private

address of the allocated virtual memory or 0

Definition at line 129 of file SwapFile.h.

Referenced by address(), allocate(), close(), map(), resize(), and unmap().

◆ m_file

QTemporaryFile Kwave::SwapFile::m_file
private

file used for swapping

Definition at line 126 of file SwapFile.h.

Referenced by allocate(), close(), map(), read(), resize(), unmap(), and write().

◆ m_map_count

int Kwave::SwapFile::m_map_count
private

reference count for mmap [0...N]

Definition at line 138 of file SwapFile.h.

Referenced by close(), map(), mapCount(), resize(), and unmap().

◆ m_pagesize

size_t Kwave::SwapFile::m_pagesize
private

size of one storage unit

Definition at line 135 of file SwapFile.h.

Referenced by allocate(), pagesize(), resize(), and SwapFile().

◆ m_size

size_t Kwave::SwapFile::m_size
private

number of allocated bytes or 0

Definition at line 132 of file SwapFile.h.

Referenced by allocate(), close(), map(), resize(), size(), and unmap().


The documentation for this class was generated from the following files: