LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfsgwriterutil.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 136 170 80.0 %
Date: 2024-05-04 12:52:34 Functions: 72 153 47.1 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  netCDF read/write Driver
       4             :  * Purpose:  GDAL bindings over netCDF library.
       5             :  * Author:   Winor Chen <wchen329 at wisc.edu>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2019, Winor Chen <wchen329 at wisc.edu>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : #ifndef __NETCDFSGWRITERUTIL_H__
      29             : #define __NETCDFSGWRITERUTIL_H__
      30             : #include <cstdio>
      31             : #include <queue>
      32             : #include <typeinfo>
      33             : #include <vector>
      34             : #include "cpl_vsi.h"
      35             : #include "ogr_core.h"
      36             : #include "ogrsf_frmts.h"
      37             : #include "netcdflayersg.h"
      38             : #include "netcdfsg.h"
      39             : #include "netcdfvirtual.h"
      40             : 
      41             : namespace nccfdriver
      42             : {
      43             : 
      44             : /* OGR_SGeometry_Feature
      45             :  * Constructs over a OGRFeature
      46             :  * gives some basic information about that SGeometry Feature such as
      47             :  * Hold references... limited to scope of its references
      48             :  * - what's its geometry type
      49             :  * - how much total points it has
      50             :  * - how many parts it has
      51             :  * - a vector of counts of points for each part
      52             :  */
      53             : class SGeometry_Feature
      54             : {
      55             :     bool hasInteriorRing;
      56             :     const OGRGeometry *geometry_ref;
      57             :     geom_t type;
      58             :     size_t total_point_count;
      59             :     size_t total_part_count;
      60             :     std::vector<size_t> ppart_node_count;
      61             :     std::vector<bool> part_at_ind_interior;  // for use with Multipolygons ONLY
      62             :     mutable OGRPoint pt_buffer;
      63             : 
      64             :   public:
      65         446 :     geom_t getType()
      66             :     {
      67         446 :         return this->type;
      68             :     }
      69             : 
      70         409 :     size_t getTotalNodeCount()
      71             :     {
      72         409 :         return this->total_point_count;
      73             :     }
      74             : 
      75        1558 :     size_t getTotalPartCount()
      76             :     {
      77        1558 :         return this->total_part_count;
      78             :     }
      79             : 
      80       68422 :     std::vector<size_t> &getPerPartNodeCount()
      81             :     {
      82       68422 :         return this->ppart_node_count;
      83             :     }
      84             : 
      85             :     const OGRPoint &getPoint(size_t part_no, int point_index) const;
      86             :     explicit SGeometry_Feature(OGRFeature &);
      87             : 
      88             :     bool getHasInteriorRing()
      89             :     {
      90             :         return this->hasInteriorRing;
      91             :     }
      92             : 
      93         591 :     bool IsPartAtIndInteriorRing(size_t ind)
      94             :     {
      95         591 :         return this->part_at_ind_interior[ind];
      96             :     }  // ONLY used for Multipolygon
      97             : };
      98             : 
      99             : /* A memory buffer with a soft limit
     100             :  * Has basic capability of over quota checking, and memory counting
     101             :  */
     102             : class WBuffer
     103             : {
     104             :     unsigned long long used_mem = 0;
     105             : 
     106             :   public:
     107             :     /* addCount(...)
     108             :      * Takes in a size, and directly adds that size to memory count
     109             :      */
     110             :     void addCount(unsigned long long memuse);
     111             : 
     112             :     /* subCount(...)
     113             :      * Directly subtracts the specified size from used_mem
     114             :      */
     115             :     void subCount(unsigned long long memfree);
     116             : 
     117         892 :     unsigned long long &getUsage()
     118             :     {
     119         892 :         return used_mem;
     120             :     }
     121             : 
     122         360 :     void reset()
     123             :     {
     124         360 :         this->used_mem = 0;
     125         360 :     }
     126             : 
     127        1922 :     WBuffer()
     128        1922 :     {
     129        1922 :     }
     130             : };
     131             : 
     132             : /* OGR_SGFS_Transaction
     133             :  * Abstract class for a committable transaction
     134             :  *
     135             :  */
     136             : class OGR_SGFS_Transaction
     137             : {
     138             :     int varId = INVALID_VAR_ID;
     139             : 
     140             :   public:
     141             :     /* int commit(...);
     142             :      * Arguments: int ncid, the dataset to write to
     143             :      *            int write_loc, the index in which to write to
     144             :      * Implementation: should write the transaction to netCDF file
     145             :      *
     146             :      */
     147             :     virtual void commit(netCDFVID &n, size_t write_loc) = 0;
     148             : 
     149             :     /* unsigned long long count(...)
     150             :      * Implementation: supposed to return an approximate count of memory usage
     151             :      * Most classes will implement with sizeof(*this), except if otherwise
     152             :      * uncounted for dynamic allocation is involved.
     153             :      */
     154             :     virtual unsigned long long count() = 0;
     155             : 
     156             :     /* appendToLog
     157             :      * Implementation - given a file pointer, a transaction will be written to
     158             :      * that log file in the format:
     159             :      * -
     160             :      * transactionVarId - sizeof(int) bytes
     161             :      * NC_TYPE - sizeof(int) bytes
     162             :      * (nc_char only) OP - 1 byte (0 if does not require COUNT or non-zero i.e.
     163             :      * 1 if does) (nc_char only): SIZE of data - sizeof(size_t) bytes DATA -
     164             :      * size depends on NC_TYPE
     165             :      */
     166             :     virtual void appendToLog(VSILFILE *) = 0;
     167             : 
     168             :     /* ~OGR_SGFS_Transaction()
     169             :      * Empty. Simply here to stop the compiler from complaining...
     170             :      */
     171      224718 :     virtual ~OGR_SGFS_Transaction()
     172      224718 :     {
     173      224718 :     }
     174             : 
     175             :     /* OGR_SGFS_Transaction()
     176             :      * Empty. Simply here to stop one of the CI machines from complaining...
     177             :      */
     178      224718 :     OGR_SGFS_Transaction()
     179      224718 :     {
     180      224718 :     }
     181             : 
     182             :     /* void getVarId(...);
     183             :      * Gets the var in which to commit the transaction to.
     184             :      */
     185      769574 :     int getVarId()
     186             :     {
     187      769574 :         return this->varId;
     188             :     }
     189             : 
     190             :     /* nc_type getType
     191             :      * Returns the type of transaction being saved
     192             :      */
     193             :     virtual nc_type getType() = 0;
     194             : 
     195             :     /* void setVarId(...);
     196             :      * Sets the var in which to commit the transaction to.
     197             :      */
     198      224718 :     void setVarId(int vId)
     199             :     {
     200      224718 :         this->varId = vId;
     201      224718 :     }
     202             : };
     203             : 
     204             : typedef std::map<int, void *> NCWMap;
     205             : typedef std::pair<int, void *> NCWEntry;  // NC Writer Entry
     206             : typedef std::unique_ptr<OGR_SGFS_Transaction>
     207             :     MTPtr;  // a.k.a Managed Transaction Ptr
     208             : 
     209             : template <class T_c_type, nc_type T_nc_type>
     210       87851 : void genericLogAppend(T_c_type r, int vId, VSILFILE *f)
     211             : {
     212       87851 :     T_c_type rep = r;
     213       87851 :     int varId = vId;
     214       87851 :     int type = T_nc_type;
     215       87851 :     VSIFWriteL(&varId, sizeof(int), 1, f);     // write varID data
     216       87851 :     VSIFWriteL(&type, sizeof(int), 1, f);      // write NC type
     217       87851 :     VSIFWriteL(&rep, sizeof(T_c_type), 1, f);  // write data
     218       87851 : }
     219             : 
     220             : template <class T_c_type, class T_r_type>
     221       87851 : MTPtr genericLogDataRead(int varId, VSILFILE *f)
     222             : {
     223             :     T_r_type data;
     224       87851 :     if (!VSIFReadL(&data, sizeof(T_r_type), 1, f))
     225             :     {
     226           0 :         return MTPtr(nullptr);  // invalid read case
     227             :     }
     228       87851 :     return MTPtr(new T_c_type(varId, data));
     229             : }
     230             : 
     231             : /* OGR_SGFS_NC_Char_Transaction
     232             :  * Writes to an NC_CHAR variable
     233             :  */
     234             : class OGR_SGFS_NC_Char_Transaction : public OGR_SGFS_Transaction
     235             : {
     236             :     std::string char_rep;
     237             : 
     238             :   public:
     239           0 :     void commit(netCDFVID &n, size_t write_loc) override
     240             :     {
     241           0 :         n.nc_put_vvar1_text(OGR_SGFS_Transaction::getVarId(), &write_loc,
     242             :                             char_rep.c_str());
     243           0 :     }
     244             : 
     245           0 :     unsigned long long count() override
     246             :     {
     247           0 :         return char_rep.size() + sizeof(*this);
     248             :     }  // account for actual character representation, this class
     249             : 
     250             :     void appendToLog(VSILFILE *f) override;
     251             : 
     252           0 :     nc_type getType() override
     253             :     {
     254           0 :         return NC_CHAR;
     255             :     }
     256             : 
     257           0 :     OGR_SGFS_NC_Char_Transaction(int i_varId, const char *pszVal)
     258           0 :         : char_rep(pszVal)
     259             :     {
     260           0 :         OGR_SGFS_Transaction::setVarId(i_varId);
     261           0 :     }
     262             : };
     263             : 
     264             : /* OGR_SGFS_NC_CharA_Transaction
     265             :  * Writes to an NC_CHAR variable, using vara instead of var1
     266             :  * Used to store 2D character array values, specifically
     267             :  */
     268             : class OGR_SGFS_NC_CharA_Transaction : public OGR_SGFS_Transaction
     269             : {
     270             :     std::string char_rep;
     271             :     size_t counts[2];
     272             : 
     273             :   public:
     274         884 :     void commit(netCDFVID &n, size_t write_loc) override
     275             :     {
     276         884 :         size_t ind[2] = {write_loc, 0};
     277         884 :         n.nc_put_vvara_text(OGR_SGFS_Transaction::getVarId(), ind, counts,
     278             :                             char_rep.c_str());
     279         884 :     }
     280             : 
     281        2356 :     unsigned long long count() override
     282             :     {
     283        2356 :         return char_rep.size() + sizeof(*this);
     284             :     }  // account for actual character representation, this class
     285             : 
     286             :     void appendToLog(VSILFILE *f) override;
     287             : 
     288         884 :     nc_type getType() override
     289             :     {
     290         884 :         return NC_CHAR;
     291             :     }
     292             : 
     293        1472 :     OGR_SGFS_NC_CharA_Transaction(int i_varId, const char *pszVal)
     294        1472 :         : char_rep(pszVal), counts{1, char_rep.length()}
     295             :     {
     296        1472 :         OGR_SGFS_Transaction::setVarId(i_varId);
     297        1472 :     }
     298             : };
     299             : 
     300             : template <class VClass, nc_type ntype>
     301             : class OGR_SGFS_NC_Transaction_Generic : public OGR_SGFS_Transaction
     302             : {
     303             :     VClass rep;
     304             : 
     305             :   public:
     306       23250 :     void commit(netCDFVID &n, size_t write_loc) override
     307             :     {
     308       23250 :         n.nc_put_vvar_generic<VClass>(OGR_SGFS_Transaction::getVarId(),
     309       23250 :                                       &write_loc, &rep);
     310       23250 :     }
     311             : 
     312      358613 :     unsigned long long count() override
     313             :     {
     314      358613 :         return sizeof(*this);
     315             :     }
     316             : 
     317       87851 :     void appendToLog(VSILFILE *f) override
     318             :     {
     319       87851 :         genericLogAppend<VClass, ntype>(rep, OGR_SGFS_Transaction::getVarId(),
     320             :                                         f);
     321       87851 :     }
     322             : 
     323      223232 :     OGR_SGFS_NC_Transaction_Generic(int i_varId, VClass in) : rep(in)
     324             :     {
     325      223232 :         OGR_SGFS_Transaction::setVarId(i_varId);
     326      223232 :     }
     327             : 
     328      112131 :     VClass getData()
     329             :     {
     330      112131 :         return rep;
     331             :     }
     332             : 
     333      382893 :     nc_type getType() override
     334             :     {
     335      382893 :         return ntype;
     336             :     }
     337             : };
     338             : 
     339             : typedef OGR_SGFS_NC_Transaction_Generic<signed char, NC_BYTE>
     340             :     OGR_SGFS_NC_Byte_Transaction;
     341             : typedef OGR_SGFS_NC_Transaction_Generic<short, NC_SHORT>
     342             :     OGR_SGFS_NC_Short_Transaction;
     343             : typedef OGR_SGFS_NC_Transaction_Generic<int, NC_INT>
     344             :     OGR_SGFS_NC_Int_Transaction;
     345             : typedef OGR_SGFS_NC_Transaction_Generic<float, NC_FLOAT>
     346             :     OGR_SGFS_NC_Float_Transaction;
     347             : typedef OGR_SGFS_NC_Transaction_Generic<double, NC_DOUBLE>
     348             :     OGR_SGFS_NC_Double_Transaction;
     349             : typedef OGR_SGFS_NC_Transaction_Generic<unsigned, NC_UINT>
     350             :     OGR_SGFS_NC_UInt_Transaction;
     351             : typedef OGR_SGFS_NC_Transaction_Generic<unsigned long long, NC_UINT64>
     352             :     OGR_SGFS_NC_UInt64_Transaction;
     353             : typedef OGR_SGFS_NC_Transaction_Generic<long long, NC_INT64>
     354             :     OGR_SGFS_NC_Int64_Transaction;
     355             : typedef OGR_SGFS_NC_Transaction_Generic<unsigned char, NC_UBYTE>
     356             :     OGR_SGFS_NC_UByte_Transaction;
     357             : typedef OGR_SGFS_NC_Transaction_Generic<unsigned short, NC_USHORT>
     358             :     OGR_SGFS_NC_UShort_Transaction;
     359             : 
     360             : /* OGR_SGFS_NC_String_Transaction
     361             :  * Writes to an NC_STRING variable, in a similar manner as NC_Char
     362             :  */
     363             : class OGR_SGFS_NC_String_Transaction : public OGR_SGFS_Transaction
     364             : {
     365             :     std::string char_rep;
     366             : 
     367             :   public:
     368          14 :     void commit(netCDFVID &n, size_t write_loc) override
     369             :     {
     370          14 :         const char *writable = char_rep.c_str();
     371          14 :         n.nc_put_vvar1_string(OGR_SGFS_Transaction::getVarId(), &write_loc,
     372             :                               &(writable));
     373          14 :     }
     374             : 
     375          28 :     unsigned long long count() override
     376             :     {
     377          28 :         return char_rep.size() + sizeof(*this);
     378             :     }  // account for actual character representation, this class
     379             : 
     380          28 :     nc_type getType() override
     381             :     {
     382          28 :         return NC_STRING;
     383             :     }
     384             : 
     385             :     void appendToLog(VSILFILE *f) override;
     386             : 
     387          14 :     OGR_SGFS_NC_String_Transaction(int i_varId, const char *pszVal)
     388          14 :         : char_rep(pszVal)
     389             :     {
     390          14 :         OGR_SGFS_Transaction::setVarId(i_varId);
     391          14 :     }
     392             : };
     393             : 
     394             : /* WTransactionLog
     395             :  * -
     396             :  * A temporary file which contains transactions to be written to a netCDF file.
     397             :  * Once the transaction log is created it is set on write mode, it can only be
     398             :  * read to after startRead() is called
     399             :  */
     400             : class WTransactionLog
     401             : {
     402             :     bool readMode = false;
     403             :     std::string wlogName;  // name of the temporary file, should be unique
     404             :     VSILFILE *log = nullptr;
     405             : 
     406             :     WTransactionLog(WTransactionLog &);  // avoid possible undefined behavior
     407             :     WTransactionLog operator=(const WTransactionLog &);
     408             : 
     409             :   public:
     410         360 :     bool logIsNull()
     411             :     {
     412         360 :         return log == nullptr;
     413             :     }
     414             : 
     415             :     void startLog();   // always call this first to open the file
     416             :     void startRead();  // then call this before reading it
     417             :     void push(MTPtr);
     418             : 
     419             :     // read mode
     420             :     MTPtr
     421             :     pop();  // to test for EOF, test to see if pointer returned is null ptr
     422             : 
     423             :     // construction, destruction
     424             :     explicit WTransactionLog(const std::string &logName);
     425             :     ~WTransactionLog();
     426             : };
     427             : 
     428             : /* OGR_NCScribe
     429             :  * Buffers several netCDF transactions in memory or in a log.
     430             :  * General scribe class
     431             :  */
     432             : class OGR_NCScribe
     433             : {
     434             :     netCDFVID &ncvd;
     435             :     WBuffer buf;
     436             :     WTransactionLog wl;
     437             :     bool singleDatumMode = false;
     438             : 
     439             :     std::queue<MTPtr> transactionQueue;
     440             :     std::map<int, size_t> varWriteInds;
     441             :     std::map<int, size_t> varMaxInds;
     442             : 
     443             :   public:
     444             :     /* size_t getWriteCount()
     445             :      * Return the total write count (happened + pending) of certain variable
     446             :      */
     447             :     size_t getWriteCount(int varId)
     448             :     {
     449             :         return this->varMaxInds.at(varId);
     450             :     }
     451             : 
     452             :     /* void commit_transaction()
     453             :      * Replays all transactions to disk (according to fs stipulations)
     454             :      */
     455             :     void commit_transaction();
     456             : 
     457             :     /* MTPtr pop()
     458             :      * Get the next transaction, if it exists.
     459             :      * If not, it will just return a shared_ptr with nullptr inside
     460             :      */
     461             :     MTPtr pop();
     462             : 
     463             :     /* void log_transacion()
     464             :      * Saves the current queued transactions to a log.
     465             :      */
     466             :     void log_transaction();
     467             : 
     468             :     /* void enqueue_transaction()
     469             :      * Add a transaction to perform
     470             :      * Once a transaction is enqueued, it will only be dequeued on commit
     471             :      */
     472             :     void enqueue_transaction(MTPtr transactionAdd);
     473             : 
     474        1922 :     WBuffer &getMemBuffer()
     475             :     {
     476        1922 :         return buf;
     477             :     }
     478             : 
     479             :     /* OGR_SGeometry_Field_Scribe()
     480             :      * Constructs a Field Scribe over a dataset
     481             :      */
     482        1922 :     OGR_NCScribe(netCDFVID &ncd, const std::string &name) : ncvd(ncd), wl(name)
     483             :     {
     484        1922 :     }
     485             : 
     486             :     /* setSingleDatumMode(...)
     487             :      * Enables or disables single datum mode
     488             :      * DO NOT use this when a commit is taking place, otherwise
     489             :      * corruption may occur...
     490             :      */
     491           2 :     void setSingleDatumMode(bool sdm)
     492             :     {
     493           2 :         this->singleDatumMode = sdm;
     494           2 :     }
     495             : };
     496             : 
     497             : class ncLayer_SG_Metadata
     498             : {
     499             :     int &ncID;  // ncid REF. which tracks ncID changes that may be made upstream
     500             : 
     501             :     netCDFVID &vDataset;
     502             :     OGR_NCScribe &ncb;
     503             :     geom_t writableType = NONE;
     504             :     std::string containerVarName;
     505             :     int containerVar_realID = INVALID_VAR_ID;
     506             :     bool interiorRingDetected =
     507             :         false;  // flips on when an interior ring polygon has been detected
     508             :     std::vector<int>
     509             :         node_coordinates_varIDs;  // ids in X, Y (and then possibly Z) order
     510             :     int node_coordinates_dimID = INVALID_DIM_ID;  // dim of all node_coordinates
     511             :     int node_count_dimID = INVALID_DIM_ID;        // node count dim
     512             :     int node_count_varID = INVALID_DIM_ID;
     513             :     int pnc_dimID =
     514             :         INVALID_DIM_ID;  // part node count dim AND interior ring dim
     515             :     int pnc_varID = INVALID_VAR_ID;
     516             :     int intring_varID = INVALID_VAR_ID;
     517             :     size_t next_write_pos_node_coord = 0;
     518             :     size_t next_write_pos_node_count = 0;
     519             :     size_t next_write_pos_pnc = 0;
     520             : 
     521             :   public:
     522         354 :     geom_t getWritableType()
     523             :     {
     524         354 :         return this->writableType;
     525             :     }
     526             : 
     527             :     void writeSGeometryFeature(SGeometry_Feature &ft);
     528             : 
     529         563 :     int get_containerRealID()
     530             :     {
     531         563 :         return this->containerVar_realID;
     532             :     }
     533             : 
     534          77 :     std::string get_containerName()
     535             :     {
     536          77 :         return this->containerVarName;
     537             :     }
     538             : 
     539         121 :     int get_node_count_dimID()
     540             :     {
     541         121 :         return this->node_count_dimID;
     542             :     }
     543             : 
     544         124 :     int get_node_coord_dimID()
     545             :     {
     546         124 :         return this->node_coordinates_dimID;
     547             :     }
     548             : 
     549          78 :     int get_pnc_dimID()
     550             :     {
     551          78 :         return this->pnc_dimID;
     552             :     }
     553             : 
     554           4 :     int get_pnc_varID()
     555             :     {
     556           4 :         return this->pnc_varID;
     557             :     }
     558             : 
     559          17 :     int get_intring_varID()
     560             :     {
     561          17 :         return this->intring_varID;
     562             :     }
     563             : 
     564          38 :     std::vector<int> &get_nodeCoordVarIDs()
     565             :     {
     566          38 :         return this->node_coordinates_varIDs;
     567             :     }
     568             : 
     569          42 :     size_t get_next_write_pos_node_coord()
     570             :     {
     571          42 :         return this->next_write_pos_node_coord;
     572             :     }
     573             : 
     574          32 :     size_t get_next_write_pos_node_count()
     575             :     {
     576          32 :         return this->next_write_pos_node_count;
     577             :     }
     578             : 
     579          27 :     size_t get_next_write_pos_pnc()
     580             :     {
     581          27 :         return this->next_write_pos_pnc;
     582             :     }
     583             : 
     584         114 :     bool getInteriorRingDetected()
     585             :     {
     586         114 :         return this->interiorRingDetected;
     587             :     }
     588             : 
     589             :     void initializeNewContainer(int containerVID);
     590             :     ncLayer_SG_Metadata(int &i_ncID, geom_t geo, netCDFVID &ncdf,
     591             :                         OGR_NCScribe &scribe);
     592             : };
     593             : 
     594             : /* WBufferManager
     595             :  * -
     596             :  * Simply takes a collection of buffers in and a quota limit and sums all the
     597             :  * usages up to establish if buffers are over the soft limit (collectively)
     598             :  *
     599             :  * The buffers added, however, are not memory managed by WBufferManager
     600             :  */
     601             : class WBufferManager
     602             : {
     603             :     unsigned long long buffer_soft_limit = 0;
     604             :     std::vector<WBuffer *> bufs;
     605             : 
     606             :   public:
     607             :     bool isOverQuota();
     608             : 
     609           4 :     void adjustLimit(unsigned long long lim)
     610             :     {
     611           4 :         this->buffer_soft_limit = lim;
     612           4 :     }
     613             : 
     614        1922 :     void addBuffer(WBuffer *b)
     615             :     {
     616        1922 :         this->bufs.push_back(b);
     617        1922 :     }
     618             : 
     619         961 :     explicit WBufferManager(unsigned long long lim) : buffer_soft_limit(lim)
     620             :     {
     621         961 :     }
     622             : };
     623             : 
     624             : // Exception Classes
     625             : class SGWriter_Exception : public SG_Exception
     626             : {
     627             :   public:
     628           0 :     const char *get_err_msg() override
     629             :     {
     630           0 :         return "A general error occurred when writing a netCDF dataset";
     631             :     }
     632             : };
     633             : 
     634             : class SGWriter_Exception_NCWriteFailure : public SGWriter_Exception
     635             : {
     636             :     std::string msg;
     637             : 
     638             :   public:
     639           0 :     const char *get_err_msg() override
     640             :     {
     641           0 :         return this->msg.c_str();
     642             :     }
     643             : 
     644             :     SGWriter_Exception_NCWriteFailure(const char *layer_name,
     645             :                                       const char *failure_name,
     646             :                                       const char *failure_type);
     647             : };
     648             : 
     649             : class SGWriter_Exception_NCInqFailure : public SGWriter_Exception
     650             : {
     651             :     std::string msg;
     652             : 
     653             :   public:
     654           0 :     const char *get_err_msg() override
     655             :     {
     656           0 :         return this->msg.c_str();
     657             :     }
     658             : 
     659             :     SGWriter_Exception_NCInqFailure(const char *layer_name,
     660             :                                     const char *failure_name,
     661             :                                     const char *failure_type);
     662             : };
     663             : 
     664             : class SGWriter_Exception_NCDefFailure : public SGWriter_Exception
     665             : {
     666             :     std::string msg;
     667             : 
     668             :   public:
     669           0 :     const char *get_err_msg() override
     670             :     {
     671           0 :         return this->msg.c_str();
     672             :     }
     673             : 
     674             :     SGWriter_Exception_NCDefFailure(const char *layer_name,
     675             :                                     const char *failure_name,
     676             :                                     const char *failure_type);
     677             : };
     678             : 
     679             : class SGWriter_Exception_NullGeometry : public SGWriter_Exception
     680             : {
     681             :     std::string msg;
     682             : 
     683             :   public:
     684           0 :     const char *get_err_msg() override
     685             :     {
     686           0 :         return this->msg.c_str();
     687             :     }
     688             : 
     689           0 :     SGWriter_Exception_NullGeometry()
     690           0 :         : msg("A null  geometry was detected when writing a netCDF file. "
     691           0 :               "Empty geometries are not allowed.")
     692             :     {
     693           0 :     }
     694             : };
     695             : 
     696             : class SGWriter_Exception_NCDelFailure : public SGWriter_Exception
     697             : {
     698             :     std::string msg;
     699             : 
     700             :   public:
     701           0 :     const char *get_err_msg() override
     702             :     {
     703           0 :         return this->msg.c_str();
     704             :     }
     705             : 
     706           0 :     SGWriter_Exception_NCDelFailure(const char *layer, const char *what)
     707           0 :         : msg("[" + std::string(layer) +
     708           0 :               "] Failed to delete: " + std::string(what))
     709             :     {
     710           0 :     }
     711             : };
     712             : 
     713             : // Helper Functions that for writing
     714             : 
     715             : /* std::vector<..> writeGeometryContainer(...)
     716             :  * Writes a geometry container of a given geometry type given the following
     717             :  * arguments: int ncID - ncid as used in netcdf.h, group or file id std::string
     718             :  * name - what to name this container geom_t geometry_type - the geometry type
     719             :  * of the container std::vector<..> node_coordinate_names - variable names
     720             :  * corresponding to each axis Only writes attributes that are for sure required.
     721             :  * i.e. does NOT required interior ring for anything or part node count for
     722             :  * Polygons
     723             :  *
     724             :  * Returns: geometry container variable ID
     725             :  */
     726             : int write_Geometry_Container(
     727             :     int ncID, const std::string &name, geom_t geometry_type,
     728             :     const std::vector<std::string> &node_coordinate_names);
     729             : 
     730             : template <class W_type>
     731      112131 : inline void NCWMapAllocIfNeeded(int varid, NCWMap &mapAdd, size_t numEntries,
     732             :                                 std::vector<int> &v)
     733             : {
     734      112131 :     if (mapAdd.count(varid) < 1)
     735             :     {
     736         201 :         mapAdd.insert(NCWEntry(varid, CPLMalloc(sizeof(W_type) * numEntries)));
     737         201 :         v.push_back(varid);
     738             :     }
     739      112131 : }
     740             : 
     741             : template <class W_type>
     742      112131 : inline void NCWMapWriteAndCommit(int varid, NCWMap &mapAdd, size_t currentEntry,
     743             :                                  size_t numEntries, W_type data,
     744             :                                  netCDFVID &vcdf)
     745             : {
     746      112131 :     W_type *ptr = static_cast<W_type *>(mapAdd.at(varid));
     747      112131 :     ptr[currentEntry] = data;
     748             :     static const size_t BEGIN = 0;
     749             : 
     750             :     // If all items are ready, write the array, and free it, delete the pointer
     751      112131 :     if (currentEntry == (numEntries - 1))
     752             :     {
     753             :         try
     754             :         {
     755             :             // Write the whole array at once
     756         201 :             vcdf.nc_put_vvara_generic<W_type>(varid, &BEGIN, &numEntries, ptr);
     757             :         }
     758           0 :         catch (SG_Exception_VWrite_Failure &e)
     759             :         {
     760           0 :             CPLError(CE_Warning, CPLE_FileIO, "%s", e.get_err_msg());
     761             :         }
     762             : 
     763         201 :         CPLFree(mapAdd.at(varid));
     764         201 :         mapAdd.erase(varid);
     765             :     }
     766      112131 : }
     767             : }  // namespace nccfdriver
     768             : 
     769             : #endif

Generated by: LCOV version 1.14