From a0d9e03d1747f3d4ac28fbecdc117d7107067868 Mon Sep 17 00:00:00 2001 From: codestation Date: Sun, 5 Jan 2014 00:41:22 -0430 Subject: [PATCH] Remove the mmap usage. Do not use memory buffer to hold the whole file. --- src/capability.cpp | 5 +++ src/capability.h | 2 +- src/cmaevent.cpp | 105 +++++++++++++++++++++++++++++---------------- src/cmaevent.h | 4 ++ 4 files changed, 79 insertions(+), 37 deletions(-) diff --git a/src/capability.cpp b/src/capability.cpp index de54333..673a3ed 100644 --- a/src/capability.cpp +++ b/src/capability.cpp @@ -22,6 +22,11 @@ #include #include +DeviceCapability::DeviceCapability() : + vita_info() +{ +} + bool DeviceCapability::exchangeInfo(vita_device_t *device) { if(VitaMTP_GetVitaInfo(device, &vita_info) != PTP_RC_OK) { diff --git a/src/capability.h b/src/capability.h index ff11816..2b15185 100644 --- a/src/capability.h +++ b/src/capability.h @@ -25,7 +25,7 @@ class DeviceCapability { public: - explicit DeviceCapability() {} + explicit DeviceCapability(); ~DeviceCapability(); bool exchangeInfo(vita_device_t *device); diff --git a/src/cmaevent.cpp b/src/cmaevent.cpp index 6d4dcbd..57dc629 100644 --- a/src/cmaevent.cpp +++ b/src/cmaevent.cpp @@ -29,6 +29,7 @@ #include Database *CmaEvent::db = NULL; +QFile *CmaEvent::m_file = NULL; metadata_t CmaEvent::g_thumbmeta = {0, 0, 0, NULL, NULL, 0, 0, 0, Thumbnail, {{17, 240, 136, 0, 1, 1.0f, 2}}, NULL}; @@ -149,20 +150,30 @@ void CmaEvent::processEvent() quint16 CmaEvent::processAllObjects(CMAObject *parent, quint32 handle) { - union { - unsigned char *fileData; - uint32_t *handles; - } data; + qDebug("Called %s, handle: %d, parent name: %s", Q_FUNC_INFO, handle, parent->metadata.name); - metadata_t remote_meta; - unsigned int length; + char *name; + uint64_t size; + int dataType; - if(VitaMTP_GetObject(device, handle, &remote_meta, (void **)&data, &length) != PTP_RC_OK) { + uint32_t *p_handles; + unsigned int p_len; + + if(VitaMTP_GetObject_Info(device, handle, &name, &dataType) != PTP_RC_OK) { qWarning("Cannot get object for handle %d", handle); return PTP_RC_VITA_Invalid_Data; } - CMAObject *object = db->pathToObject(remote_meta.name, parent->metadata.ohfi); + if(dataType & Folder) { + if(VitaMTP_GetObject_Folder(device, handle, &p_handles, &p_len) != PTP_RC_OK) { + qWarning("Cannot get folder handles for handle %d", handle); + return PTP_RC_VITA_Invalid_Data; + } + } else { + + } + + CMAObject *object = db->pathToObject(name, parent->metadata.ohfi); if(object) { qDebug("Deleting %s", object->path.toStdString().c_str()); @@ -172,49 +183,48 @@ quint16 CmaEvent::processAllObjects(CMAObject *parent, quint32 handle) QDir dir(parent->path); - if(remote_meta.dataType & Folder) { - if(!dir.mkpath(remote_meta.name)) { - qWarning("Cannot create directory: %s", remote_meta.name); - free(data.fileData); - free(remote_meta.name); + if(dataType & Folder) { + if(!dir.mkpath(name)) { + qWarning("Cannot create directory: %s", name); + free(name); return PTP_RC_VITA_Failed_Operate_Object; } } else { - QFile file(dir.absoluteFilePath(remote_meta.name)); + m_file = new QFile(dir.absoluteFilePath(name)); - if(!file.open(QIODevice::WriteOnly)) { - qWarning("Cannot write to %s", remote_meta.name); - free(data.fileData); - free(remote_meta.name); + if(!m_file->open(QIODevice::WriteOnly)) { + qWarning("Cannot write to %s", name); + free(name); + delete m_file; return PTP_RC_VITA_Invalid_Permission; } else { - file.write((const char *)data.fileData, remote_meta.size); + VitaMTP_GetObject_Callback(device, handle, &size, CmaEvent::writeCallback); + m_file->close(); + delete m_file; } } - QFileInfo info(dir, remote_meta.name); + QFileInfo info(dir, name); object = new CMAObject(parent); object->initObject(info); - object->metadata.handle = remote_meta.handle; + object->metadata.handle = handle; db->append(parent->metadata.ohfi, object); - free(remote_meta.name); + free(name); qDebug("Added object %s with OHFI %i to database", object->metadata.path, object->metadata.ohfi); - if(remote_meta.dataType & Folder) { - for(unsigned int i = 0; i < length; i++) { - quint16 ret = processAllObjects(object, data.handles[i]); + if(dataType & Folder) { + for(unsigned int i = 0; i < p_len; i++) { + quint16 ret = processAllObjects(object, p_handles[i]); if(ret != PTP_RC_OK) { qDebug("Deleteting object with OHFI %d", object->metadata.ohfi); db->remove(object); - free(data.fileData); return ret; } } } - free(data.fileData); return PTP_RC_OK; } @@ -405,15 +415,15 @@ void CmaEvent::vitaEventSendObject(vita_event_t *event, int eventId) uint handle; do { - uchar *data = NULL; len = object->metadata.size; - QFile file(object->path); + m_file = new QFile(object->path); // read the file to send if it's not a directory // if it is a directory, data and len are not used by VitaMTP if(object->metadata.dataType & File) { - if(!file.open(QIODevice::ReadOnly) || (data = file.map(0, file.size())) == NULL) { + if(!m_file->open(QIODevice::ReadOnly)) { qWarning("Failed to read %s", object->path.toStdString().c_str()); + delete m_file; VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Not_Exist_Object); return; } @@ -432,17 +442,19 @@ void CmaEvent::vitaEventSendObject(vita_event_t *event, int eventId) qDebug("OHFI %d with handle 0x%08X", ohfi, parentHandle); VitaMTP_RegisterCancelEventId(eventId); - quint16 ret = VitaMTP_SendObject(device, &parentHandle, &handle, &object->metadata, data); + quint16 ret = VitaMTP_SendObject_Callback(device, &parentHandle, &handle, &object->metadata, &CmaEvent::readCallback); if(ret != PTP_RC_OK) { qWarning("Sending of %s failed. Code: %04X", object->metadata.name, ret); - file.unmap(data); + m_file->close(); + delete m_file; return; } object->metadata.handle = handle; if(object->metadata.dataType & File) { - file.unmap(data); + m_file->close(); + delete m_file; } // break early if only a file needs to be sent @@ -686,7 +698,7 @@ void CmaEvent::vitaEventSendPartOfObject(vita_event_t *event, int eventId) } else { file.seek(part_init.offset); QByteArray data = file.read(part_init.size); - qDebug("Sending %s at file offset %"PRIu64" for %"PRIu64" bytes", object->metadata.path, part_init.offset, part_init.size); + qDebug("Sending %s at file offset %" PRIu64" for %" PRIu64" bytes", object->metadata.path, part_init.offset, part_init.size); if(VitaMTP_SendPartOfObject(device, eventId, (unsigned char *)data.data(), data.size()) != PTP_RC_OK) { qWarning("Failed to send part of object OHFI %d", part_init.ohfi); @@ -813,7 +825,7 @@ void CmaEvent::vitaEventGetPartOfObject(vita_event_t *event, int eventId) return; } - qDebug("Receiving %s at offset %"PRIu64" for %"PRIu64" bytes", object->metadata.path, part_init.offset, part_init.size); + qDebug("Receiving %s at offset %" PRIu64" for %" PRIu64" bytes", object->metadata.path, part_init.offset, part_init.size); QFile file(object->path); if(!file.open(QIODevice::ReadWrite)) { @@ -823,7 +835,7 @@ void CmaEvent::vitaEventGetPartOfObject(vita_event_t *event, int eventId) file.seek(part_init.offset); file.write((const char *)data, part_init.size); object->updateObjectSize(part_init.size); - qDebug("Written %"PRIu64" bytes to %s at offset %"PRIu64, part_init.size, object->path.toStdString().c_str(), part_init.offset); + qDebug("Written %" PRIu64" bytes to %s at offset %" PRIu64, part_init.size, object->path.toStdString().c_str(), part_init.offset); VitaMTP_ReportResult(device, eventId, PTP_RC_OK); } @@ -900,3 +912,24 @@ void CmaEvent::vitaEventCheckExistance(vita_event_t *event, int eventId) VitaMTP_ReportResult(device, eventId, PTP_RC_OK); } + +int CmaEvent::readCallback(unsigned char *data, unsigned long wantlen, unsigned long *gotlen) +{ + QByteArray qdata = m_file->read(wantlen); + *gotlen = qdata.size(); + if(*gotlen) { + memcpy(data, qdata.constData(), qdata.size()); + } + + return PTP_RC_OK; +} + +int CmaEvent::writeCallback(const unsigned char *data, unsigned long size, unsigned long *written) +{ + int ret = m_file->write((const char *)data, size); + if(ret != -1) { + *written = ret; + ret = PTP_RC_OK; + } + return ret; +} diff --git a/src/cmaevent.h b/src/cmaevent.h index c0a93eb..a64d7b3 100644 --- a/src/cmaevent.h +++ b/src/cmaevent.h @@ -61,6 +61,9 @@ private: void vitaEventSendObjectMetadataItems(vita_event_t *event, int eventId); void vitaEventSendNPAccountInfo(vita_event_t *event, int eventId); + static int readCallback(unsigned char *data, unsigned long wantlen, unsigned long *gotlen); + static int writeCallback(const unsigned char *data, unsigned long size, unsigned long *written); + void processEvent(); bool isActive(); void setDevice(vita_device_t *device); @@ -75,6 +78,7 @@ private: QSemaphore sema; static metadata_t g_thumbmeta; + static QFile *m_file; signals: void finishedEventLoop();