comphelper/source/misc/storagehelper.cxx | 46 ++++++++---- include/comphelper/storagehelper.hxx | 6 + oox/source/helper/zipstorage.cxx | 4 - package/inc/ZipFile.hxx | 6 + package/source/xstor/xfactory.cxx | 4 - package/source/xstor/xstorage.cxx | 3 package/source/zipapi/ZipFile.cxx | 118 +++++++++++++++++++++++++++++-- package/source/zippackage/ZipPackage.cxx | 6 + 8 files changed, 167 insertions(+), 26 deletions(-)
New commits: commit a104cbe76eefca3cf23973da68893d2225fd718b Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Fri Jan 13 20:47:46 2017 -0500 tdf#97597: Ensure that each parsing thread has its own buffer. (cherry picked from commit 4ae705d02df0ddf75b97d0e94add6994626f487e) Change-Id: I93077f954a49b3922930e4fc86c80228be0f4dd2 Reviewed-on: https://gerrit.libreoffice.org/33069 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Kohei Yoshida <libreoff...@kohei.us> diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx index bc83276..42aaade 100644 --- a/comphelper/source/misc/storagehelper.cxx +++ b/comphelper/source/misc/storagehelper.cxx @@ -326,17 +326,28 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStr const OUString& aFormat, const uno::Reference < io::XInputStream >& xStream, const uno::Reference< uno::XComponentContext >& rxContext, - bool bRepairStorage ) + bool bRepairStorage, bool bUseBufferedStream ) throw ( uno::Exception ) { uno::Sequence< beans::PropertyValue > aProps( 1 ); - aProps[0].Name = "StorageFormat"; - aProps[0].Value <<= aFormat; + sal_Int32 nPos = 0; + aProps[nPos].Name = "StorageFormat"; + aProps[nPos].Value <<= aFormat; + ++nPos; if ( bRepairStorage ) { - aProps.realloc( 2 ); - aProps[1].Name = "RepairPackage"; - aProps[1].Value <<= bRepairStorage; + aProps.realloc(nPos+1); + aProps[nPos].Name = "RepairPackage"; + aProps[nPos].Value <<= bRepairStorage; + ++nPos; + } + + if (bUseBufferedStream) + { + aProps.realloc(nPos+1); + aProps[nPos].Name = "UseBufferedStream"; + aProps[nPos].Value <<= bUseBufferedStream; + ++nPos; } uno::Sequence< uno::Any > aArgs( 3 ); @@ -358,17 +369,28 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream( const uno::Reference < io::XStream >& xStream, sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext, - bool bRepairStorage ) + bool bRepairStorage, bool bUseBufferedStream ) throw ( uno::Exception ) { uno::Sequence< beans::PropertyValue > aProps( 1 ); - aProps[0].Name = "StorageFormat"; - aProps[0].Value <<= aFormat; + sal_Int32 nPos = 0; + aProps[nPos].Name = "StorageFormat"; + aProps[nPos].Value <<= aFormat; + ++nPos; if ( bRepairStorage ) { - aProps.realloc( 2 ); - aProps[1].Name = "RepairPackage"; - aProps[1].Value <<= bRepairStorage; + aProps.realloc(nPos+1); + aProps[nPos].Name = "RepairPackage"; + aProps[nPos].Value <<= bRepairStorage; + ++nPos; + } + + if (bUseBufferedStream) + { + aProps.realloc(nPos+1); + aProps[nPos].Name = "UseBufferedStream"; + aProps[nPos].Value <<= bUseBufferedStream; + ++nPos; } uno::Sequence< uno::Any > aArgs( 3 ); diff --git a/include/comphelper/storagehelper.hxx b/include/comphelper/storagehelper.hxx index 9472ce6..f257d3c 100644 --- a/include/comphelper/storagehelper.hxx +++ b/include/comphelper/storagehelper.hxx @@ -155,7 +155,8 @@ public: const css::uno::Reference < css::io::XInputStream >& xStream, const css::uno::Reference< css::uno::XComponentContext >& rxContext = css::uno::Reference< css::uno::XComponentContext >(), - bool bRepairStorage = false ) + bool bRepairStorage = false, + bool bUseBufferedStream = false ) throw ( css::uno::Exception ); static css::uno::Reference< css::embed::XStorage > @@ -165,7 +166,8 @@ public: sal_Int32 nStorageMode = css::embed::ElementModes::READWRITE, const css::uno::Reference< css::uno::XComponentContext >& rxContext = css::uno::Reference< css::uno::XComponentContext >(), - bool bRepairStorage = false ) + bool bRepairStorage = false, + bool bUseBufferedStream = false ) throw ( css::uno::Exception ); static css::uno::Sequence< css::beans::NamedValue > diff --git a/oox/source/helper/zipstorage.cxx b/oox/source/helper/zipstorage.cxx index 0673651..c0d454d 100644 --- a/oox/source/helper/zipstorage.cxx +++ b/oox/source/helper/zipstorage.cxx @@ -58,7 +58,7 @@ ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const R implementation of relations handling. */ mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( - ZIP_STORAGE_FORMAT_STRING, rxInStream, rxContext ); + ZIP_STORAGE_FORMAT_STRING, rxInStream, rxContext, false, true); } catch (Exception const& e) { @@ -76,7 +76,7 @@ ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const R { const sal_Int32 nOpenMode = ElementModes::READWRITE | ElementModes::TRUNCATE; mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( - OFOPXML_STORAGE_FORMAT_STRING, rxStream, nOpenMode, rxContext, true ); + OFOPXML_STORAGE_FORMAT_STRING, rxStream, nOpenMode, rxContext, true, true); } catch (Exception const& e) { diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx index f0ec8db..8de6690 100644 --- a/package/inc/ZipFile.hxx +++ b/package/inc/ZipFile.hxx @@ -65,9 +65,10 @@ protected: css::uno::Reference < css::ucb::XProgressHandler > xProgressHandler; bool bRecoveryMode; + bool mbUseBufferedStream; // aMediaType parameter is used only for raw stream header creation - css::uno::Reference < css::io::XInputStream > createUnbufferedStream( + css::uno::Reference < css::io::XInputStream > createStreamForZipEntry( const rtl::Reference<SotMutexHolder>& aMutexHolder, ZipEntry & rEntry, const ::rtl::Reference < EncryptionData > &rData, @@ -104,6 +105,9 @@ public: EntryHash& GetEntryHash() { return aEntries; } void setInputStream ( css::uno::Reference < css::io::XInputStream > xNewStream ); + + void setUseBufferedStream( bool b ); + css::uno::Reference< css::io::XInputStream > SAL_CALL getRawData( ZipEntry& rEntry, const ::rtl::Reference < EncryptionData > &rData, diff --git a/package/source/xstor/xfactory.cxx b/package/source/xstor/xfactory.cxx index 95bb21a..d5031b4 100644 --- a/package/source/xstor/xfactory.cxx +++ b/package/source/xstor/xfactory.cxx @@ -193,8 +193,8 @@ uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstanceWithAr if ( aDescr[nInd].Name == "InteractionHandler" || aDescr[nInd].Name == "Password" || aDescr[nInd].Name == "RepairPackage" - || aDescr[nInd].Name == "StatusIndicator" ) - // || aDescr[nInd].Name == "Unpacked" ) // TODO: + || aDescr[nInd].Name == "StatusIndicator" + || aDescr[nInd].Name == "UseBufferedStream" ) { aPropsToSet.realloc( ++nNumArgs ); aPropsToSet[nNumArgs-1].Name = aDescr[nInd].Name; diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx index 0853d7f..bbd35f3 100644 --- a/package/source/xstor/xstorage.cxx +++ b/package/source/xstor/xstorage.cxx @@ -462,7 +462,8 @@ void OStorage_Impl::OpenOwnPackage() for ( sal_Int32 aInd = 0; aInd < m_xProperties.getLength(); aInd++ ) { if ( m_xProperties[aInd].Name == "RepairPackage" - || m_xProperties[aInd].Name == "ProgressHandler" ) + || m_xProperties[aInd].Name == "ProgressHandler" + || m_xProperties[aInd].Name == "UseBufferedStream" ) { beans::NamedValue aNamedValue( m_xProperties[aInd].Name, m_xProperties[aInd].Value ); diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index 41d77fb..d6579c4 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -75,6 +75,7 @@ ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference , xSeek(xInput, UNO_QUERY) , m_xContext ( rxContext ) , bRecoveryMode( false ) +, mbUseBufferedStream(false) { if (bInitialise) { @@ -95,6 +96,7 @@ ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference , m_xContext ( rxContext ) , xProgressHandler( xProgress ) , bRecoveryMode( bForceRecovery ) +, mbUseBufferedStream(false) { if (bInitialise) { @@ -115,6 +117,11 @@ ZipFile::~ZipFile() aEntries.clear(); } +void ZipFile::setUseBufferedStream( bool b ) +{ + mbUseBufferedStream = b; +} + void ZipFile::setInputStream ( uno::Reference < XInputStream > xNewStream ) { ::osl::MutexGuard aGuard( m_aMutex ); @@ -509,7 +516,99 @@ bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ::rtl::Reference< Encr return bRet; } -uno::Reference< XInputStream > ZipFile::createUnbufferedStream( +namespace { + +class XBufferedStream : public cppu::WeakImplHelper<css::io::XInputStream> +{ + std::vector<sal_Int8> maBytes; + size_t mnPos; + + size_t remainingSize() const + { + return maBytes.size() - mnPos; + } + + bool hasBytes() const + { + return mnPos < maBytes.size(); + } + +public: + XBufferedStream( const uno::Reference<XInputStream>& xSrcStream ) : mnPos(0) + { + const sal_Int32 nBufSize = 8192; + + sal_Int32 nRemaining = xSrcStream->available(); + maBytes.reserve(nRemaining); + uno::Sequence<sal_Int8> aBuf(nBufSize); + + auto readAndCopy = [&]( sal_Int32 nReadSize ) -> sal_Int32 + { + sal_Int32 nBytes = xSrcStream->readBytes(aBuf, nReadSize); + const sal_Int8* p = aBuf.getArray(); + const sal_Int8* pEnd = p + nBytes; + std::copy(p, pEnd, std::back_inserter(maBytes)); + return nBytes; + }; + + while (nRemaining > nBufSize) + nRemaining -= readAndCopy(nBufSize); + + if (nRemaining) + readAndCopy(nRemaining); + } + + virtual sal_Int32 SAL_CALL readBytes( uno::Sequence<sal_Int8>& rData, sal_Int32 nBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + if (!hasBytes()) + return 0; + + sal_Int32 nReadSize = std::min<sal_Int32>(nBytesToRead, remainingSize()); + rData.realloc(nReadSize); + std::vector<sal_Int8>::const_iterator it = maBytes.cbegin(); + std::advance(it, mnPos); + for (sal_Int32 i = 0; i < nReadSize; ++i, ++it) + rData[i] = *it; + + mnPos += nReadSize; + + return nReadSize; + } + + virtual sal_Int32 SAL_CALL readSomeBytes( ::css::uno::Sequence<sal_Int8>& rData, sal_Int32 nMaxBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + return readBytes(rData, nMaxBytesToRead); + } + + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + if (!hasBytes()) + return; + + mnPos += nBytesToSkip; + } + + virtual sal_Int32 SAL_CALL available() + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + if (!hasBytes()) + return 0; + + return remainingSize(); + } + + virtual void SAL_CALL closeInput() + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + } +}; + +} + +uno::Reference< XInputStream > ZipFile::createStreamForZipEntry( const rtl::Reference<SotMutexHolder>& aMutexHolder, ZipEntry & rEntry, const ::rtl::Reference< EncryptionData > &rData, @@ -519,7 +618,14 @@ uno::Reference< XInputStream > ZipFile::createUnbufferedStream( { ::osl::MutexGuard aGuard( m_aMutex ); - return new XUnbufferedStream ( m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode ); + uno::Reference<io::XInputStream> xSrcStream = new XUnbufferedStream( + m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode); + + if (!mbUseBufferedStream) + return xSrcStream; + + uno::Reference<io::XInputStream> xBufStream(new XBufferedStream(xSrcStream)); + return xBufStream; } ZipEnumeration * SAL_CALL ZipFile::entries( ) @@ -548,7 +654,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntr if ( bIsEncrypted && rData.is() && rData->m_aDigest.getLength() ) bNeedRawStream = !hasValidPassword ( rEntry, rData ); - return createUnbufferedStream ( aMutexHolder, + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA, @@ -588,7 +694,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry else bNeedRawStream = ( rEntry.nMethod == STORED ); - return createUnbufferedStream ( aMutexHolder, + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA, @@ -606,7 +712,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getRawData( ZipEntry& rEntry, if ( rEntry.nOffset <= 0 ) readLOC( rEntry ); - return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted ); + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted ); } uno::Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream( @@ -627,7 +733,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream( if ( rEntry.nOffset <= 0 ) readLOC( rEntry ); - return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, true, aMediaType ); + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, true, aMediaType ); } bool ZipFile::readLOC( ZipEntry &rEntry ) diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx index b87b7a4..fdfdb34 100644 --- a/package/source/zippackage/ZipPackage.cxx +++ b/package/source/zippackage/ZipPackage.cxx @@ -572,6 +572,7 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) if ( aArguments.getLength() ) { bool bHaveZipFile = true; + bool bUseBufferedStream = false; for( int ind = 0; ind < aArguments.getLength(); ind++ ) { @@ -699,6 +700,10 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) aNamedValue.Value >>= m_bAllowRemoveOnInsert; m_pRootFolder->setRemoveOnInsertMode_Impl( m_bAllowRemoveOnInsert ); } + else if (aNamedValue.Name == "UseBufferedStream") + { + aNamedValue.Value >>= bUseBufferedStream; + } // for now the progress handler is not used, probably it will never be // if ( aNamedValue.Name == "ProgressHandler" ) @@ -742,6 +747,7 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) try { m_pZipFile = new ZipFile ( m_xContentStream, m_xContext, true, m_bForceRecovery, xProgressHandler ); + m_pZipFile->setUseBufferedStream(bUseBufferedStream); getZipFileContents(); } catch ( IOException & e ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits