SnapshotItem(const IFileContainer *container, const Location &fileName, const struct RARHeaderDataEx &info, SnapshotItem *parent) : ::VFS::SnapshotItem(container, unpackedSize(info), parent) { m_data.path = QString::fromWCharArray(info.FileNameW); m_data.fileName = fileName; m_data.fileSize = totalSize(); m_data.lastModified = fromDosTime(info.FileTime); }
void PtexReader::readFace(int levelid, Level* level, int faceid) { // temporarily release cache lock so other threads can proceed _cache->cachelock.unlock(); // get read lock and make sure we still need to read FaceData*& face = level->faces[faceid]; AutoMutex locker(readlock); if (face) { // another thread must have read it while we were waiting _cache->cachelock.lock(); // make sure it's still there now that we have the lock if (face) { face->ref(); return; } _cache->cachelock.unlock(); } // Go ahead and read the face, and read nearby faces if // possible. The goal is to coalesce small faces into single // runs of consecutive reads to minimize seeking and take // advantage of read-ahead buffering. // Try to read as many faces as will fit in BlockSize. Use the // in-memory size rather than the on-disk size to prevent flooding // the memory cache. And don't coalesce w/ tiled faces as these // are meant to be read individually. // scan both backwards and forwards looking for unread faces int first = faceid, last = faceid; int totalsize = 0; FaceDataHeader fdh = level->fdh[faceid]; if (fdh.encoding() != enc_tiled) { totalsize += unpackedSize(fdh, levelid, faceid); int nfaces = int(level->fdh.size()); while (1) { int f = first-1; if (f < 0 || level->faces[f]) break; fdh = level->fdh[f]; if (fdh.encoding() == enc_tiled) break; int size = totalsize + unpackedSize(fdh, levelid, f); if (size > BlockSize) break; first = f; totalsize = size; } while (1) { int f = last+1; if (f >= nfaces || level->faces[f]) break; fdh = level->fdh[f]; if (fdh.encoding() == enc_tiled) break; int size = totalsize + unpackedSize(fdh, levelid, f); if (size > BlockSize) break; last = f; totalsize = size; } } // read all faces in range // keep track of extra faces we read so we can add them to the cache later std::vector<FaceData*> extraFaces; extraFaces.reserve(last-first); for (int i = first; i <= last; i++) { fdh = level->fdh[i]; // skip faces with zero size (which is true for level-0 constant faces) if (fdh.blocksize()) { FaceData*& face = level->faces[i]; readFaceData(level->offsets[i], fdh, getRes(levelid, i), levelid, face); if (i != faceid) extraFaces.push_back(face); } } // reacquire cache lock, then unref extra faces to add them to the cache _cache->cachelock.lock(); for (size_t i = 0, size = extraFaces.size(); i < size; i++) extraFaces[i]->unref(); }