comparison base/MatrixFileCache.cpp @ 93:27d726916ab3

* Remove mmap-based code again. We can be more efficient with read().
author Chris Cannam
date Wed, 03 May 2006 16:47:04 +0000
parents 1dcf41ed3863
children 040a151d0897
comparison
equal deleted inserted replaced
92:4988de098b25 93:27d726916ab3
28 28
29 #include <QFileInfo> 29 #include <QFileInfo>
30 #include <QFile> 30 #include <QFile>
31 #include <QDir> 31 #include <QDir>
32 32
33 //#define HAVE_MMAP 1
34
35 #ifdef HAVE_MMAP
36 #include <sys/mman.h>
37 #endif
38
39 std::map<QString, int> MatrixFileCache::m_refcount; 33 std::map<QString, int> MatrixFileCache::m_refcount;
40 QMutex MatrixFileCache::m_refcountMutex; 34 QMutex MatrixFileCache::m_refcountMutex;
41 35
42 //!!! This class is a work in progress -- it does only as much as we 36 //!!! This class is a work in progress -- it does only as much as we
43 // need for the current SpectrogramLayer. Slated for substantial 37 // need for the current SpectrogramLayer. Slated for substantial
52 m_autoRegionWidth(256), 46 m_autoRegionWidth(256),
53 m_off(-1), 47 m_off(-1),
54 m_rx(0), 48 m_rx(0),
55 m_rw(0), 49 m_rw(0),
56 m_userRegion(false), 50 m_userRegion(false),
57 m_region(0), 51 m_region(0)
58 m_mmapped(false),
59 m_mmapSize(0),
60 m_mmapOff(0),
61 m_preferMmap(false)
62 { 52 {
63 // Ensure header size is a multiple of the size of our data (for 53 // Ensure header size is a multiple of the size of our data (for
64 // alignment purposes) 54 // alignment purposes)
65 size_t hs = ((m_headerSize / sizeof(float)) * sizeof(float)); 55 size_t hs = ((m_headerSize / sizeof(float)) * sizeof(float));
66 if (hs != m_headerSize) m_headerSize = hs + sizeof(float); 56 if (hs != m_headerSize) m_headerSize = hs + sizeof(float);
119 } 109 }
120 110
121 MatrixFileCache::~MatrixFileCache() 111 MatrixFileCache::~MatrixFileCache()
122 { 112 {
123 if (m_rw > 0) { 113 if (m_rw > 0) {
124 if (m_mmapped) { 114 delete[] m_region;
125 #ifdef HAVE_MMAP
126 ::munmap(m_region, m_mmapSize);
127 #endif
128 } else {
129 delete[] m_region;
130 }
131 } 115 }
132 116
133 if (m_fd >= 0) { 117 if (m_fd >= 0) {
134 if (::close(m_fd) < 0) { 118 if (::close(m_fd) < 0) {
135 ::perror("MatrixFileCache::~MatrixFileCache: close failed"); 119 ::perror("MatrixFileCache::~MatrixFileCache: close failed");
171 155
172 off_t off = m_headerSize + (w * h * sizeof(float)); 156 off_t off = m_headerSize + (w * h * sizeof(float));
173 157
174 if (w * h > m_width * m_height) { 158 if (w * h > m_width * m_height) {
175 159
176 #ifdef HAVE_MMAP 160 /*!!!
177 // If we're going to mmap the file, we need to ensure it's long 161 // If we're going to mmap the file, we need to ensure it's long
178 // enough beforehand 162 // enough beforehand
179 163
180 if (m_preferMmap) { 164 if (m_preferMmap) {
181 165
191 float f(0); 175 float f(0);
192 if (::write(m_fd, &f, sizeof(float)) != sizeof(float)) { 176 if (::write(m_fd, &f, sizeof(float)) != sizeof(float)) {
193 ::perror("WARNING: MatrixFileCache::resize: write failed"); 177 ::perror("WARNING: MatrixFileCache::resize: write failed");
194 } 178 }
195 } 179 }
196 #endif 180 */
197
198 } else { 181 } else {
199 182
200 if (::ftruncate(m_fd, off) < 0) { 183 if (::ftruncate(m_fd, off) < 0) {
201 ::perror("WARNING: MatrixFileCache::resize: ftruncate failed"); 184 ::perror("WARNING: MatrixFileCache::resize: ftruncate failed");
202 } 185 }
356 { 339 {
357 if (m_rw == 0) return 0; 340 if (m_rw == 0) return 0;
358 341
359 float *region = m_region; 342 float *region = m_region;
360 343
361 if (m_mmapOff > 0) {
362 char *cr = (char *)m_region;
363 cr += m_mmapOff;
364 region = (float *)cr;
365 }
366
367 float *ptr = &(region[(x - m_rx) * m_height + y]); 344 float *ptr = &(region[(x - m_rx) * m_height + y]);
368 345
369 // std::cerr << "getRegionPtr(" << x << "," << y << "): region is " << m_region << ", returning " << ptr << std::endl; 346 // std::cerr << "getRegionPtr(" << x << "," << y << "): region is " << m_region << ", returning " << ptr << std::endl;
370 return ptr; 347 return ptr;
371 } 348 }
388 { 365 {
389 if (!user && m_userRegion) return false; 366 if (!user && m_userRegion) return false;
390 if (m_rw > 0 && x >= m_rx && x + width <= m_rx + m_rw) return true; 367 if (m_rw > 0 && x >= m_rx && x + width <= m_rx + m_rw) return true;
391 368
392 if (m_rw > 0) { 369 if (m_rw > 0) {
393 if (m_mmapped) { 370 delete[] m_region;
394 #ifdef HAVE_MMAP
395 ::munmap(m_region, m_mmapSize);
396 std::cerr << "unmapped " << m_mmapSize << " at " << m_region << std::endl;
397 #endif
398 } else {
399 delete[] m_region;
400 }
401 m_region = 0; 371 m_region = 0;
402 m_mmapped = false;
403 m_mmapSize = 0;
404 m_mmapOff = 0;
405 m_rw = 0; 372 m_rw = 0;
406 } 373 }
407 374
408 if (width == 0) { 375 if (width == 0) {
409 return true; 376 return true;
410 } 377 }
411
412 #ifdef HAVE_MMAP
413
414 if (m_preferMmap) {
415
416 size_t mmapSize = m_height * width * sizeof(float);
417 off_t offset = m_headerSize + (x * m_height) * sizeof(float);
418 int pagesize = getpagesize();
419 off_t aligned = (offset / pagesize) * pagesize;
420 size_t mmapOff = offset - aligned;
421 mmapSize += mmapOff;
422
423 m_region = (float *)
424 ::mmap(0, mmapSize, PROT_READ, MAP_PRIVATE, m_fd, aligned);
425
426 if (m_region == MAP_FAILED) {
427
428 ::perror("Mmap failed");
429 std::cerr << "ERROR: MatrixFileCache::setRegion(" << x << ", "
430 << width << "): Mmap(0, " << mmapSize
431 << ", " << PROT_READ << ", " << MAP_SHARED << ", " << m_fd
432 << ", " << aligned << ") failed, falling back to "
433 << "non-mmapping code for this cache" << std::endl;
434 m_preferMmap = false;
435
436 } else {
437
438 std::cerr << "mmap succeeded (offset " << aligned << ", size " << mmapSize << ", m_mmapOff " << mmapOff << ") = " << m_region << std::endl;
439
440 m_mmapped = true;
441 m_mmapSize = mmapSize;
442 m_mmapOff = mmapOff;
443 m_rx = x;
444 m_rw = width;
445 if (user) m_userRegion = true;
446 MUNLOCK(m_region, m_mmapSize);
447 return true;
448 }
449 }
450 #endif
451 378
452 if (!seekTo(x, 0)) return false; 379 if (!seekTo(x, 0)) return false;
453 380
454 m_region = new float[width * m_height]; 381 m_region = new float[width * m_height];
455 MUNLOCK(m_region, width * m_height * sizeof(float)); 382 MUNLOCK(m_region, width * m_height * sizeof(float));