const bool FChunkWriter::FQueuedChunkWriter::WriteChunkData(const FString& ChunkFilename, FChunkFile* ChunkFile, const FGuid& ChunkGuid) { // Chunks are saved with GUID, so if a file already exists it will never be different. // Skip with return true if already exists if( FPaths::FileExists( ChunkFilename ) ) { const int64 ChunkFilesSize = IFileManager::Get().FileSize(*ChunkFilename); ChunkFileSizesCS.Lock(); ChunkFileSizes.Add(ChunkGuid, ChunkFilesSize); ChunkFileSizesCS.Unlock(); return true; } FArchive* FileOut = IFileManager::Get().CreateFileWriter( *ChunkFilename ); bool bSuccess = FileOut != NULL; if( bSuccess ) { // Setup to handle compression bool bDataIsCompressed = true; uint8* ChunkDataSource = ChunkFile->ChunkData; int32 ChunkDataSourceSize = FBuildPatchData::ChunkDataSize; TArray< uint8 > TempCompressedData; TempCompressedData.Empty( ChunkDataSourceSize ); TempCompressedData.AddUninitialized( ChunkDataSourceSize ); int32 CompressedSize = ChunkDataSourceSize; // Compressed can increase in size, but the function will return as failure in that case // we can allow that to happen since we would not keep larger compressed data anyway. bDataIsCompressed = FCompression::CompressMemory( static_cast< ECompressionFlags >( COMPRESS_ZLIB | COMPRESS_BiasMemory ), TempCompressedData.GetData(), CompressedSize, ChunkFile->ChunkData, FBuildPatchData::ChunkDataSize ); // If compression succeeded, set data vars if( bDataIsCompressed ) { ChunkDataSource = TempCompressedData.GetData(); ChunkDataSourceSize = CompressedSize; } // Setup Header FChunkHeader& Header = ChunkFile->ChunkHeader; *FileOut << Header; Header.HeaderSize = FileOut->Tell(); Header.StoredAs = bDataIsCompressed ? FChunkHeader::STORED_COMPRESSED : FChunkHeader::STORED_RAW; Header.DataSize = ChunkDataSourceSize; Header.HashType = FChunkHeader::HASH_ROLLING; // Write out files FileOut->Seek( 0 ); *FileOut << Header; FileOut->Serialize( ChunkDataSource, ChunkDataSourceSize ); const int64 ChunkFilesSize = FileOut->TotalSize(); FileOut->Close(); ChunkFileSizesCS.Lock(); ChunkFileSizes.Add(ChunkGuid, ChunkFilesSize); ChunkFileSizesCS.Unlock(); bSuccess = !FileOut->GetError(); delete FileOut; } // Log errors if( !bSuccess ) { GLog->Logf( TEXT( "BuildPatchServices: Error: Could not save out generated chunk file %s" ), *ChunkFilename ); } return bSuccess; }