LCOV - code coverage report
Current view: top level - port - cpl_vsil_uploadonclose.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 41 54 75.9 %
Date: 2024-11-21 22:18:42 Functions: 10 15 66.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  CPL - Common Portability Library
       4             :  * Purpose:  File handler that uses a temporary file, and upload file on close
       5             :  * Author:   Even Rouault, even.rouault at spatialys.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2020, Even Rouault <even.rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_vsi_virtual.h"
      14             : 
      15             : #include <algorithm>
      16             : #include <vector>
      17             : 
      18             : /************************************************************************/
      19             : /*                        VSIUploadOnCloseHandle                        */
      20             : /************************************************************************/
      21             : 
      22             : class VSIUploadOnCloseHandle final : public VSIVirtualHandle
      23             : {
      24             :     VSIVirtualHandleUniquePtr m_poWritableHandle;
      25             :     std::string m_osTmpFilename;
      26             :     VSIVirtualHandleUniquePtr m_fpTemp;
      27             : 
      28             :     VSIUploadOnCloseHandle(const VSIUploadOnCloseHandle &) = delete;
      29             :     VSIUploadOnCloseHandle &operator=(const VSIUploadOnCloseHandle &) = delete;
      30             : 
      31             :   public:
      32           5 :     VSIUploadOnCloseHandle(VSIVirtualHandleUniquePtr &&poWritableHandle,
      33             :                            const std::string &osTmpFilename,
      34             :                            VSIVirtualHandleUniquePtr &&fpTemp)
      35          10 :         : m_poWritableHandle(std::move(poWritableHandle)),
      36           5 :           m_osTmpFilename(osTmpFilename), m_fpTemp(std::move(fpTemp))
      37             :     {
      38           5 :     }
      39             : 
      40             :     ~VSIUploadOnCloseHandle() override;
      41             : 
      42          31 :     int Seek(vsi_l_offset nOffset, int nWhence) override
      43             :     {
      44          31 :         return m_fpTemp->Seek(nOffset, nWhence);
      45             :     }
      46             : 
      47          27 :     vsi_l_offset Tell() override
      48             :     {
      49          27 :         return m_fpTemp->Tell();
      50             :     }
      51             : 
      52          35 :     size_t Read(void *pBuffer, size_t nSize, size_t nCount) override
      53             :     {
      54          35 :         return m_fpTemp->Read(pBuffer, nSize, nCount);
      55             :     }
      56             : 
      57          13 :     size_t Write(const void *pBuffer, size_t nSize, size_t nCount) override
      58             :     {
      59          13 :         return m_fpTemp->Write(pBuffer, nSize, nCount);
      60             :     }
      61             : 
      62           0 :     void ClearErr() override
      63             :     {
      64           0 :     }
      65             : 
      66           0 :     int Error() override
      67             :     {
      68           0 :         return 0;
      69             :     }
      70             : 
      71           1 :     int Eof() override
      72             :     {
      73           1 :         return m_fpTemp->Eof();
      74             :     }
      75             : 
      76           0 :     int Flush() override
      77             :     {
      78           0 :         return m_fpTemp->Flush();
      79             :     }
      80             : 
      81             :     int Close() override;
      82             : 
      83           0 :     int Truncate(vsi_l_offset nNewSize) override
      84             :     {
      85           0 :         return m_fpTemp->Truncate(nNewSize);
      86             :     }
      87             : 
      88           0 :     VSIRangeStatus GetRangeStatus(vsi_l_offset nOffset,
      89             :                                   vsi_l_offset nLength) override
      90             :     {
      91           0 :         return m_fpTemp->GetRangeStatus(nOffset, nLength);
      92             :     }
      93             : };
      94             : 
      95             : /************************************************************************/
      96             : /*                      ~VSIUploadOnCloseHandle()                       */
      97             : /************************************************************************/
      98             : 
      99          10 : VSIUploadOnCloseHandle::~VSIUploadOnCloseHandle()
     100             : {
     101           5 :     VSIUploadOnCloseHandle::Close();
     102           5 :     if (!m_osTmpFilename.empty())
     103           0 :         VSIUnlink(m_osTmpFilename.c_str());
     104          10 : }
     105             : 
     106             : /************************************************************************/
     107             : /*                              Close()                                 */
     108             : /************************************************************************/
     109             : 
     110          10 : int VSIUploadOnCloseHandle::Close()
     111             : {
     112          10 :     if (m_fpTemp == nullptr)
     113           5 :         return -1;
     114             : 
     115             :     // Copy temporary files to m_poWritableHandle
     116           5 :     if (m_fpTemp->Seek(0, SEEK_END) != 0)
     117             :     {
     118           0 :         m_fpTemp.reset();
     119           0 :         return -1;
     120             :     }
     121           5 :     const auto nSize = m_fpTemp->Tell();
     122           5 :     m_fpTemp->Seek(0, SEEK_SET);
     123           5 :     constexpr size_t CHUNK_SIZE = 1024 * 1024;
     124           5 :     vsi_l_offset nOffset = 0;
     125          15 :     std::vector<GByte> abyBuffer(CHUNK_SIZE);
     126           8 :     while (nOffset < nSize)
     127             :     {
     128             :         size_t nToRead = static_cast<size_t>(
     129           4 :             std::min(nSize - nOffset, static_cast<vsi_l_offset>(CHUNK_SIZE)));
     130           8 :         if (m_fpTemp->Read(&abyBuffer[0], nToRead, 1) != 1 ||
     131           4 :             m_poWritableHandle->Write(&abyBuffer[0], nToRead, 1) != 1)
     132             :         {
     133           1 :             m_fpTemp.reset();
     134           1 :             return -1;
     135             :         }
     136           3 :         nOffset += nToRead;
     137             :     }
     138           4 :     m_fpTemp.reset();
     139           4 :     return m_poWritableHandle->Close();
     140             : }
     141             : 
     142             : /************************************************************************/
     143             : /*                    VSICreateUploadOnCloseFile()                      */
     144             : /************************************************************************/
     145             : 
     146             : VSIVirtualHandle *
     147           5 : VSICreateUploadOnCloseFile(VSIVirtualHandleUniquePtr &&poWritableHandle,
     148             :                            VSIVirtualHandleUniquePtr &&poTmpFile,
     149             :                            const std::string &osTmpFilename)
     150             : {
     151           5 :     const bool deleted = VSIUnlink(osTmpFilename.c_str()) == 0;
     152           5 :     return new VSIUploadOnCloseHandle(std::move(poWritableHandle),
     153          10 :                                       deleted ? std::string() : osTmpFilename,
     154          10 :                                       std::move(poTmpFile));
     155             : }

Generated by: LCOV version 1.14