Added stream version into network cache file format
At the moment, there is no stream information in the cache file. This can lead to a problem when current stream version differs from version cache file written with. As an example, if file written with Qt 5.1.1, QTimeDate in the metadata stored as 13-bytes value, but Qt 5.2 and later can read additional 4 bytes which breaks following data, leading to network request just hangs forever. Adding stream version fixes this problem. As cache format changed, cache version bumped. Task-number: QTBUG-36219 Change-Id: I467d8c9fda82bcf9302192f51e7a00d2f6a9ff66 Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>bb10
parent
6186dd8571
commit
feb1afc782
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
#define CACHE_POSTFIX QLatin1String(".d")
|
||||
#define PREPARED_SLASH QLatin1String("prepared/")
|
||||
#define CACHE_VERSION 7
|
||||
#define CACHE_VERSION 8
|
||||
#define DATA_DIR QLatin1String("data")
|
||||
|
||||
#define MAX_COMPRESSION_SIZE (1024 * 1024 * 3)
|
||||
|
|
@ -686,6 +686,7 @@ void QCacheItem::writeHeader(QFile *device) const
|
|||
|
||||
out << qint32(CacheMagic);
|
||||
out << qint32(CurrentCacheVersion);
|
||||
out << static_cast<qint32>(out.version());
|
||||
out << metaData;
|
||||
bool compressed = canCompress();
|
||||
out << compressed;
|
||||
|
|
@ -719,6 +720,13 @@ bool QCacheItem::read(QFile *device, bool readData)
|
|||
if (v != CurrentCacheVersion)
|
||||
return false;
|
||||
|
||||
qint32 streamVersion;
|
||||
in >> streamVersion;
|
||||
// Default stream version is also the highest we can handle
|
||||
if (streamVersion > in.version())
|
||||
return false;
|
||||
in.setVersion(streamVersion);
|
||||
|
||||
bool compressed;
|
||||
QByteArray dataBA;
|
||||
in >> metaData;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ private slots:
|
|||
void oldCacheVersionFile_data();
|
||||
void oldCacheVersionFile();
|
||||
|
||||
void streamVersion_data();
|
||||
void streamVersion();
|
||||
|
||||
void sync();
|
||||
|
||||
void crashWhenParentingCache();
|
||||
|
|
@ -568,6 +571,74 @@ void tst_QNetworkDiskCache::oldCacheVersionFile()
|
|||
}
|
||||
}
|
||||
|
||||
void tst_QNetworkDiskCache::streamVersion_data()
|
||||
{
|
||||
QTest::addColumn<int>("version");
|
||||
QTest::newRow("Qt 5.1") << int(QDataStream::Qt_5_1);
|
||||
QDataStream ds;
|
||||
QTest::newRow("current") << ds.version();
|
||||
QTest::newRow("higher than current") << ds.version() + 1;
|
||||
}
|
||||
|
||||
void tst_QNetworkDiskCache::streamVersion()
|
||||
{
|
||||
SubQNetworkDiskCache cache;
|
||||
QUrl url(EXAMPLE_URL);
|
||||
cache.setupWithOne(tempDir.path(), url);
|
||||
|
||||
QString cacheFile;
|
||||
// find the file
|
||||
QStringList files = countFiles(cache.cacheDirectory());
|
||||
foreach (const QString &file, files) {
|
||||
QFileInfo info(file);
|
||||
if (info.isFile()) {
|
||||
cacheFile = file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QFile file(cacheFile);
|
||||
QVERIFY(file.open(QFile::ReadWrite|QIODevice::Truncate));
|
||||
QDataStream out(&file);
|
||||
QFETCH(int, version);
|
||||
if (version < out.version())
|
||||
out.setVersion(version);
|
||||
out << qint32(0xe8); // cache magic
|
||||
// Following code works only for cache file version 8 and should be updated on version change
|
||||
out << qint32(8);
|
||||
out << qint32(version);
|
||||
|
||||
QNetworkCacheMetaData md;
|
||||
md.setUrl(url);
|
||||
QNetworkCacheMetaData::RawHeader header("content-type", "text/html");
|
||||
QNetworkCacheMetaData::RawHeaderList list;
|
||||
list.append(header);
|
||||
md.setRawHeaders(list);
|
||||
md.setLastModified(QDateTime::currentDateTimeUtc().toOffsetFromUtc(3600));
|
||||
out << md;
|
||||
|
||||
bool compressed = true;
|
||||
out << compressed;
|
||||
|
||||
QByteArray data("Hello World!");
|
||||
out << qCompress(data);
|
||||
|
||||
file.close();
|
||||
|
||||
QNetworkCacheMetaData cachedMetaData = cache.call_fileMetaData(cacheFile);
|
||||
if (version > out.version()) {
|
||||
QVERIFY(!cachedMetaData.isValid());
|
||||
QVERIFY(!QFile::exists(cacheFile));
|
||||
} else {
|
||||
QVERIFY(cachedMetaData.isValid());
|
||||
QVERIFY(QFile::exists(cacheFile));
|
||||
QIODevice *dataDevice = cache.data(url);
|
||||
QVERIFY(dataDevice != 0);
|
||||
QByteArray cachedData = dataDevice->readAll();
|
||||
QCOMPARE(cachedData, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Runner : public QThread
|
||||
{
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue