LCOV - code coverage report
Current view: directory - gcore - gdalclientserver.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 2637 1773 67.2 %
Date: 2013-03-30 Functions: 153 128 83.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalclientserver.cpp 25684 2013-02-25 15:40:26Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  GDAL Client/server dataset mechanism.
       6                 :  * Author:   Even Rouault, <even dot rouault at mines-paris dot org>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2013, Even Rouault, <even dot rouault at mines-paris dot org>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "cpl_port.h"
      31                 : 
      32                 : #ifdef WIN32
      33                 :   #ifndef _WIN32_WINNT
      34                 :     #define _WIN32_WINNT 0x0501
      35                 :   #endif
      36                 :   #include <winsock2.h>
      37                 :   #include <ws2tcpip.h>
      38                 :   typedef SOCKET CPL_SOCKET;
      39                 :   #ifndef HAVE_GETADDRINFO
      40                 :     #define HAVE_GETADDRINFO 1
      41                 :   #endif
      42                 : #else
      43                 :   #include <sys/types.h>
      44                 :   #include <sys/socket.h>
      45                 :   #include <sys/un.h>
      46                 :   #include <netinet/in.h>
      47                 :   #include <arpa/inet.h>
      48                 :   #include <netdb.h>
      49                 :   typedef int CPL_SOCKET;
      50                 :   #define INVALID_SOCKET -1
      51                 :   #define SOCKET_ERROR -1
      52                 :   #define SOCKADDR struct sockaddr
      53                 :   #define WSAGetLastError() errno
      54                 :   #define WSACleanup()
      55                 :   #define closesocket(s) close(s)
      56                 : #endif
      57                 : 
      58                 : #include "gdal_pam.h"
      59                 : #include "gdal_rat.h"
      60                 : #include "cpl_spawn.h"
      61                 : #include "cpl_multiproc.h"
      62                 : 
      63                 : /*! 
      64                 : \page gdal_api_proxy GDAL API Proxy
      65                 : 
      66                 : \section gdal_api_proxy_intro Introduction
      67                 : 
      68                 : (GDAL >= 1.10.0)
      69                 : 
      70                 : When dealing with some file formats, particularly the drivers relying on third-party
      71                 : (potentially closed-source) libraries, it is difficult to ensure that those third-party
      72                 : libraries will be robust to hostile/corrupted datasource.
      73                 : 
      74                 : The implemented solution is to have a (private) API_PROXY driver that will expose a GDALClientDataset
      75                 : object, which will forward all the GDAL API calls to another process ("server"), where the real driver
      76                 : will be effectively run. This way, if the server aborts due to a fatal error, the calling process will
      77                 : be unaffected and will report a clean error instead of aborting itself.
      78                 : 
      79                 : \section gdal_api_proxy_enabling How to enable ?
      80                 : 
      81                 : The API_PROXY mechanism can be enabled by setting the GDAL_API_PROXY config option to YES.
      82                 : The option can also be set to a list of file extensions that must be the only ones to trigger
      83                 : this mechanism (e.g. GDAL_API_PROXY=ecw,sid).
      84                 : 
      85                 : When enabled, datasets can be handled with GDALOpen(), GDALCreate() or GDALCreateCopy() with
      86                 : their nominal filename (or connexion string).
      87                 : 
      88                 : Alternatively, the API_PROXY mechanism can be used selectively on a datasource by prefixing its
      89                 : name with API_PROXY:, for example GDALOpen("API_PROXY:foo.tif", GA_ReadOnly).
      90                 : 
      91                 : \section gdal_api_proxy_options Advanced options
      92                 : 
      93                 : For now, the server launched is the gdalserver executable on Windows. On Unix, the default behaviour is
      94                 : to just fork() the current process. It is also possible to launch the gdalserver executable
      95                 : by forcing GDAL_API_PROXY_SERVER=YES.
      96                 : The full filename of the gdalserver executable can also be specified in the GDAL_API_PROXY_SERVER.
      97                 : 
      98                 : It is also possible to connect to a gdalserver in TCP, possibly on a remote host. In that case,
      99                 : gdalserver must be launched on a host with "gdalserver -tcpserver the_tcp_port". And the client
     100                 : must set GDAL_API_PROXY_SERVER="hostname:the_tcp_port", where hostname is a string or a IP address.
     101                 : 
     102                 : In case of many dataset opening or creation, to avoid the cost of repeated process forking,
     103                 : a pool of unused connections is established. Each time a dataset is closed, the associated connection
     104                 : is pushed in the pool (if there's an empty bucket). When a following dataset is to be opened, one of those
     105                 : connections will be reused. This behaviour is controlled with the GDAL_API_PROXY_CONN_POOL config option
     106                 : that is set to YES by default, and will keep a maximum of 4 unused connections.
     107                 : GDAL_API_PROXY_CONN_POOL can be set to a integer value to specify the maximum number of unused connections.
     108                 : 
     109                 : \section gdal_api_proxy_limitations Limitations
     110                 : 
     111                 : Datasets stored in the memory virtual file system (/vsimem) or handled by the MEM driver are excluded from
     112                 : the API Proxy mechanism.
     113                 : 
     114                 : Additionnaly, for GDALCreate() or GDALCreateCopy(), the VRT driver is also excluded from that mechanism.
     115                 : 
     116                 : Currently, the client dataset returned is not protected by a mutex, so it is unsafe to use it concurrently
     117                 : from multiple threads. However, it is safe to use several client datasets from multiple threads.
     118                 : 
     119                 : */
     120                 : 
     121                 : /* REMINDER: upgrade this number when the on-wire protocol changes */
     122                 : /* Note: please at least keep the version exchange protocol unchanged ! */
     123                 : #define GDAL_CLIENT_SERVER_PROTOCOL_MAJOR 1
     124                 : #define GDAL_CLIENT_SERVER_PROTOCOL_MINOR 0
     125                 : 
     126                 : #include <map>
     127                 : #include <vector>
     128                 : 
     129                 : CPL_C_START
     130                 : int CPL_DLL GDALServerLoop(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout);
     131                 : const char* GDALClientDatasetGetFilename(const char* pszFilename);
     132                 : int CPL_DLL GDALServerLoopSocket(CPL_SOCKET nSocket);
     133                 : CPL_C_END
     134                 : 
     135                 : #define BUFFER_SIZE 1024
     136                 : typedef struct
     137                 : {
     138                 :     CPL_FILE_HANDLE fin;
     139                 :     CPL_FILE_HANDLE fout;
     140                 :     CPL_SOCKET      nSocket;
     141                 :     int             bOK;
     142                 :     GByte           abyBuffer[BUFFER_SIZE];
     143                 :     int             nBufferSize;
     144                 : } GDALPipe;
     145                 : 
     146                 : typedef struct
     147                 : {
     148                 :     CPLSpawnedProcess *sp;
     149                 :     GDALPipe          *p;
     150                 : } GDALServerSpawnedProcess;
     151                 : 
     152                 : typedef struct
     153                 : {
     154                 :     int    bUpdated;
     155                 :     double dfComplete;
     156                 :     char  *pszProgressMsg;
     157                 :     int    bRet;
     158                 :     void  *hMutex;
     159                 : } GDALServerAsyncProgress;
     160                 : 
     161                 : typedef enum
     162                 : {
     163                 :     INSTR_INVALID = 0,
     164                 :     INSTR_GetGDALVersion = 1, /* do not change this ! */
     165                 :     INSTR_EXIT,
     166                 :     INSTR_EXIT_FAIL,
     167                 :     INSTR_SetConfigOption,
     168                 :     INSTR_Progress,
     169                 :     INSTR_Reset,
     170                 :     INSTR_Open,
     171                 :     INSTR_Identify,
     172                 :     INSTR_Create,
     173                 :     INSTR_CreateCopy,
     174                 :     INSTR_QuietDelete,
     175                 :     INSTR_AddBand,
     176                 :     INSTR_GetGeoTransform,
     177                 :     INSTR_SetGeoTransform,
     178                 :     INSTR_GetProjectionRef,
     179                 :     INSTR_SetProjection,
     180                 :     INSTR_GetGCPCount,
     181                 :     INSTR_GetGCPProjection,
     182                 :     INSTR_GetGCPs,
     183                 :     INSTR_SetGCPs,
     184                 :     INSTR_GetFileList,
     185                 :     INSTR_FlushCache,
     186                 :     INSTR_SetDescription,
     187                 :     INSTR_GetMetadata,
     188                 :     INSTR_GetMetadataItem,
     189                 :     INSTR_SetMetadata,
     190                 :     INSTR_SetMetadataItem,
     191                 :     INSTR_IRasterIO_Read,
     192                 :     INSTR_IRasterIO_Write,
     193                 :     INSTR_IBuildOverviews,
     194                 :     INSTR_AdviseRead,
     195                 :     INSTR_CreateMaskBand,
     196                 :     INSTR_Band_First,
     197                 :     INSTR_Band_FlushCache,
     198                 :     INSTR_Band_GetCategoryNames,
     199                 :     INSTR_Band_SetCategoryNames,
     200                 :     INSTR_Band_SetDescription,
     201                 :     INSTR_Band_GetMetadata,
     202                 :     INSTR_Band_GetMetadataItem,
     203                 :     INSTR_Band_SetMetadata,
     204                 :     INSTR_Band_SetMetadataItem,
     205                 :     INSTR_Band_GetColorInterpretation,
     206                 :     INSTR_Band_SetColorInterpretation,
     207                 :     INSTR_Band_GetNoDataValue,
     208                 :     INSTR_Band_GetMinimum,
     209                 :     INSTR_Band_GetMaximum,
     210                 :     INSTR_Band_GetOffset,
     211                 :     INSTR_Band_GetScale,
     212                 :     INSTR_Band_SetNoDataValue,
     213                 :     INSTR_Band_SetOffset,
     214                 :     INSTR_Band_SetScale,
     215                 :     INSTR_Band_IReadBlock,
     216                 :     INSTR_Band_IWriteBlock,
     217                 :     INSTR_Band_IRasterIO_Read,
     218                 :     INSTR_Band_IRasterIO_Write,
     219                 :     INSTR_Band_GetStatistics,
     220                 :     INSTR_Band_ComputeStatistics,
     221                 :     INSTR_Band_SetStatistics,
     222                 :     INSTR_Band_ComputeRasterMinMax,
     223                 :     INSTR_Band_GetHistogram,
     224                 :     INSTR_Band_GetDefaultHistogram,
     225                 :     INSTR_Band_SetDefaultHistogram,
     226                 :     INSTR_Band_HasArbitraryOverviews,
     227                 :     INSTR_Band_GetOverviewCount,
     228                 :     INSTR_Band_GetOverview,
     229                 :     INSTR_Band_GetMaskBand,
     230                 :     INSTR_Band_GetMaskFlags,
     231                 :     INSTR_Band_CreateMaskBand,
     232                 :     INSTR_Band_Fill,
     233                 :     INSTR_Band_GetColorTable,
     234                 :     INSTR_Band_SetColorTable,
     235                 :     INSTR_Band_GetUnitType,
     236                 :     INSTR_Band_SetUnitType,
     237                 :     INSTR_Band_BuildOverviews,
     238                 :     INSTR_Band_GetDefaultRAT,
     239                 :     INSTR_Band_SetDefaultRAT,
     240                 :     INSTR_Band_AdviseRead,
     241                 :     INSTR_Band_End,
     242                 :     INSTR_END
     243                 : } InstrEnum;
     244                 : 
     245                 : #ifdef DEBUG
     246                 : static const char* apszInstr[] =
     247                 : {
     248                 :     "INVALID",
     249                 :     "GetGDALVersion",
     250                 :     "EXIT",
     251                 :     "FAIL",
     252                 :     "SetConfigOption",
     253                 :     "Progress",
     254                 :     "Reset",
     255                 :     "Open",
     256                 :     "Identify",
     257                 :     "Create",
     258                 :     "CreateCopy",
     259                 :     "QuietDelete",
     260                 :     "AddBand",
     261                 :     "GetGeoTransform",
     262                 :     "SetGeoTransform",
     263                 :     "GetProjectionRef",
     264                 :     "SetProjection",
     265                 :     "GetGCPCount",
     266                 :     "GetGCPProjection",
     267                 :     "GetGCPs",
     268                 :     "SetGCPs",
     269                 :     "GetFileList",
     270                 :     "FlushCache",
     271                 :     "SetDescription",
     272                 :     "GetMetadata",
     273                 :     "GetMetadataItem",
     274                 :     "SetMetadata",
     275                 :     "SetMetadataItem",
     276                 :     "IRasterIO_Read",
     277                 :     "IRasterIO_Write",
     278                 :     "IBuildOverviews",
     279                 :     "AdviseRead",
     280                 :     "CreateMaskBand",
     281                 :     "Band_First",
     282                 :     "Band_FlushCache",
     283                 :     "Band_GetCategoryNames",
     284                 :     "Band_SetCategoryNames",
     285                 :     "Band_SetDescription",
     286                 :     "Band_GetMetadata",
     287                 :     "Band_GetMetadataItem",
     288                 :     "Band_SetMetadata",
     289                 :     "Band_SetMetadataItem",
     290                 :     "Band_GetColorInterpretation",
     291                 :     "Band_SetColorInterpretation",
     292                 :     "Band_GetNoDataValue",
     293                 :     "Band_GetMinimum",
     294                 :     "Band_GetMaximum",
     295                 :     "Band_GetOffset",
     296                 :     "Band_GetScale",
     297                 :     "Band_SetNoDataValue",
     298                 :     "Band_SetOffset",
     299                 :     "Band_SetScale",
     300                 :     "Band_IReadBlock",
     301                 :     "Band_IWriteBlock",
     302                 :     "Band_IRasterIO_Read",
     303                 :     "Band_IRasterIO_Write",
     304                 :     "Band_GetStatistics",
     305                 :     "Band_ComputeStatistics",
     306                 :     "Band_SetStatistics",
     307                 :     "Band_ComputeRasterMinMax",
     308                 :     "Band_GetHistogram",
     309                 :     "Band_GetDefaultHistogram",
     310                 :     "Band_SetDefaultHistogram",
     311                 :     "Band_HasArbitraryOverviews",
     312                 :     "Band_GetOverviewCount",
     313                 :     "Band_GetOverview",
     314                 :     "Band_GetMaskBand",
     315                 :     "Band_GetMaskFlags",
     316                 :     "Band_CreateMaskBand",
     317                 :     "Band_Fill",
     318                 :     "Band_GetColorTable",
     319                 :     "Band_SetColorTable",
     320                 :     "Band_GetUnitType",
     321                 :     "Band_SetUnitType",
     322                 :     "Band_BuildOverviews",
     323                 :     "Band_GetDefaultRAT",
     324                 :     "Band_SetDefaultRAT",
     325                 :     "Band_AdviseRead",
     326                 :     "Band_End",
     327                 :     "END",
     328                 : };
     329                 : #endif
     330                 : 
     331                 : static const GByte abyEndOfJunkMarker[] = { 0xDE, 0xAD, 0xBE, 0xEF };
     332                 : 
     333                 : /* Recycling of connexions to child processes */
     334                 : #define MAX_RECYCLED        128
     335                 : #define DEFAULT_RECYCLED    4
     336                 : static int bRecycleChild = FALSE;
     337                 : static int nMaxRecycled = 0;
     338                 : static GDALServerSpawnedProcess* aspRecycled[MAX_RECYCLED];
     339                 : 
     340                 : /************************************************************************/
     341                 : /*                          EnterObject                                 */
     342                 : /************************************************************************/
     343                 : 
     344                 : #ifdef DEBUG_VERBOSE
     345                 : class EnterObject
     346                 : {
     347                 :     const char* pszFunction;
     348                 : 
     349                 :     public:
     350                 :         EnterObject(const char* pszFunction) : pszFunction(pszFunction)
     351                 :         {
     352                 :             CPLDebug("GDAL", "Enter %s", pszFunction);
     353                 :         }
     354                 : 
     355                 :         ~EnterObject()
     356                 :         {
     357                 :             CPLDebug("GDAL", "Leave %s", pszFunction);
     358                 :         }
     359                 : };
     360                 : 
     361                 : #define CLIENT_ENTER() EnterObject o(__FUNCTION__)
     362                 : #else
     363                 : #define CLIENT_ENTER() while(0)
     364                 : #endif
     365                 : 
     366                 : /************************************************************************/
     367                 : /*                            MyChdir()                                 */
     368                 : /************************************************************************/
     369                 : 
     370              25 : static void MyChdir(const char* pszCWD)
     371                 : {
     372                 : #ifdef WIN32
     373                 :     SetCurrentDirectory(pszCWD);
     374                 : #else
     375              25 :     chdir(pszCWD);
     376                 : #endif
     377              25 : }
     378                 : 
     379                 : /************************************************************************/
     380                 : /*                        MyChdirRootDirectory()                        */
     381                 : /************************************************************************/
     382                 : 
     383              12 : static void MyChdirRootDirectory()
     384                 : {
     385                 : #ifdef WIN32
     386                 :     SetCurrentDirectory("C:\\");
     387                 : #else
     388              12 :     chdir("/");
     389                 : #endif
     390              12 : }
     391                 : 
     392                 : /************************************************************************/
     393                 : /*                       GDALClientDataset                              */
     394                 : /************************************************************************/
     395                 : 
     396                 : class GDALClientDataset: public GDALPamDataset
     397                 : {
     398                 :     GDALServerSpawnedProcess                         *ssp;
     399                 :     GDALPipe                                         *p;
     400                 :     CPLString                                         osProjection;
     401                 :     CPLString                                         osGCPProjection;
     402                 :     int                                               bFreeDriver;
     403                 :     int                                               nGCPCount;
     404                 :     GDAL_GCP                                         *pasGCPs;
     405                 :     std::map<CPLString, char**>                       aoMapMetadata;
     406                 :     std::map< std::pair<CPLString,CPLString>, char*>  aoMapMetadataItem;
     407                 :     GDALServerAsyncProgress                          *async;
     408                 :     GByte                                             abyCaps[16]; /* 16 * 8 = 128 > INSTR_END */
     409                 : 
     410                 :         int                      mCreateCopy(const char* pszFilename,
     411                 :                                              GDALDataset* poSrcDS,
     412                 :                                              int bStrict, char** papszOptions,
     413                 :                                              GDALProgressFunc pfnProgress,
     414                 :                                              void * pProgressData);
     415                 :         int                      mCreate( const char * pszName,
     416                 :                                           int nXSize, int nYSize, int nBands,
     417                 :                                           GDALDataType eType,
     418                 :                                           char ** papszOptions );
     419                 : 
     420                 :                                   GDALClientDataset(GDALServerSpawnedProcess* ssp);
     421                 : 
     422                 :         static GDALClientDataset* CreateAndConnect();
     423                 : 
     424                 :     protected:
     425                 :        virtual CPLErr IBuildOverviews( const char *, int, int *,
     426                 :                                     int, int *, GDALProgressFunc, void * );
     427                 :        virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
     428                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
     429                 :                                void * pData, int nBufXSize, int nBufYSize,
     430                 :                                GDALDataType eBufType, 
     431                 :                                int nBandCount, int *panBandMap,
     432                 :                                int nPixelSpace, int nLineSpace, int nBandSpace);
     433                 :     public:
     434                 :                             GDALClientDataset(GDALPipe* p);
     435                 :                             ~GDALClientDataset();
     436                 : 
     437                 :         int                 Init(const char* pszFilename, GDALAccess eAccess);
     438                 : 
     439               2 :         void                AttachAsyncProgress(GDALServerAsyncProgress* async) { this->async = async; }
     440                 :         int                 ProcessAsyncProgress();
     441             203 :         int                 SupportsInstr(InstrEnum instr) const { return abyCaps[instr / 8] & (1 << (instr % 8)); }
     442                 : 
     443                 :         virtual void        FlushCache();
     444                 : 
     445                 :         virtual CPLErr        AddBand( GDALDataType eType, 
     446                 :                                    char **papszOptions=NULL );
     447                 : 
     448                 :         //virtual void        SetDescription( const char * );
     449                 : 
     450                 :         virtual const char* GetMetadataItem( const char * pszName,
     451                 :                                              const char * pszDomain = ""  );
     452                 :         virtual char      **GetMetadata( const char * pszDomain = "" );
     453                 :         virtual CPLErr      SetMetadata( char ** papszMetadata,
     454                 :                                          const char * pszDomain = "" );
     455                 :         virtual CPLErr      SetMetadataItem( const char * pszName,
     456                 :                                              const char * pszValue,
     457                 :                                              const char * pszDomain = "" );
     458                 : 
     459                 :         virtual const char* GetProjectionRef();
     460                 :         virtual CPLErr SetProjection( const char * );
     461                 : 
     462                 :         virtual CPLErr GetGeoTransform( double * );
     463                 :         virtual CPLErr SetGeoTransform( double * );
     464                 : 
     465                 :         virtual int    GetGCPCount();
     466                 :         virtual const char *GetGCPProjection();
     467                 :         virtual const GDAL_GCP *GetGCPs();
     468                 :         virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
     469                 :                                 const char *pszGCPProjection );
     470                 : 
     471                 :         virtual char      **GetFileList(void);
     472                 : 
     473                 :         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
     474                 :                                 int nBufXSize, int nBufYSize, 
     475                 :                                 GDALDataType eDT, 
     476                 :                                 int nBandCount, int *panBandList,
     477                 :                                 char **papszOptions );
     478                 : 
     479                 :         virtual CPLErr          CreateMaskBand( int nFlags );
     480                 : 
     481                 :         static GDALDataset *Open( GDALOpenInfo * );
     482                 :         static int          Identify( GDALOpenInfo * );
     483                 :         static GDALDataset *CreateCopy( const char * pszFilename, 
     484                 :                                         GDALDataset * poSrcDS, int bStrict, char ** papszOptions, 
     485                 :                                         GDALProgressFunc pfnProgress, void * pProgressData );
     486                 :         static GDALDataset* Create( const char * pszName,
     487                 :                                     int nXSize, int nYSize, int nBands,
     488                 :                                     GDALDataType eType,
     489                 :                                     char ** papszOptions );
     490                 :         static CPLErr       Delete( const char * pszName );
     491                 : };
     492                 : 
     493                 : /************************************************************************/
     494                 : /*                       GDALClientRasterBand                           */
     495                 : /************************************************************************/
     496                 : 
     497                 : class GDALClientRasterBand : public GDALPamRasterBand
     498                 : {
     499                 :     friend class GDALClientDataset;
     500                 : 
     501                 :     GDALPipe                                        *p;
     502                 :     int                                              iSrvBand;
     503                 :     std::map<int, GDALRasterBand*>                   aMapOvrBands;
     504                 :     std::map<int, GDALRasterBand*>                   aMapOvrBandsCurrent;
     505                 :     GDALRasterBand                                  *poMaskBand;
     506                 :     std::map<CPLString, char**>                      aoMapMetadata;
     507                 :     std::map< std::pair<CPLString,CPLString>, char*> aoMapMetadataItem;
     508                 :     char                                           **papszCategoryNames;
     509                 :     GDALColorTable                                  *poColorTable;
     510                 :     char                                            *pszUnitType;
     511                 :     GDALRasterAttributeTable                        *poRAT;
     512                 :     std::vector<GDALRasterBand*>                     apoOldMaskBands;
     513                 :     GByte                                            abyCaps[16]; /* 16 * 8 = 128 > INSTR_END */
     514                 : 
     515                 :     int                WriteInstr(InstrEnum instr);
     516                 : 
     517                 :     double             GetDouble( InstrEnum instr, int *pbSuccess );
     518                 :     CPLErr             SetDouble( InstrEnum instr, double dfVal );
     519                 : 
     520                 :     GDALRasterBand    *CreateFakeMaskBand();
     521                 : 
     522                 :     int                                              bEnableLineCaching;
     523                 :     int                                              nSuccessiveLinesRead;
     524                 :     GDALDataType                                     eLastBufType;
     525                 :     int                                              nLastYOff;
     526                 :     GByte                                           *pabyCachedLines;
     527                 :     GDALDataType                                     eCachedBufType;
     528                 :     int                                              nCachedYStart;
     529                 :     int                                              nCachedLines;
     530                 : 
     531                 :     void    InvalidateCachedLines();
     532                 :     CPLErr  IRasterIO_read_internal(
     533                 :                                 int nXOff, int nYOff, int nXSize, int nYSize,
     534                 :                                 void * pData, int nBufXSize, int nBufYSize,
     535                 :                                 GDALDataType eBufType,
     536                 :                                 int nPixelSpace, int nLineSpace );
     537                 :     protected:
     538                 : 
     539                 :         virtual CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void* pImage);
     540                 :         virtual CPLErr IWriteBlock(int nBlockXOff, int nBlockYOff, void* pImage);
     541                 :         virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
     542                 :                                   int nXOff, int nYOff, int nXSize, int nYSize,
     543                 :                                   void * pData, int nBufXSize, int nBufYSize,
     544                 :                                   GDALDataType eBufType,
     545                 :                                   int nPixelSpace, int nLineSpace );
     546                 : 
     547                 :     public:
     548                 :         GDALClientRasterBand(GDALPipe* p, int iSrvBand,
     549                 :                              GDALClientDataset* poDS, int nBand, GDALAccess eAccess,
     550                 :                              int nRasterXSize, int nRasterYSize,
     551                 :                              GDALDataType eDataType, int nBlockXSize, int nBlockYSize,
     552                 :                              GByte abyCaps[16]);
     553                 :         ~GDALClientRasterBand();
     554                 :         
     555               6 :         int GetSrvBand() const { return iSrvBand; }
     556             687 :         int SupportsInstr(InstrEnum instr) const { return abyCaps[instr / 8] & (1 << (instr % 8)); }
     557                 : 
     558               3 :         void ClearOverviewCache() { aMapOvrBandsCurrent.clear(); }
     559                 : 
     560                 :         virtual CPLErr FlushCache();
     561                 : 
     562                 :         virtual void        SetDescription( const char * );
     563                 : 
     564                 :         virtual const char* GetMetadataItem( const char * pszName,
     565                 :                                              const char * pszDomain = ""  );
     566                 :         virtual char      **GetMetadata( const char * pszDomain = "" );
     567                 :         virtual CPLErr      SetMetadata( char ** papszMetadata,
     568                 :                                          const char * pszDomain = "" );
     569                 :         virtual CPLErr      SetMetadataItem( const char * pszName,
     570                 :                                              const char * pszValue,
     571                 :                                              const char * pszDomain = "" );
     572                 : 
     573                 :         virtual GDALColorInterp GetColorInterpretation();
     574                 :         virtual CPLErr SetColorInterpretation( GDALColorInterp );
     575                 : 
     576                 :         virtual char **GetCategoryNames();
     577                 :         virtual double GetNoDataValue( int *pbSuccess = NULL );
     578                 :         virtual double GetMinimum( int *pbSuccess = NULL );
     579                 :         virtual double GetMaximum(int *pbSuccess = NULL );
     580                 :         virtual double GetOffset( int *pbSuccess = NULL );
     581                 :         virtual double GetScale( int *pbSuccess = NULL );
     582                 : 
     583                 :         virtual GDALColorTable *GetColorTable();
     584                 :         virtual CPLErr SetColorTable( GDALColorTable * ); 
     585                 : 
     586                 :         virtual const char *GetUnitType();
     587                 :         virtual CPLErr SetUnitType( const char * );
     588                 : 
     589                 :         virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0);
     590                 : 
     591                 :         virtual CPLErr SetCategoryNames( char ** );
     592                 :         virtual CPLErr SetNoDataValue( double );
     593                 :         virtual CPLErr SetOffset( double );
     594                 :         virtual CPLErr SetScale( double );
     595                 : 
     596                 :         virtual CPLErr GetStatistics( int bApproxOK, int bForce,
     597                 :                                     double *pdfMin, double *pdfMax, 
     598                 :                                     double *pdfMean, double *padfStdDev );
     599                 :         virtual CPLErr ComputeStatistics( int bApproxOK, 
     600                 :                                         double *pdfMin, double *pdfMax, 
     601                 :                                         double *pdfMean, double *pdfStdDev,
     602                 :                                         GDALProgressFunc, void *pProgressData );
     603                 :         virtual CPLErr SetStatistics( double dfMin, double dfMax, 
     604                 :                                       double dfMean, double dfStdDev );
     605                 :         virtual CPLErr ComputeRasterMinMax( int, double* );
     606                 : 
     607                 :         virtual CPLErr GetHistogram( double dfMin, double dfMax, 
     608                 :                                      int nBuckets, int *panHistogram, 
     609                 :                                      int bIncludeOutOfRange, int bApproxOK,
     610                 :                                      GDALProgressFunc pfnProgress, 
     611                 :                                      void *pProgressData );
     612                 : 
     613                 :         virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
     614                 :                                             int *pnBuckets, int ** ppanHistogram,
     615                 :                                             int bForce,
     616                 :                                             GDALProgressFunc, void *pProgressData);
     617                 :         virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
     618                 :                                             int nBuckets, int *panHistogram );
     619                 : 
     620                 :         virtual int HasArbitraryOverviews();
     621                 :         virtual int GetOverviewCount();
     622                 :         virtual GDALRasterBand *GetOverview(int);
     623                 : 
     624                 :         virtual GDALRasterBand *GetMaskBand();
     625                 :         virtual int             GetMaskFlags();
     626                 :         virtual CPLErr          CreateMaskBand( int nFlags );
     627                 : 
     628                 :         virtual CPLErr BuildOverviews( const char *, int, int *,
     629                 :                                        GDALProgressFunc, void * );
     630                 : 
     631                 :         virtual const GDALRasterAttributeTable *GetDefaultRAT();
     632                 :         virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
     633                 : 
     634                 :         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
     635                 :                                 int nBufXSize, int nBufYSize, 
     636                 :                                 GDALDataType eDT, char **papszOptions );
     637                 :         /*
     638                 :         virtual GDALRasterBand *GetRasterSampleOverview( int );
     639                 :         */
     640                 : 
     641                 : };
     642                 : 
     643                 : /************************************************************************/
     644                 : /*                          GDALPipeBuild()                             */
     645                 : /************************************************************************/
     646                 : 
     647               2 : static GDALPipe* GDALPipeBuild(CPLSpawnedProcess* sp)
     648                 : {
     649               2 :     GDALPipe* p = (GDALPipe*)CPLMalloc(sizeof(GDALPipe));
     650               2 :     p->bOK = TRUE;
     651               2 :     p->fin = CPLSpawnAsyncGetInputFileHandle(sp);
     652               2 :     p->fout = CPLSpawnAsyncGetOutputFileHandle(sp);
     653               2 :     p->nSocket = INVALID_SOCKET;
     654               2 :     p->nBufferSize = 0;
     655               2 :     return p;
     656                 : }
     657                 : 
     658               8 : static GDALPipe* GDALPipeBuild(CPL_SOCKET nSocket)
     659                 : {
     660               8 :     GDALPipe* p = (GDALPipe*)CPLMalloc(sizeof(GDALPipe));
     661               8 :     p->bOK = TRUE;
     662               8 :     p->fin = CPL_FILE_INVALID_HANDLE;
     663               8 :     p->fout = CPL_FILE_INVALID_HANDLE;
     664               8 :     p->nSocket = nSocket;
     665               8 :     p->nBufferSize = 0;
     666               8 :     return p;
     667                 : }
     668                 : 
     669               0 : static GDALPipe* GDALPipeBuild(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout)
     670                 : {
     671               0 :     GDALPipe* p = (GDALPipe*)CPLMalloc(sizeof(GDALPipe));
     672               0 :     p->bOK = TRUE;
     673               0 :     p->fin = fin;
     674               0 :     p->fout = fout;
     675               0 :     p->nSocket = INVALID_SOCKET;
     676               0 :     p->nBufferSize = 0;
     677               0 :     return p;
     678                 : }
     679                 : 
     680                 : /************************************************************************/
     681                 : /*                      GDALPipeWrite_internal()                        */
     682                 : /************************************************************************/
     683                 : 
     684            1256 : static int GDALPipeWrite_internal(GDALPipe* p, const void* data, int length)
     685                 : {
     686            1256 :     if(!p->bOK)
     687               0 :         return FALSE;
     688            1256 :     if( p->fout != CPL_FILE_INVALID_HANDLE )
     689                 :     {
     690             240 :         int nRet = CPLPipeWrite(p->fout, data, length);
     691             240 :         if( !nRet )
     692                 :         {
     693               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Write to pipe failed");
     694               0 :             p->bOK = FALSE;
     695                 :         }
     696             240 :         return nRet;
     697                 :     }
     698                 :     else
     699                 :     {
     700            1016 :         const char* pabyData = (const char*) data;
     701            1016 :         int nRemain = length;
     702            3048 :         while( nRemain > 0 )
     703                 :         {
     704            1016 :             int nRet = send(p->nSocket, pabyData, nRemain, 0);
     705            1016 :             if( nRet < 0 )
     706                 :             {
     707               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Write to socket failed");
     708               0 :                 p->bOK = FALSE;
     709               0 :                 return FALSE;
     710                 :             }
     711            1016 :             pabyData += nRet;
     712            1016 :             nRemain -= nRet;
     713                 :         }
     714            1016 :         return TRUE;
     715                 :     }
     716                 : }
     717                 : 
     718                 : /************************************************************************/
     719                 : /*                        GDALPipeFlushBuffer()                         */
     720                 : /************************************************************************/
     721                 : 
     722            6754 : static int GDALPipeFlushBuffer(GDALPipe * p)
     723                 : {
     724            6754 :     if( p->nBufferSize == 0 )
     725            5525 :         return TRUE;
     726            1229 :     if( GDALPipeWrite_internal(p, p->abyBuffer, p->nBufferSize) )
     727                 :     {
     728            1229 :         p->nBufferSize = 0;
     729            1229 :         return TRUE;
     730                 :     }
     731               0 :     return FALSE;
     732                 : }
     733                 : 
     734                 : /************************************************************************/
     735                 : /*                            GDALPipeFree()                            */
     736                 : /************************************************************************/
     737                 : 
     738              10 : static void GDALPipeFree(GDALPipe * p)
     739                 : {
     740              10 :     GDALPipeFlushBuffer(p);
     741              10 :     if( p->nSocket != INVALID_SOCKET )
     742                 :     {
     743               8 :         closesocket(p->nSocket);
     744                 :         WSACleanup();
     745                 :     }
     746              10 :     CPLFree(p);
     747              10 : }
     748                 : 
     749                 : /************************************************************************/
     750                 : /*                            GDALPipeRead()                            */
     751                 : /************************************************************************/
     752                 : 
     753            6713 : static int GDALPipeRead(GDALPipe* p, void* data, int length)
     754                 : {
     755            6713 :     if(!p->bOK)
     756               0 :         return FALSE;
     757            6713 :     if(!GDALPipeFlushBuffer(p))
     758               0 :         return FALSE;
     759                 :     
     760            6713 :     if( p->fout != CPL_FILE_INVALID_HANDLE )
     761                 :     {
     762            1283 :         if( CPLPipeRead(p->fin, data, length) )
     763            1283 :             return TRUE;
     764                 :         // fprintf(stderr, "[%d] Read from pipe failed\n", (int)getpid());
     765               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Read from pipe failed");
     766               0 :         p->bOK = FALSE;
     767               0 :         return FALSE;
     768                 :     }
     769                 :     else
     770                 :     {
     771            5430 :         char* pabyData = (char*) data;
     772            5430 :         int nRemain = length;
     773           16292 :         while( nRemain > 0 )
     774                 :         {
     775            5432 :             int nRet = recv(p->nSocket, pabyData, nRemain, 0);
     776            5432 :             if( nRet <= 0 )
     777                 :             {
     778               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Read from socket failed");
     779               0 :                 p->bOK = FALSE;
     780               0 :                 return FALSE;
     781                 :             }
     782            5432 :             pabyData += nRet;
     783            5432 :             nRemain -= nRet;
     784                 :         }
     785            5430 :         return TRUE;
     786                 :     }
     787                 : 
     788                 : }
     789                 : 
     790                 : /************************************************************************/
     791                 : /*                           GDALPipeWrite()                            */
     792                 : /************************************************************************/
     793                 : 
     794            6824 : static int GDALPipeWrite(GDALPipe* p, const void* data,
     795                 :                                  int length)
     796                 : {
     797                 :     //return GDALPipeWrite_internal(p, data, length);
     798            6824 :     GByte* pCur = (GByte*) data;
     799            6824 :     int nRemain = length;
     800           20476 :     while( nRemain > 0 )
     801                 :     {
     802            6828 :         if( p->nBufferSize + nRemain <= BUFFER_SIZE )
     803                 :         {
     804            6797 :             memcpy(p->abyBuffer + p->nBufferSize, pCur, nRemain);
     805            6797 :             pCur += nRemain;
     806            6797 :             p->nBufferSize += nRemain;
     807            6797 :             nRemain = 0;
     808                 :         }
     809              31 :         else if( nRemain > BUFFER_SIZE )
     810                 :         {
     811              27 :             if( !GDALPipeFlushBuffer(p) )
     812               0 :                 return FALSE;
     813              27 :             if( !GDALPipeWrite_internal(p, pCur, nRemain) )
     814               0 :                 return FALSE;
     815              27 :             pCur += nRemain;
     816              27 :             nRemain = 0;
     817                 :         }
     818                 :         else
     819                 :         {
     820                 :             memcpy(p->abyBuffer + p->nBufferSize, pCur,
     821               4 :                    BUFFER_SIZE - p->nBufferSize);
     822               4 :             pCur += (BUFFER_SIZE - p->nBufferSize);
     823               4 :             nRemain -= (BUFFER_SIZE - p->nBufferSize);
     824               4 :             p->nBufferSize = BUFFER_SIZE;
     825               4 :             if( !GDALPipeFlushBuffer(p) )
     826               0 :                 return FALSE;
     827                 :         }
     828                 :     }
     829            6824 :     return TRUE;
     830                 : }
     831                 : 
     832                 : /************************************************************************/
     833                 : /*                          GDALPipeRead()                              */
     834                 : /************************************************************************/
     835                 : 
     836            4432 : static int GDALPipeRead(GDALPipe* p, int* pnInt)
     837                 : {
     838            4432 :     return GDALPipeRead(p, pnInt, 4);
     839                 : }
     840                 : 
     841             215 : static int GDALPipeRead(GDALPipe* p, CPLErr* peErr)
     842                 : {
     843             215 :     return GDALPipeRead(p, peErr, 4);
     844                 : }
     845                 : 
     846             165 : static int GDALPipeRead(GDALPipe* p, double* pdfDouble)
     847                 : {
     848             165 :     return GDALPipeRead(p, pdfDouble, 8);
     849                 : }
     850                 : 
     851            1901 : static int GDALPipeRead_nolength(GDALPipe* p, int nLength, void* pabyData)
     852                 : {
     853            1901 :     return GDALPipeRead(p, pabyData, nLength);
     854                 : }
     855                 : 
     856              43 : static int GDALPipeRead(GDALPipe* p, int nExpectedLength, void* pabyData)
     857                 : {
     858                 :     int nLength;
     859                 :     return GDALPipeRead(p, &nLength) &&
     860                 :            nLength == nExpectedLength &&
     861              43 :            GDALPipeRead_nolength(p, nLength, pabyData);
     862                 : }
     863                 : 
     864            1414 : static int GDALPipeRead(GDALPipe* p, char** ppszStr)
     865                 : {
     866                 :     int nLength;
     867            1414 :     if( !GDALPipeRead(p, &nLength) || nLength < 0 )
     868                 :     {
     869               0 :         *ppszStr = NULL;
     870               0 :         return FALSE;
     871                 :     }
     872            1414 :     if( nLength == 0 )
     873                 :     {
     874             323 :         *ppszStr = NULL;
     875             323 :         return TRUE;
     876                 :     }
     877            1091 :     *ppszStr = (nLength < INT_MAX-1) ? (char*) VSIMalloc(nLength + 1) : NULL;
     878            1091 :     if( *ppszStr == NULL )
     879               0 :         return FALSE;
     880            1091 :     if( nLength > 0 && !GDALPipeRead_nolength(p, nLength, *ppszStr) )
     881                 :     {
     882               0 :         CPLFree(*ppszStr);
     883               0 :         *ppszStr = NULL;
     884               0 :         return FALSE;
     885                 :     }
     886            1091 :     (*ppszStr)[nLength] = 0;
     887            1091 :     return TRUE;
     888                 : }
     889                 : 
     890                 : 
     891              93 : static int GDALPipeRead(GDALPipe* p, char*** ppapszStr)
     892                 : {
     893                 :     int nStrCount;
     894              93 :     if( !GDALPipeRead(p, &nStrCount) )
     895               0 :         return FALSE;
     896              93 :     if( nStrCount < 0 )
     897                 :     {
     898              48 :         *ppapszStr = NULL;
     899              48 :         return TRUE;
     900                 :     }
     901                 : 
     902              45 :     *ppapszStr = (char**) VSIMalloc2(sizeof(char*), (nStrCount + 1));
     903              45 :     if( *ppapszStr == NULL )
     904               0 :         return FALSE;
     905              98 :     for(int i=0;i<nStrCount;i++)
     906                 :     {
     907              53 :         if( !GDALPipeRead(p, (*ppapszStr) + i) )
     908                 :         {
     909               0 :             CSLDestroy(*ppapszStr);
     910               0 :             *ppapszStr = NULL;
     911               0 :             return FALSE;
     912                 :         }
     913                 :     }
     914              45 :     (*ppapszStr)[nStrCount] = NULL;
     915              45 :     return TRUE;
     916                 : }
     917                 : 
     918              17 : static int GDALPipeRead(GDALPipe* p, int nItems, int** ppanInt)
     919                 : {
     920                 :     int nSize;
     921              17 :     *ppanInt = NULL;
     922              17 :     if( !GDALPipeRead(p, &nSize) )
     923               0 :         return FALSE;
     924              17 :     if( nSize != nItems * (int)sizeof(int) )
     925               0 :         return FALSE;
     926              17 :     *ppanInt = (int*) VSIMalloc(nSize);
     927              17 :     if( *ppanInt == NULL )
     928               0 :         return FALSE;
     929              17 :     if( !GDALPipeRead_nolength(p, nSize, *ppanInt) )
     930               0 :         return FALSE;
     931              17 :     return TRUE;
     932                 : }
     933                 : 
     934              28 : static int GDALPipeRead(GDALPipe* p, GDALColorTable** ppoColorTable)
     935                 : {
     936                 :     int nPaletteInterp, nCount;
     937              28 :     *ppoColorTable = NULL;
     938              28 :     if( !GDALPipeRead(p, &nPaletteInterp) )
     939               0 :         return FALSE;
     940                 :     GDALColorTable* poColorTable;
     941              28 :     if( nPaletteInterp < 0 )
     942                 :     {
     943              23 :         poColorTable = NULL;
     944                 :     }
     945                 :     else
     946                 :     {
     947               5 :         if( !GDALPipeRead(p, &nCount) )
     948               0 :             return FALSE;
     949               5 :         poColorTable = new GDALColorTable((GDALPaletteInterp)nPaletteInterp);
     950              10 :         for(int i=0; i<nCount; i++)
     951                 :         {
     952                 :             int c1, c2, c3, c4;
     953               5 :             if( !GDALPipeRead(p, &c1) ||
     954                 :                 !GDALPipeRead(p, &c2) ||
     955                 :                 !GDALPipeRead(p, &c3) ||
     956                 :                 !GDALPipeRead(p, &c4) )
     957                 :             {
     958               0 :                 delete poColorTable;
     959               0 :                 return FALSE;
     960                 :             }
     961                 :             GDALColorEntry eEntry;
     962               5 :             eEntry.c1 = (short)c1;
     963               5 :             eEntry.c2 = (short)c2;
     964               5 :             eEntry.c3 = (short)c3;
     965               5 :             eEntry.c4 = (short)c4;
     966               5 :             poColorTable->SetColorEntry(i, &eEntry);
     967                 :         }
     968                 :     }
     969              28 :     *ppoColorTable = poColorTable;
     970              28 :     return TRUE;
     971                 : }
     972                 : 
     973               8 : static int GDALPipeRead(GDALPipe* p, GDALRasterAttributeTable** ppoRAT)
     974                 : {
     975               8 :     *ppoRAT = NULL;
     976               8 :     char* pszRAT = NULL;
     977               8 :     if( !GDALPipeRead(p, &pszRAT))
     978               0 :         return FALSE;
     979               8 :     if( pszRAT == NULL )
     980               8 :         return TRUE;
     981                 : 
     982               0 :     CPLXMLNode* poNode = CPLParseXMLString( pszRAT );
     983               0 :     CPLFree(pszRAT);
     984               0 :     if( poNode == NULL )
     985               0 :         return FALSE;
     986                 : 
     987               0 :     *ppoRAT = new GDALRasterAttributeTable();
     988               0 :     if( (*ppoRAT)->XMLInit(poNode, NULL) != CE_None )
     989                 :     {
     990               0 :         CPLDestroyXMLNode(poNode);
     991               0 :         delete *ppoRAT;
     992               0 :         *ppoRAT = NULL;
     993               0 :         return FALSE;
     994                 :     }
     995               0 :     CPLDestroyXMLNode(poNode);
     996               0 :     return TRUE;
     997                 : }
     998                 : 
     999               3 : static int GDALPipeRead(GDALPipe* p, int* pnGCPCount, GDAL_GCP** ppasGCPs)
    1000                 : {
    1001               3 :     *pnGCPCount = 0;
    1002               3 :     *ppasGCPs = NULL;
    1003                 :     int nGCPCount;
    1004               3 :     if( !GDALPipeRead(p, &nGCPCount) )
    1005               0 :         return FALSE;
    1006               3 :     GDAL_GCP* pasGCPs = (GDAL_GCP* )CPLCalloc(nGCPCount, sizeof(GDAL_GCP));
    1007               3 :     for(int i=0;i<nGCPCount;i++)
    1008                 :     {
    1009               0 :         if( !GDALPipeRead(p, &pasGCPs[i].pszId) ||
    1010               0 :             !GDALPipeRead(p, &pasGCPs[i].pszInfo) ||
    1011               0 :             !GDALPipeRead(p, &pasGCPs[i].dfGCPPixel) ||
    1012               0 :             !GDALPipeRead(p, &pasGCPs[i].dfGCPLine) ||
    1013               0 :             !GDALPipeRead(p, &pasGCPs[i].dfGCPX) ||
    1014               0 :             !GDALPipeRead(p, &pasGCPs[i].dfGCPY) ||
    1015               0 :             !GDALPipeRead(p, &pasGCPs[i].dfGCPZ) )
    1016                 :         {
    1017               0 :             GDALDeinitGCPs(i, pasGCPs);
    1018               0 :             CPLFree(pasGCPs);
    1019               0 :             return FALSE;
    1020                 :         }
    1021                 :     }
    1022               3 :     *pnGCPCount = nGCPCount;
    1023               3 :     *ppasGCPs = pasGCPs;
    1024               3 :     return TRUE;
    1025                 : }
    1026                 : 
    1027              29 : static int GDALPipeRead(GDALPipe* p, GDALClientDataset* poDS,
    1028                 :                         GDALRasterBand** ppoBand, GByte abyCaps[16])
    1029                 : {
    1030                 :     int iSrvBand;
    1031              29 :     *ppoBand = NULL;
    1032              29 :     if( !GDALPipeRead(p, &iSrvBand) )
    1033               0 :         return FALSE;
    1034              29 :     if( iSrvBand < 0 )
    1035               3 :         return TRUE;
    1036                 : 
    1037                 :     int iBand, nBandAccess, nXSize, nYSize, nDataType, nBlockXSize, nBlockYSize;
    1038              26 :     if( !GDALPipeRead(p, &iBand) ||
    1039                 :         !GDALPipeRead(p, &nBandAccess) ||
    1040                 :         !GDALPipeRead(p, &nXSize) ||
    1041                 :         !GDALPipeRead(p, &nYSize) ||
    1042                 :         !GDALPipeRead(p, &nDataType) ||
    1043                 :         !GDALPipeRead(p, &nBlockXSize) ||
    1044                 :         !GDALPipeRead(p, &nBlockYSize) )
    1045                 :     {
    1046               0 :         return FALSE;
    1047                 :     }
    1048                 : 
    1049              26 :     char* pszDescription = NULL;
    1050              26 :     if( !GDALPipeRead(p, &pszDescription) )
    1051               0 :         return FALSE;
    1052                 : 
    1053                 :     GDALClientRasterBand* poBand = new GDALClientRasterBand(p, iSrvBand,
    1054                 :                                                   poDS, iBand, (GDALAccess)nBandAccess,
    1055                 :                                                   nXSize, nYSize,
    1056                 :                                                   (GDALDataType)nDataType,
    1057              26 :                                                   nBlockXSize, nBlockYSize, abyCaps);
    1058              26 :     if( pszDescription != NULL )
    1059              26 :         poBand->GDALMajorObject::SetDescription(pszDescription);
    1060              26 :     CPLFree(pszDescription);
    1061                 : 
    1062              26 :     *ppoBand = poBand;
    1063              26 :     return TRUE;
    1064                 : }
    1065                 : 
    1066                 : /************************************************************************/
    1067                 : /*                GDALSkipUntilEndOfJunkMarker()                        */
    1068                 : /************************************************************************/
    1069                 : 
    1070             653 : static int GDALSkipUntilEndOfJunkMarker(GDALPipe* p)
    1071                 : {
    1072             653 :     if(!p->bOK)
    1073               0 :         return FALSE;
    1074                 :     GByte c;
    1075             653 :     size_t nIter = 0;
    1076             653 :     int nStep = 0;
    1077             653 :     CPLString osJunk;
    1078             653 :     int nMarkerSize = (int)sizeof(abyEndOfJunkMarker);
    1079                 :     GByte abyBuffer[sizeof(abyEndOfJunkMarker)];
    1080             653 :     if( !GDALPipeRead_nolength(p, sizeof(abyBuffer), abyBuffer ) )
    1081               0 :         return FALSE;
    1082             653 :     if( memcmp(abyEndOfJunkMarker, abyBuffer, sizeof(abyBuffer)) == 0 )
    1083             650 :         return TRUE;
    1084              21 :     while(TRUE)
    1085                 :     {
    1086              24 :         if( nIter < sizeof(abyBuffer) )
    1087              12 :             c = abyBuffer[nIter ++];
    1088              12 :         else if( !GDALPipeRead_nolength(p, 1, &c ) )
    1089               0 :             return FALSE;
    1090                 : 
    1091              24 :         if( c != 0 )
    1092              12 :             osJunk += c;
    1093              24 :         if( c == abyEndOfJunkMarker[0] ) nStep = 1;
    1094              21 :         else if( c == abyEndOfJunkMarker[nStep] )
    1095                 :         {
    1096               9 :             nStep ++;
    1097               9 :             if( nStep == nMarkerSize )
    1098                 :             {
    1099               3 :                 osJunk.resize(osJunk.size() - nMarkerSize);
    1100               3 :                 if( osJunk.size() )
    1101               0 :                     CPLDebug("GDAL", "Got junk : %s", osJunk.c_str());
    1102               3 :                 return TRUE;
    1103                 :             }
    1104                 :         }
    1105                 :         else
    1106              12 :             nStep = 0;
    1107               0 :     }
    1108                 : }
    1109                 : 
    1110                 : /************************************************************************/
    1111                 : /*                         GDALPipeWrite()                              */
    1112                 : /************************************************************************/
    1113                 : 
    1114            4924 : static int GDALPipeWrite(GDALPipe* p, int nInt)
    1115                 : {
    1116            4924 :     return GDALPipeWrite(p, &nInt, 4);
    1117                 : }
    1118                 : 
    1119             145 : static int GDALPipeWrite(GDALPipe* p, double dfDouble)
    1120                 : {
    1121             145 :     return GDALPipeWrite(p, &dfDouble, 8);
    1122                 : }
    1123                 : 
    1124            1755 : static int GDALPipeWrite_nolength(GDALPipe* p, int nLength, const void* pabyData)
    1125                 : {
    1126            1755 :     return GDALPipeWrite(p, pabyData, nLength);
    1127                 : }
    1128                 : 
    1129            1224 : static int GDALPipeWrite(GDALPipe* p, int nLength, const void* pabyData)
    1130                 : {
    1131            1224 :     if( !GDALPipeWrite(p, nLength) ||
    1132                 :         !GDALPipeWrite_nolength(p, nLength, pabyData) )
    1133               0 :         return FALSE;
    1134            1224 :     return TRUE;
    1135                 : }
    1136                 : 
    1137            1507 : static int GDALPipeWrite(GDALPipe* p, const char* pszStr)
    1138                 : {
    1139            1507 :     if( pszStr == NULL )
    1140             402 :         return GDALPipeWrite(p, 0);
    1141            1105 :     return GDALPipeWrite(p, (int)strlen(pszStr) + 1, pszStr);
    1142                 : }
    1143                 : 
    1144              92 : static int GDALPipeWrite(GDALPipe* p, char** papszStr)
    1145                 : {
    1146              92 :     if( papszStr == NULL )
    1147              47 :         return GDALPipeWrite(p, -1);
    1148                 : 
    1149              45 :     int nCount = CSLCount(papszStr);
    1150              45 :     if( !GDALPipeWrite(p, nCount) )
    1151               0 :         return FALSE;
    1152              97 :     for(int i=0; i < nCount; i++)
    1153                 :     {
    1154              52 :         if( !GDALPipeWrite(p, papszStr[i]) )
    1155               0 :             return FALSE;
    1156                 :     }
    1157              45 :     return TRUE;
    1158                 : }
    1159                 : 
    1160              21 : static int GDALPipeWrite(GDALPipe* p,
    1161                 :                          std::vector<GDALRasterBand*>& aBands,
    1162                 :                          GDALRasterBand* poBand)
    1163                 : {
    1164              21 :     if( poBand == NULL )
    1165               2 :         GDALPipeWrite(p, -1);
    1166                 :     else
    1167                 :     {
    1168              19 :         GDALPipeWrite(p, (int)aBands.size());
    1169              19 :         aBands.push_back(poBand);
    1170              19 :         GDALPipeWrite(p, poBand->GetBand());
    1171              19 :         GDALPipeWrite(p, poBand->GetAccess());
    1172              19 :         GDALPipeWrite(p, poBand->GetXSize());
    1173              19 :         GDALPipeWrite(p, poBand->GetYSize());
    1174              19 :         GDALPipeWrite(p, poBand->GetRasterDataType());
    1175                 :         int nBlockXSize, nBlockYSize;
    1176              19 :         poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
    1177              19 :         GDALPipeWrite(p, nBlockXSize);
    1178              19 :         GDALPipeWrite(p, nBlockYSize);
    1179              19 :         GDALPipeWrite(p, poBand->GetDescription() );
    1180                 :     }
    1181              21 :     return TRUE;
    1182                 : }
    1183                 : 
    1184              27 : static int GDALPipeWrite(GDALPipe* p, GDALColorTable* poColorTable)
    1185                 : {
    1186              27 :     if( poColorTable == NULL )
    1187                 :     {
    1188              22 :         if( !GDALPipeWrite(p, -1) )
    1189               0 :             return FALSE;
    1190                 :     }
    1191                 :     else
    1192                 :     {
    1193               5 :         int nCount = poColorTable->GetColorEntryCount();
    1194               5 :         if( !GDALPipeWrite(p, poColorTable->GetPaletteInterpretation()) ||
    1195                 :             !GDALPipeWrite(p, nCount) )
    1196               0 :             return FALSE;
    1197                 : 
    1198              10 :         for(int i=0; i < nCount; i++)
    1199                 :         {
    1200               5 :             const GDALColorEntry* poColorEntry = poColorTable->GetColorEntry(i);
    1201               5 :             if( !GDALPipeWrite(p, poColorEntry->c1) ||
    1202                 :                 !GDALPipeWrite(p, poColorEntry->c2) ||
    1203                 :                 !GDALPipeWrite(p, poColorEntry->c3) ||
    1204                 :                 !GDALPipeWrite(p, poColorEntry->c4) )
    1205               0 :                 return FALSE;
    1206                 :         }
    1207                 :     }
    1208              27 :     return TRUE;
    1209                 : }
    1210                 : 
    1211               7 : static int GDALPipeWrite(GDALPipe* p, const GDALRasterAttributeTable* poRAT)
    1212                 : {
    1213                 :     int bRet;
    1214               7 :     if( poRAT == NULL )
    1215               7 :         bRet = GDALPipeWrite(p, (const char*)NULL);
    1216                 :     else
    1217                 :     {
    1218               0 :         CPLXMLNode* poNode = poRAT->Serialize();
    1219               0 :         if( poNode != NULL )
    1220                 :         {
    1221               0 :             char* pszRAT = CPLSerializeXMLTree(poNode);
    1222               0 :             bRet = GDALPipeWrite(p, pszRAT);
    1223               0 :             CPLFree(pszRAT);
    1224               0 :             CPLDestroyXMLNode(poNode);
    1225                 :         }
    1226                 :         else
    1227               0 :             bRet = GDALPipeWrite(p, (const char*)NULL);
    1228                 :     }
    1229               7 :     return bRet;
    1230                 : }
    1231                 : 
    1232               2 : static int GDALPipeWrite(GDALPipe* p, int nGCPCount, const GDAL_GCP* pasGCPs)
    1233                 : {
    1234               2 :     if( !GDALPipeWrite(p, nGCPCount ) )
    1235               0 :         return FALSE;
    1236               2 :     for(int i=0;i<nGCPCount;i++)
    1237                 :     {
    1238               0 :         if( !GDALPipeWrite(p, pasGCPs[i].pszId) ||
    1239               0 :             !GDALPipeWrite(p, pasGCPs[i].pszInfo) ||
    1240               0 :             !GDALPipeWrite(p, pasGCPs[i].dfGCPPixel) ||
    1241               0 :             !GDALPipeWrite(p, pasGCPs[i].dfGCPLine) ||
    1242               0 :             !GDALPipeWrite(p, pasGCPs[i].dfGCPX) ||
    1243               0 :             !GDALPipeWrite(p, pasGCPs[i].dfGCPY) ||
    1244               0 :             !GDALPipeWrite(p, pasGCPs[i].dfGCPZ) )
    1245               0 :             return FALSE;
    1246                 :     }
    1247               2 :     return TRUE;
    1248                 : }
    1249                 : 
    1250                 : /************************************************************************/
    1251                 : /*                    GDALPipeWriteConfigOption()                       */
    1252                 : /************************************************************************/
    1253                 : 
    1254             346 : static int GDALPipeWriteConfigOption(GDALPipe* p, const char* pszKey,
    1255                 :                                      int bWriteIfNonNull = TRUE)
    1256                 : {
    1257             346 :     const char* pszVal = CPLGetConfigOption(pszKey, NULL);
    1258             346 :     if( pszVal == NULL && !bWriteIfNonNull )
    1259               0 :         return TRUE;
    1260                 :     return GDALPipeWrite(p, INSTR_SetConfigOption) &&
    1261                 :            GDALPipeWrite(p, pszKey) &&
    1262             346 :            GDALPipeWrite(p, pszVal);
    1263                 : }
    1264                 : 
    1265                 : /************************************************************************/
    1266                 : /*                    GDALEmitEndOfJunkMarker()                         */
    1267                 : /************************************************************************/
    1268                 : 
    1269                 : /* When receiving an instruction : */
    1270                 : /* - read all input arguments */
    1271                 : /* - do the call to the dataset or the band */
    1272                 : /* - as the previous call may potentially emit */
    1273                 : /*   unwanted content on the stdout, we emit */
    1274                 : /*   a special marker that the receiver will */
    1275                 : /*   wait until interpreting the rest of the */
    1276                 : /*   output arguments */
    1277                 : /* - emit output arguments */
    1278             527 : static int GDALEmitEndOfJunkMarker(GDALPipe* p)
    1279                 : {
    1280                 :     return GDALPipeWrite_nolength(p, sizeof(abyEndOfJunkMarker),
    1281                 :                                   abyEndOfJunkMarker) ==
    1282             527 :                                         (int)sizeof(abyEndOfJunkMarker);
    1283                 : }
    1284                 : 
    1285                 : /************************************************************************/
    1286                 : /*                       GDALConsumeErrors()                            */
    1287                 : /************************************************************************/
    1288                 : 
    1289             646 : static void GDALConsumeErrors(GDALPipe* p)
    1290                 : {
    1291                 :     int nErrors;
    1292             646 :     if( !GDALPipeRead(p, &nErrors) )
    1293               0 :         return;
    1294             649 :     for(int i=0;i<nErrors;i++)
    1295                 :     {
    1296                 :         int       eErr;
    1297                 :         int       nErrNo;
    1298               3 :         char     *pszErrorMsg = NULL;
    1299               3 :         if( !GDALPipeRead(p, &eErr) ||
    1300                 :             !GDALPipeRead(p, &nErrNo) ||
    1301                 :             !GDALPipeRead(p, &pszErrorMsg) )
    1302               0 :             return;
    1303               3 :         CPLError((CPLErr)eErr, nErrNo, "%s", pszErrorMsg ? pszErrorMsg : "unknown");
    1304               3 :         CPLFree(pszErrorMsg);
    1305                 :     }
    1306                 : }
    1307                 : 
    1308                 : /************************************************************************/
    1309                 : /*                       GDALEmitReset()                                */
    1310                 : /************************************************************************/
    1311                 : 
    1312              21 : static int GDALEmitReset(GDALPipe* p)
    1313                 : {
    1314                 :     int bOK;
    1315              21 :     if( !GDALPipeWrite(p, INSTR_Reset) ||
    1316                 :         !GDALSkipUntilEndOfJunkMarker(p) ||
    1317                 :         !GDALPipeRead(p, &bOK) )
    1318               0 :         return FALSE;
    1319              21 :     GDALConsumeErrors(p);
    1320              21 :     return bOK;
    1321                 : }
    1322                 : 
    1323                 : /************************************************************************/
    1324                 : /*                       GDALEmitEXIT()                                 */
    1325                 : /************************************************************************/
    1326                 : 
    1327              10 : static int GDALEmitEXIT(GDALPipe* p, InstrEnum instr = INSTR_EXIT )
    1328                 : {
    1329                 :     int bOK;
    1330              10 :     if( !GDALPipeWrite(p, instr) ||
    1331                 :         !GDALSkipUntilEndOfJunkMarker(p) ||
    1332                 :         !GDALPipeRead(p, &bOK) )
    1333               0 :         return FALSE;
    1334              10 :     return bOK;
    1335                 : }
    1336                 : 
    1337                 : /************************************************************************/
    1338                 : /*                    GDALServerSpawnAsyncFinish()                      */
    1339                 : /************************************************************************/
    1340                 : 
    1341              27 : static int GDALServerSpawnAsyncFinish(GDALServerSpawnedProcess* ssp)
    1342                 : {
    1343              27 :     if( bRecycleChild && ssp->p->bOK )
    1344                 :     {
    1345                 :         /* Store the descriptor in a free slot if available for a */
    1346                 :         /* later reuse */
    1347              21 :         CPLMutexHolderD(GDALGetphDMMutex());
    1348              24 :         for(int i = 0; i < nMaxRecycled; i ++)
    1349                 :         {
    1350              24 :             if( aspRecycled[i] == NULL )
    1351                 :             {
    1352              21 :                 if( !GDALEmitReset(ssp->p) )
    1353               0 :                     break;
    1354                 : 
    1355              21 :                 aspRecycled[i] = ssp;
    1356              21 :                 return TRUE;
    1357                 :             }
    1358               0 :         }
    1359                 :     }
    1360                 : 
    1361               6 :     if(ssp->p->bOK)
    1362                 :     {
    1363               6 :         GDALEmitEXIT(ssp->p);
    1364                 :     }
    1365                 : 
    1366               6 :     CPLDebug("GDAL", "Destroy spawned process %p", ssp);
    1367               6 :     GDALPipeFree(ssp->p);
    1368               6 :     int nRet = ssp->sp ? CPLSpawnAsyncFinish(ssp->sp, TRUE, TRUE) : 0;
    1369               6 :     CPLFree(ssp);
    1370               6 :     return nRet;
    1371                 : }
    1372                 : 
    1373                 : /************************************************************************/
    1374                 : /*                      GDALCheckServerVersion()                        */
    1375                 : /************************************************************************/
    1376                 : 
    1377               4 : static int GDALCheckServerVersion(GDALPipe* p)
    1378                 : {
    1379               4 :     GDALPipeWrite(p, INSTR_GetGDALVersion);
    1380               4 :     char bIsLSB = CPL_IS_LSB;
    1381               4 :     GDALPipeWrite_nolength(p, 1, &bIsLSB);
    1382               4 :     GDALPipeWrite(p, GDAL_RELEASE_NAME);
    1383               4 :     GDALPipeWrite(p, GDAL_VERSION_MAJOR);
    1384               4 :     GDALPipeWrite(p, GDAL_VERSION_MINOR);
    1385               4 :     GDALPipeWrite(p, GDAL_CLIENT_SERVER_PROTOCOL_MAJOR);
    1386               4 :     GDALPipeWrite(p, GDAL_CLIENT_SERVER_PROTOCOL_MINOR);
    1387               4 :     GDALPipeWrite(p, 0); /* extra bytes */
    1388                 : 
    1389               4 :     char* pszVersion = NULL;
    1390                 :     int nMajor, nMinor, nProtocolMajor, nProtocolMinor, nExtraBytes;
    1391               4 :     if( !GDALPipeRead(p, &pszVersion) ||
    1392                 :         !GDALPipeRead(p, &nMajor) ||
    1393                 :         !GDALPipeRead(p, &nMinor) ||
    1394                 :         !GDALPipeRead(p, &nProtocolMajor) ||
    1395                 :         !GDALPipeRead(p, &nProtocolMinor) ||
    1396                 :         !GDALPipeRead(p, &nExtraBytes) )
    1397                 :     {
    1398               0 :         CPLFree(pszVersion);
    1399               0 :         return FALSE;
    1400                 :     }
    1401                 : 
    1402               4 :     if( nExtraBytes > 0 )
    1403                 :     {
    1404               0 :         void* pTemp = VSIMalloc(nExtraBytes);
    1405               0 :         if( !pTemp )
    1406                 :         {
    1407               0 :             CPLFree(pszVersion);
    1408               0 :             return FALSE;
    1409                 :         }
    1410               0 :         if( !GDALPipeRead_nolength(p, nExtraBytes, pTemp) )
    1411                 :         {
    1412               0 :             CPLFree(pszVersion);
    1413               0 :             CPLFree(pTemp);
    1414               0 :             return FALSE;
    1415                 :         }
    1416               0 :         CPLFree(pTemp);
    1417                 :     }
    1418                 : 
    1419                 :     CPLDebug("GDAL",
    1420                 :              "Server version : %s (%d.%d), "
    1421                 :              "Server protocol version = %d.%d",
    1422                 :              pszVersion,
    1423                 :              nMajor, nMinor,
    1424               4 :              nProtocolMajor, nProtocolMinor);
    1425                 :     CPLDebug("GDAL",
    1426                 :              "Client version : %s (%d.%d), "
    1427                 :              "Client protocol version = %d.%d",
    1428                 :              GDAL_RELEASE_NAME, GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR,
    1429                 :              GDAL_CLIENT_SERVER_PROTOCOL_MAJOR,
    1430               4 :              GDAL_CLIENT_SERVER_PROTOCOL_MINOR);
    1431               4 :     if( nProtocolMajor != GDAL_CLIENT_SERVER_PROTOCOL_MAJOR )
    1432                 :     {
    1433                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1434                 :                  "GDAL server (GDAL version=%s, protocol version=%d.%d) is "
    1435                 :                  "incompatible with GDAL client (GDAL version=%s, protocol version=%d.%d)",
    1436                 :                  pszVersion,
    1437                 :                  nProtocolMajor, nProtocolMinor,
    1438                 :                  GDAL_RELEASE_NAME,
    1439                 :                  GDAL_CLIENT_SERVER_PROTOCOL_MAJOR,
    1440               0 :                  GDAL_CLIENT_SERVER_PROTOCOL_MINOR);
    1441               0 :         CPLFree(pszVersion);
    1442               0 :         return FALSE;
    1443                 :     }
    1444               4 :     else if( nProtocolMinor != GDAL_CLIENT_SERVER_PROTOCOL_MINOR )
    1445                 :     {
    1446               0 :         CPLDebug("GDAL", "Note: client/server protocol versions differ by minor number.");
    1447                 :     }
    1448               4 :     CPLFree(pszVersion);
    1449               4 :     return TRUE;
    1450                 : }
    1451                 : 
    1452                 : /************************************************************************/
    1453                 : /*                       GDALServerLoopForked()                         */
    1454                 : /************************************************************************/
    1455                 : 
    1456                 : #ifndef WIN32
    1457                 : void CPLReinitAllMutex();
    1458                 : 
    1459               0 : static int GDALServerLoopForked(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout)
    1460                 : {
    1461                 :     /* Do not try to close datasets at process closing */
    1462               0 :     GDALNullifyOpenDatasetsList();
    1463                 :     /* Nullify the existing mutex to avoid issues with locked mutex by */
    1464                 :     /* parent's process threads */
    1465               0 :     GDALNullifyProxyPoolSingleton();
    1466                 : #ifdef CPL_MULTIPROC_PTHREAD
    1467               0 :     CPLReinitAllMutex();
    1468                 : #endif
    1469                 : 
    1470               0 :     memset(aspRecycled, 0, sizeof(aspRecycled));
    1471                 : 
    1472               0 :     return GDALServerLoop(fin, fout);
    1473                 : }
    1474                 : #endif
    1475                 : 
    1476                 : /************************************************************************/
    1477                 : /*                      GDALServerSpawnAsync()                          */
    1478                 : /************************************************************************/
    1479                 : 
    1480              21 : static GDALServerSpawnedProcess* GDALServerSpawnAsync()
    1481                 : {
    1482              21 :     if( bRecycleChild )
    1483                 :     {
    1484                 :         /* Try to find an existing unused descriptor to reuse it */
    1485              21 :         CPLMutexHolderD(GDALGetphDMMutex());
    1486              45 :         for(int i = 0; i < nMaxRecycled; i ++)
    1487                 :         {
    1488              39 :             if( aspRecycled[i] != NULL )
    1489                 :             {
    1490              15 :                 GDALServerSpawnedProcess* ssp = aspRecycled[i];
    1491              15 :                 aspRecycled[i] = NULL;
    1492              15 :                 return ssp;
    1493                 :             }
    1494              21 :         }
    1495                 :     }
    1496                 : 
    1497                 : #ifdef WIN32
    1498                 :     const char* pszSpawnServer = CPLGetConfigOption("GDAL_API_PROXY_SERVER", "gdalserver");
    1499                 : #else
    1500               6 :     const char* pszSpawnServer = CPLGetConfigOption("GDAL_API_PROXY_SERVER", "NO");
    1501                 : #endif
    1502                 : 
    1503               6 :     const char* pszColon = strchr(pszSpawnServer, ':');
    1504               6 :     if( pszColon != NULL &&
    1505                 :         pszColon != pszSpawnServer + 1 /* do not confuse with c:/some_path/gdalserver.exe */ )
    1506                 :     {
    1507               2 :         CPLString osHost(pszSpawnServer);
    1508               2 :         osHost.resize(pszColon - pszSpawnServer);
    1509               2 :         CPL_SOCKET nConnSocket = INVALID_SOCKET;
    1510                 :         int nRet;
    1511                 : 
    1512                 : #ifdef WIN32
    1513                 :         WSADATA wsaData;
    1514                 : 
    1515                 :         nRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
    1516                 :         if (nRet != NO_ERROR)
    1517                 :         {
    1518                 :             CPLError(CE_Failure, CPLE_AppDefined,
    1519                 :                      "WSAStartup() failed with error: %d\n", nRet);
    1520                 :             return NULL;
    1521                 :         }
    1522                 : #endif
    1523                 : 
    1524                 : #ifdef HAVE_GETADDRINFO
    1525                 :         struct addrinfo sHints;
    1526               2 :         struct addrinfo* psResults = NULL, *psResultsIter;
    1527               2 :         memset(&sHints, 0, sizeof(struct addrinfo));
    1528               2 :         sHints.ai_family = AF_UNSPEC;
    1529               2 :         sHints.ai_socktype = SOCK_STREAM;
    1530               2 :         sHints.ai_flags = 0;
    1531               2 :         sHints.ai_protocol = IPPROTO_TCP;
    1532                 : 
    1533               2 :         nRet = getaddrinfo(osHost, pszColon + 1, &sHints, &psResults);
    1534               2 :         if (nRet)
    1535                 :         {
    1536                 :             CPLError(CE_Failure, CPLE_AppDefined,
    1537               0 :                      "getaddrinfo(): %s", gai_strerror(nRet));
    1538                 :             WSACleanup();
    1539               0 :             return NULL;
    1540                 :         }
    1541                 : 
    1542               4 :         for( psResultsIter = psResults;
    1543                 :              psResultsIter != NULL;
    1544                 :              psResultsIter = psResultsIter->ai_next)
    1545                 :         {
    1546                 :             nConnSocket = socket(psResultsIter->ai_family,
    1547                 :                                  psResultsIter->ai_socktype,
    1548               4 :                                  psResultsIter->ai_protocol);
    1549               4 :             if (nConnSocket == INVALID_SOCKET)
    1550               0 :                 continue;
    1551                 : 
    1552               4 :             if (connect(nConnSocket, psResultsIter->ai_addr,
    1553                 :                         psResultsIter->ai_addrlen) != SOCKET_ERROR)
    1554               2 :                 break;
    1555                 : 
    1556               2 :             closesocket(nConnSocket);
    1557                 :         }
    1558                 : 
    1559               2 :         freeaddrinfo(psResults);
    1560                 : 
    1561               2 :         if (psResultsIter == NULL)
    1562                 :         {
    1563               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Could not connect");
    1564                 :             WSACleanup();
    1565               0 :             return NULL;
    1566                 :         }
    1567                 : #else
    1568                 :         struct sockaddr_in sockAddrIn;
    1569                 :         int nPort = atoi(pszColon + 1);
    1570                 :         sockAddrIn.sin_family = AF_INET;
    1571                 :         sockAddrIn.sin_addr.s_addr = inet_addr(osHost);
    1572                 :         if (sockAddrIn.sin_addr.s_addr == INADDR_NONE)
    1573                 :         {
    1574                 :             struct hostent *hp;
    1575                 :             hp = gethostbyname(osHost);
    1576                 :             if (hp == NULL)
    1577                 :             {
    1578                 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1579                 :                          "Unknown host : %s", osHost.c_str());
    1580                 :                 WSACleanup();
    1581                 :                 return NULL;
    1582                 :             }
    1583                 :             else
    1584                 :             {
    1585                 :                 sockAddrIn.sin_family = hp->h_addrtype;
    1586                 :                 memcpy(&(sockAddrIn.sin_addr.s_addr), hp->h_addr, hp->h_length);
    1587                 :             }
    1588                 :         }
    1589                 :         sockAddrIn.sin_port = htons(nPort);
    1590                 : 
    1591                 :         nConnSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    1592                 :         if (nConnSocket == INVALID_SOCKET)
    1593                 :         {
    1594                 :             CPLError(CE_Failure, CPLE_AppDefined,
    1595                 :                      "socket() failed with error: %d", WSAGetLastError());
    1596                 :             WSACleanup();
    1597                 :             return NULL;
    1598                 :         }
    1599                 : 
    1600                 :         if (connect(nConnSocket, (const SOCKADDR *)&sockAddrIn, sizeof (sockAddrIn)) == SOCKET_ERROR )
    1601                 :         {
    1602                 :             CPLError(CE_Failure, CPLE_AppDefined,
    1603                 :                      "connect() function failed with error: %d", WSAGetLastError());
    1604                 :             closesocket(nConnSocket);
    1605                 :             WSACleanup();
    1606                 :             return NULL;
    1607                 :         }
    1608                 : #endif
    1609                 : 
    1610                 :         GDALServerSpawnedProcess* ssp =
    1611               2 :                 (GDALServerSpawnedProcess*)CPLMalloc(sizeof(GDALServerSpawnedProcess));
    1612               2 :         ssp->sp = NULL;
    1613               2 :         ssp->p = GDALPipeBuild(nConnSocket);
    1614                 : 
    1615               2 :         CPLDebug("GDAL", "Create spawned process %p", ssp);
    1616               2 :         if( !GDALCheckServerVersion(ssp->p) )
    1617                 :         {
    1618               0 :             GDALServerSpawnAsyncFinish(ssp);
    1619               0 :             return NULL;
    1620                 :         }
    1621               2 :         return ssp;
    1622                 :     }
    1623                 : 
    1624                 : #ifndef WIN32
    1625                 :     VSIStatBuf sStat;
    1626               4 :     if( VSIStat(pszSpawnServer, &sStat) == 0 && sStat.st_size == 0 )
    1627                 :     {
    1628               2 :         int nConnSocket = socket(AF_UNIX, SOCK_STREAM, 0);
    1629               2 :         if (nConnSocket >= 0)
    1630                 :         {
    1631                 :             struct sockaddr_un sockAddrUnix;
    1632               2 :             sockAddrUnix.sun_family = AF_UNIX;
    1633               2 :             CPLStrlcpy(sockAddrUnix.sun_path, pszSpawnServer, sizeof(sockAddrUnix.sun_path));
    1634                 : 
    1635               2 :             if (connect(nConnSocket, (const SOCKADDR *)&sockAddrUnix, sizeof (sockAddrUnix)) >= 0 )
    1636                 :             {
    1637                 :                 GDALServerSpawnedProcess* ssp =
    1638               2 :                     (GDALServerSpawnedProcess*)CPLMalloc(sizeof(GDALServerSpawnedProcess));
    1639               2 :                 ssp->sp = NULL;
    1640               2 :                 ssp->p = GDALPipeBuild(nConnSocket);
    1641                 : 
    1642               2 :                 CPLDebug("GDAL", "Create spawned process %p", ssp);
    1643               2 :                 if( !GDALCheckServerVersion(ssp->p) )
    1644                 :                 {
    1645               0 :                     GDALServerSpawnAsyncFinish(ssp);
    1646               0 :                     return NULL;
    1647                 :                 }
    1648               2 :                 return ssp;
    1649                 :             }
    1650                 :             else
    1651               0 :                 closesocket(nConnSocket);
    1652                 :         }
    1653                 :     }
    1654                 : #endif
    1655                 : 
    1656               2 :     if( EQUAL(pszSpawnServer, "YES") || EQUAL(pszSpawnServer, "ON") ||
    1657                 :         EQUAL(pszSpawnServer, "TRUE")  || EQUAL(pszSpawnServer, "1") )
    1658               0 :         pszSpawnServer = "gdalserver";
    1659                 : #ifdef WIN32
    1660                 :     const char* apszGDALServer[] = { pszSpawnServer, "-stdinout", NULL };
    1661                 : #else
    1662               2 :     const char* apszGDALServer[] = { pszSpawnServer, "-pipe_in", "{pipe_in}", "-pipe_out", "{pipe_out}", NULL };
    1663               2 :     if( strstr(pszSpawnServer, "gdalserver") == NULL )
    1664               2 :         apszGDALServer[1] = NULL;
    1665                 : #endif
    1666               2 :     int bCheckVersions = TRUE;
    1667                 : 
    1668                 :     CPLSpawnedProcess* sp;
    1669                 : #ifndef WIN32
    1670               4 :     if( EQUAL(pszSpawnServer, "NO") || EQUAL(pszSpawnServer, "OFF") ||
    1671                 :         EQUAL(pszSpawnServer, "FALSE")  || EQUAL(pszSpawnServer, "0") )
    1672                 :     {
    1673               2 :         sp = CPLSpawnAsync(GDALServerLoopForked, NULL, TRUE, TRUE, FALSE, NULL);
    1674               2 :         bCheckVersions = FALSE;
    1675                 :     }
    1676                 :     else
    1677                 : #endif
    1678               0 :         sp = CPLSpawnAsync(NULL, apszGDALServer, TRUE, TRUE, FALSE, NULL);
    1679                 : 
    1680               2 :     if( sp == NULL )
    1681               0 :         return NULL;
    1682                 : 
    1683                 :     GDALServerSpawnedProcess* ssp =
    1684               2 :         (GDALServerSpawnedProcess*)CPLMalloc(sizeof(GDALServerSpawnedProcess));
    1685               2 :     ssp->sp = sp;
    1686               2 :     ssp->p = GDALPipeBuild(sp);
    1687                 : 
    1688               2 :     CPLDebug("GDAL", "Create spawned process %p", ssp);
    1689               2 :     if( bCheckVersions && !GDALCheckServerVersion(ssp->p) )
    1690                 :     {
    1691               0 :         GDALServerSpawnAsyncFinish(ssp);
    1692               0 :         return NULL;
    1693                 :     }
    1694               2 :     return ssp;
    1695                 : }
    1696                 : 
    1697                 : /************************************************************************/
    1698                 : /*                        CPLErrOnlyRet()                               */
    1699                 : /************************************************************************/
    1700                 : 
    1701              95 : static CPLErr CPLErrOnlyRet(GDALPipe* p)
    1702                 : {
    1703              95 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    1704               0 :         return CE_Failure;
    1705                 : 
    1706              95 :     CPLErr eRet = CE_Failure;
    1707              95 :     if( !GDALPipeRead(p, &eRet) )
    1708               0 :         return eRet;
    1709              95 :     GDALConsumeErrors(p);
    1710              95 :     return eRet;
    1711                 : }
    1712                 : 
    1713                 : /************************************************************************/
    1714                 : /*                         RunErrorHandler()                            */
    1715                 : /************************************************************************/
    1716                 : 
    1717                 : class GDALServerErrorDesc
    1718             382 : {
    1719                 :     public:
    1720             378 :         GDALServerErrorDesc() {}
    1721                 : 
    1722                 :         CPLErr    eErr;
    1723                 :         int       nErrNo;
    1724                 :         CPLString osErrorMsg;
    1725                 : };
    1726                 : 
    1727               2 : static void CPL_STDCALL RunErrorHandler(CPLErr eErr, int nErrNo,
    1728                 :                                         const char* pszErrorMsg)
    1729                 : {
    1730               2 :     GDALServerErrorDesc oDesc;
    1731               2 :     oDesc.eErr = eErr;
    1732               2 :     oDesc.nErrNo = nErrNo;
    1733               2 :     oDesc.osErrorMsg = pszErrorMsg;
    1734                 :     std::vector<GDALServerErrorDesc>* paoErrors =
    1735               2 :         (std::vector<GDALServerErrorDesc>*) CPLGetErrorHandlerUserData();
    1736               2 :     if( paoErrors )
    1737               2 :         paoErrors->push_back(oDesc);
    1738               2 : }
    1739                 : 
    1740                 : /************************************************************************/
    1741                 : /*                        RunAsyncProgress()                            */
    1742                 : /************************************************************************/
    1743                 : 
    1744               6 : static int CPL_STDCALL RunAsyncProgress(double dfComplete,
    1745                 :                                         const char *pszMessage,
    1746                 :                                         void *pProgressArg)
    1747                 : {
    1748                 :     /* We don't send the progress right now, since some drivers like ECW */
    1749                 :     /* call the progress callback from an helper thread, while calling methods */
    1750                 :     /* on the source dataset. So we could end up sending mixed content on the pipe */
    1751                 :     /* to the client. The best is to transmit the progress in a regularly called method */
    1752                 :     /* of the dataset, such as IReadBlock() / IRasterIO() */
    1753               6 :     GDALServerAsyncProgress* asyncp = (GDALServerAsyncProgress*)pProgressArg;
    1754               6 :     CPLMutexHolderD(&(asyncp->hMutex));
    1755               6 :     asyncp->bUpdated = TRUE;
    1756               6 :     asyncp->dfComplete = dfComplete;
    1757               6 :     CPLFree(asyncp->pszProgressMsg);
    1758               6 :     asyncp->pszProgressMsg = (pszMessage) ? CPLStrdup(pszMessage) : NULL;
    1759               6 :     return asyncp->bRet;
    1760                 : }
    1761                 : 
    1762                 : /************************************************************************/
    1763                 : /*                        RunSyncProgress()                             */
    1764                 : /************************************************************************/
    1765                 : 
    1766               8 : static int CPL_STDCALL RunSyncProgress(double dfComplete,
    1767                 :                                        const char *pszMessage,
    1768                 :                                        void *pProgressArg)
    1769                 : {
    1770               8 :     GDALPipe* p = (GDALPipe*)pProgressArg;
    1771               8 :     if( !GDALPipeWrite(p, INSTR_Progress) ||
    1772                 :         !GDALPipeWrite(p, dfComplete) ||
    1773                 :         !GDALPipeWrite(p, pszMessage) )
    1774               0 :         return FALSE;
    1775               8 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    1776               0 :         return FALSE;
    1777               8 :     int bRet = FALSE;
    1778               8 :     if( !GDALPipeRead(p, &bRet) )
    1779               0 :         return FALSE;
    1780               8 :     GDALConsumeErrors(p);
    1781               8 :     return bRet;
    1782                 : }
    1783                 : 
    1784                 : /************************************************************************/
    1785                 : /*                         GDALServerLoop()                             */
    1786                 : /************************************************************************/
    1787                 : 
    1788              10 : static int GDALServerLoop(GDALPipe* p,
    1789                 :                           GDALDataset* poSrcDS,
    1790                 :                           GDALProgressFunc pfnProgress, void* pProgressData)
    1791                 : {
    1792              10 :     GDALDataset* poDS = NULL;
    1793              10 :     std::vector<GDALRasterBand*> aBands;
    1794              10 :     std::vector<GDALServerErrorDesc> aoErrors;
    1795              10 :     int nRet = 1;
    1796                 :     GDALServerAsyncProgress asyncp;
    1797              10 :     memset(&asyncp, 0, sizeof(asyncp));
    1798              10 :     asyncp.bRet = TRUE;
    1799              10 :     void* pBuffer = NULL;
    1800              10 :     int nBufferSize = 0;
    1801                 : 
    1802              10 :     const char* pszOldVal = CPLGetConfigOption("GDAL_API_PROXY", NULL);
    1803              10 :     char* pszOldValDup = (pszOldVal) ? CPLStrdup(pszOldVal) : NULL;
    1804              10 :     CPLSetThreadLocalConfigOption("GDAL_API_PROXY", "OFF");
    1805                 : 
    1806              10 :     if( poSrcDS == NULL )
    1807               7 :         CPLPushErrorHandlerEx(RunErrorHandler, &aoErrors);
    1808                 : 
    1809                 :     // fprintf(stderr, "[%d] started\n", (int)getpid());
    1810             779 :     while(TRUE)
    1811                 :     {
    1812                 :         int instr;
    1813             789 :         if( !GDALPipeRead(p, &instr) )
    1814                 :         {
    1815                 :             // fprintf(stderr, "[%d] instr failed\n", (int)getpid());
    1816               0 :             break;
    1817                 :         }
    1818                 : 
    1819                 :         // fprintf(stderr, "[%d] %s\n", (int)getpid(), (instr >= 0 && instr < INSTR_END) ? apszInstr[instr] : "unknown");
    1820                 : 
    1821             789 :         GDALRasterBand* poBand = NULL;
    1822                 : 
    1823             789 :         if( instr == INSTR_EXIT )
    1824                 :         {
    1825              10 :             if( poSrcDS == NULL && poDS != NULL )
    1826                 :             {
    1827               0 :                 GDALClose((GDALDatasetH)poDS);
    1828               0 :                 poDS = NULL;
    1829               0 :                 aBands.resize(0);
    1830                 :             }
    1831              10 :             GDALEmitEndOfJunkMarker(p);
    1832              10 :             GDALPipeWrite(p, TRUE);
    1833              10 :             nRet = 0;
    1834              10 :             break;
    1835                 :         }
    1836             779 :         else if( instr == INSTR_EXIT_FAIL )
    1837                 :         {
    1838               0 :             GDALEmitEndOfJunkMarker(p);
    1839               0 :             GDALPipeWrite(p, TRUE);
    1840               0 :             break;
    1841                 :         }
    1842             779 :         else if( instr == INSTR_GetGDALVersion ||
    1843                 :                  instr == 0x01000000 )
    1844                 :         {
    1845                 :             /* Do not change this protocol ! */
    1846                 :             char bClientIsLSB;
    1847               4 :             char* pszClientVersion = NULL;
    1848                 :             int nClientMajor, nClientMinor,
    1849                 :                 nClientProtocolMajor, nClientProtocolMinor,
    1850                 :                 nExtraBytes;
    1851               4 :             if( !GDALPipeRead_nolength(p, 1, &bClientIsLSB) )
    1852               0 :                 break;
    1853               4 :             if( bClientIsLSB != CPL_IS_LSB )
    1854                 :             {
    1855               0 :                 fprintf(stderr, "Server does not understand client endianness.\n");
    1856               0 :                 break;
    1857                 :             }
    1858                 : 
    1859               4 :             if (!GDALPipeRead(p, &pszClientVersion) ||
    1860                 :                 !GDALPipeRead(p, &nClientMajor) ||
    1861                 :                 !GDALPipeRead(p, &nClientMinor) ||
    1862                 :                 !GDALPipeRead(p, &nClientProtocolMajor) ||
    1863                 :                 !GDALPipeRead(p, &nClientProtocolMinor) ||
    1864                 :                 !GDALPipeRead(p, &nExtraBytes) )
    1865                 :             {
    1866               0 :                 CPLFree(pszClientVersion);
    1867               0 :                 break;
    1868                 :             }
    1869                 : 
    1870               4 :             if( nExtraBytes > 0 )
    1871                 :             {
    1872               0 :                 void* pTemp = VSIMalloc(nExtraBytes);
    1873               0 :                 if( !pTemp )
    1874                 :                 {
    1875               0 :                     CPLFree(pszClientVersion);
    1876               0 :                     break;
    1877                 :                 }
    1878               0 :                 if( !GDALPipeRead_nolength(p, nExtraBytes, pTemp) )
    1879                 :                 {
    1880               0 :                     CPLFree(pszClientVersion);
    1881               0 :                     CPLFree(pTemp);
    1882               0 :                     break;
    1883                 :                 }
    1884               0 :                 CPLFree(pTemp);
    1885                 :             }
    1886                 : 
    1887               4 :             GDALPipeWrite(p, GDAL_RELEASE_NAME);
    1888               4 :             GDALPipeWrite(p, GDAL_VERSION_MAJOR);
    1889               4 :             GDALPipeWrite(p, GDAL_VERSION_MINOR);
    1890               4 :             GDALPipeWrite(p, GDAL_CLIENT_SERVER_PROTOCOL_MAJOR);
    1891               4 :             GDALPipeWrite(p, GDAL_CLIENT_SERVER_PROTOCOL_MINOR);
    1892               4 :             GDALPipeWrite(p, 0); /* extra bytes */
    1893               4 :             continue;
    1894                 :         }
    1895             775 :         else if( instr == INSTR_SetConfigOption )
    1896                 :         {
    1897             254 :             char *pszKey = NULL, *pszValue = NULL;
    1898             254 :             if( !GDALPipeRead(p, &pszKey) ||
    1899                 :                 !GDALPipeRead(p, &pszValue) )
    1900               0 :                 break;
    1901             254 :             CPLSetConfigOption(pszKey, pszValue);
    1902             254 :             CPLFree(pszKey);
    1903             254 :             CPLFree(pszValue);
    1904             254 :             continue;
    1905                 :         }
    1906             521 :         else if( instr == INSTR_Progress )
    1907                 :         {
    1908                 :             double dfProgress;
    1909              18 :             char* pszProgressMsg = NULL;
    1910              18 :             if( !GDALPipeRead(p, &dfProgress) ||
    1911                 :                 !GDALPipeRead(p, &pszProgressMsg) )
    1912               0 :                 break;
    1913              18 :             int nRet = pfnProgress(dfProgress, pszProgressMsg, pProgressData);
    1914              18 :             GDALEmitEndOfJunkMarker(p);
    1915              18 :             GDALPipeWrite(p, nRet);
    1916              18 :             CPLFree(pszProgressMsg);
    1917                 :         }
    1918             503 :         else if( instr == INSTR_Reset )
    1919                 :         {
    1920              14 :             if( poSrcDS == NULL && poDS != NULL )
    1921                 :             {
    1922              12 :                 GDALClose((GDALDatasetH)poDS);
    1923              12 :                 poDS = NULL;
    1924              12 :                 MyChdirRootDirectory();
    1925              12 :                 aBands.resize(0);
    1926                 :             }
    1927              14 :             GDALEmitEndOfJunkMarker(p);
    1928              14 :             GDALPipeWrite(p, TRUE);
    1929                 :         }
    1930             489 :         else if( instr == INSTR_Open )
    1931                 :         {
    1932                 :             int nAccess;
    1933              15 :             char* pszFilename = NULL;
    1934              15 :             char* pszCWD = NULL;
    1935              15 :             if( !GDALPipeRead(p, &nAccess) ||
    1936                 :                 !GDALPipeRead(p, &pszFilename) ||
    1937                 :                 !GDALPipeRead(p, &pszCWD) )
    1938                 :             {
    1939               0 :                 CPLFree(pszFilename);
    1940               0 :                 CPLFree(pszCWD);
    1941               0 :                 break;
    1942                 :             }
    1943              15 :             if( pszCWD != NULL )
    1944                 :             {
    1945              15 :                 MyChdir(pszCWD);
    1946              15 :                 CPLFree(pszCWD);
    1947                 :             }
    1948              15 :             if( poSrcDS != NULL )
    1949               3 :                 poDS = poSrcDS;
    1950              12 :             else if( poDS == NULL && pszFilename != NULL )
    1951               8 :                 poDS = (GDALDataset*) GDALOpen(pszFilename, (GDALAccess)nAccess);
    1952              15 :             CPLFree(pszFilename);
    1953              15 :             GDALEmitEndOfJunkMarker(p);
    1954              15 :             GDALPipeWrite(p, poDS != NULL);
    1955              15 :             if( poDS != NULL )
    1956                 :             {
    1957                 :                 CPLAssert(INSTR_END < 128);
    1958                 :                 GByte abyCaps[16]; /* 16 * 8 = 128 */
    1959              15 :                 memset(abyCaps, 0, sizeof(abyCaps));
    1960                 :                 /* We implement all known instructions (except marker ones) */
    1961            1185 :                 for(int c = 1; c < INSTR_END; c++)
    1962                 :                 {
    1963            1170 :                     if( c != INSTR_Band_First && c != INSTR_Band_End )
    1964            1140 :                         abyCaps[c / 8] |= (1 << (c % 8));
    1965                 :                 }
    1966              15 :                 GDALPipeWrite(p, sizeof(abyCaps), abyCaps);
    1967              15 :                 GDALPipeWrite(p, poDS->GetDescription() );
    1968              15 :                 GDALDriver* poDriver = poDS->GetDriver();
    1969              15 :                 if( poDriver != NULL )
    1970                 :                 {
    1971              15 :                     GDALPipeWrite(p, poDriver->GetDescription() );
    1972              15 :                     char** papszItems = poDriver->GetMetadata();
    1973             165 :                     for(int i = 0; papszItems[i] != NULL; i++ )
    1974                 :                     {
    1975             150 :                         char* pszKey = NULL;
    1976             150 :                         const char* pszVal = CPLParseNameValue(papszItems[i], &pszKey );
    1977             150 :                         if( pszKey != NULL )
    1978                 :                         {
    1979             150 :                             GDALPipeWrite(p, pszKey );
    1980             150 :                             GDALPipeWrite(p, pszVal );
    1981             150 :                             CPLFree(pszKey);
    1982                 :                         }
    1983                 :                     }
    1984              15 :                     GDALPipeWrite(p, (const char*)NULL);
    1985                 :                 }
    1986                 :                 else
    1987               0 :                     GDALPipeWrite(p, (const char*)NULL);
    1988                 : 
    1989              15 :                 GDALPipeWrite(p, poDS->GetRasterXSize());
    1990              15 :                 GDALPipeWrite(p, poDS->GetRasterYSize());
    1991              15 :                 int nBands = poDS->GetRasterCount();
    1992              15 :                 GDALPipeWrite(p, nBands);
    1993                 :                 int i;
    1994              15 :                 int bAllSame = TRUE;
    1995              15 :                 GDALRasterBand* poFirstBand = NULL;
    1996              15 :                 int nFBBlockXSize = 0, nFBBlockYSize = 0;
    1997                 : 
    1998                 :                 /* Check if all bands are identical */
    1999              32 :                 for(i=0;i<nBands;i++)
    2000                 :                 {
    2001              19 :                     GDALRasterBand* poBand = poDS->GetRasterBand(i+1);
    2002              19 :                     if( strlen(poBand->GetDescription()) > 0 )
    2003                 :                     {
    2004               2 :                         bAllSame = FALSE;
    2005               2 :                         break;
    2006                 :                     }
    2007              17 :                     if( i == 0 )
    2008                 :                     {
    2009              13 :                         poFirstBand = poBand;
    2010              13 :                         poBand->GetBlockSize(&nFBBlockXSize, &nFBBlockYSize);
    2011                 :                     }
    2012                 :                     else
    2013                 :                     {
    2014                 :                         int nBlockXSize, nBlockYSize;
    2015               4 :                         poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
    2016               4 :                         if( poBand->GetXSize() != poFirstBand->GetXSize() ||
    2017                 :                             poBand->GetYSize() != poFirstBand->GetYSize() ||
    2018                 :                             poBand->GetRasterDataType() != poFirstBand->GetRasterDataType() ||
    2019                 :                             nBlockXSize != nFBBlockXSize ||
    2020                 :                             nBlockYSize != nFBBlockYSize )
    2021                 :                         {
    2022               0 :                             bAllSame = FALSE;
    2023               0 :                             break;
    2024                 :                         }
    2025                 :                     }
    2026                 :                 }
    2027                 : 
    2028                 :                 /* Transmit bands */
    2029              15 :                 GDALPipeWrite(p, bAllSame);
    2030              34 :                 for(i=0;i<nBands;i++)
    2031                 :                 {
    2032              19 :                     GDALRasterBand* poBand = poDS->GetRasterBand(i+1);
    2033              23 :                     if( i > 0 && bAllSame )
    2034               4 :                         aBands.push_back(poBand);
    2035                 :                     else
    2036              15 :                         GDALPipeWrite(p, aBands, poBand);
    2037                 :                 }
    2038                 :             }
    2039                 :         }
    2040             474 :         else if( instr == INSTR_Identify )
    2041                 :         {
    2042               2 :             char* pszFilename = NULL;
    2043               2 :             char* pszCWD = NULL;
    2044               2 :             if( !GDALPipeRead(p, &pszFilename) ||
    2045                 :                 pszFilename == NULL ||
    2046                 :                 !GDALPipeRead(p, &pszCWD) )
    2047                 :             {
    2048               0 :                 CPLFree(pszFilename);
    2049               0 :                 CPLFree(pszCWD);
    2050               0 :                 break;
    2051                 :             }
    2052                 : 
    2053               2 :             if( pszCWD != NULL )
    2054                 :             {
    2055               2 :                 MyChdir(pszCWD);
    2056               2 :                 CPLFree(pszCWD);
    2057                 :             }
    2058                 : 
    2059               2 :             int bRet = GDALIdentifyDriver(pszFilename, NULL) != NULL;
    2060               2 :             CPLFree(pszFilename);
    2061               2 :             GDALEmitEndOfJunkMarker(p);
    2062               2 :             GDALPipeWrite(p, bRet);
    2063               2 :             aoErrors.resize(0);
    2064                 :         }
    2065             472 :         else if( instr == INSTR_Create )
    2066                 :         {
    2067               2 :             char* pszFilename = NULL;
    2068               2 :             char* pszCWD = NULL;
    2069                 :             int nXSize, nYSize, nBands, nDataType;
    2070               2 :             char** papszOptions = NULL;
    2071               2 :             GDALDriver* poDriver = NULL;
    2072               2 :             if( !GDALPipeRead(p, &pszFilename) ||
    2073                 :                 pszFilename == NULL ||
    2074                 :                 !GDALPipeRead(p, &pszCWD) ||
    2075                 :                 !GDALPipeRead(p, &nXSize) ||
    2076                 :                 !GDALPipeRead(p, &nYSize) ||
    2077                 :                 !GDALPipeRead(p, &nBands) ||
    2078                 :                 !GDALPipeRead(p, &nDataType) ||
    2079                 :                 !GDALPipeRead(p, &papszOptions) )
    2080                 :             {
    2081               0 :                 CPLFree(pszFilename);
    2082               0 :                 CPLFree(pszCWD);
    2083               0 :                 break;
    2084                 :             }
    2085                 : 
    2086               2 :             if( pszCWD != NULL )
    2087                 :             {
    2088               2 :                 MyChdir(pszCWD);
    2089               2 :                 CPLFree(pszCWD);
    2090                 :             }
    2091                 : 
    2092               2 :             const char* pszDriver = CSLFetchNameValue(papszOptions, "SERVER_DRIVER");
    2093               2 :             CPLString osDriver;
    2094               2 :             if( pszDriver != NULL )
    2095                 :             {
    2096               2 :                 osDriver = pszDriver;
    2097               2 :                 pszDriver = osDriver.c_str();
    2098               2 :                 poDriver = (GDALDriver* )GDALGetDriverByName(pszDriver);
    2099                 :             }
    2100               2 :             papszOptions = CSLSetNameValue(papszOptions, "SERVER_DRIVER", NULL);
    2101               2 :             if( poDriver != NULL )
    2102                 :             {
    2103                 :                 poDS = poDriver->Create(pszFilename, nXSize, nYSize, nBands,
    2104                 :                                         (GDALDataType)nDataType,
    2105               2 :                                         papszOptions);
    2106                 :             }
    2107                 :             else
    2108                 :                 CPLError(CE_Failure, CPLE_AppDefined, "Cannot find driver %s",
    2109               0 :                          (pszDriver) ? pszDriver : "(unknown)");
    2110                 : 
    2111               2 :             GDALEmitEndOfJunkMarker(p);
    2112               2 :             GDALPipeWrite(p, poDS != NULL);
    2113               2 :             CPLFree(pszFilename);
    2114               2 :             CSLDestroy(papszOptions);
    2115                 :         }
    2116             470 :         else if( instr == INSTR_CreateCopy )
    2117                 :         {
    2118               2 :             char* pszFilename = NULL;
    2119               2 :             char* pszSrcDescription = NULL;
    2120               2 :             char* pszCWD = NULL;
    2121               2 :             char** papszCreateOptions = NULL;
    2122               2 :             GDALDriver* poDriver = NULL;
    2123               2 :             int bStrict = FALSE;
    2124                 : 
    2125               2 :             if( !GDALPipeRead(p, &pszFilename) ||
    2126                 :                 pszFilename == NULL ||
    2127                 :                 !GDALPipeRead(p, &pszSrcDescription) ||
    2128                 :                 !GDALPipeRead(p, &pszCWD) ||
    2129                 :                 !GDALPipeRead(p, &bStrict) ||
    2130                 :                 !GDALPipeRead(p, &papszCreateOptions) )
    2131                 :             {
    2132               0 :                 CPLFree(pszFilename);
    2133               0 :                 CPLFree(pszSrcDescription);
    2134               0 :                 CPLFree(pszCWD);
    2135               0 :                 break;
    2136                 :             }
    2137                 : 
    2138               2 :             CPLFree(pszSrcDescription);
    2139                 : 
    2140               2 :             if( pszCWD != NULL )
    2141                 :             {
    2142               2 :                 MyChdir(pszCWD);
    2143               2 :                 CPLFree(pszCWD);
    2144                 :             }
    2145                 : 
    2146               2 :             const char* pszDriver = CSLFetchNameValue(papszCreateOptions, "SERVER_DRIVER");
    2147               2 :             CPLString osDriver;
    2148               2 :             if( pszDriver != NULL )
    2149                 :             {
    2150               2 :                 osDriver = pszDriver;
    2151               2 :                 pszDriver = osDriver.c_str();
    2152               2 :                 poDriver = (GDALDriver* )GDALGetDriverByName(pszDriver);
    2153                 :             }
    2154               2 :             papszCreateOptions = CSLSetNameValue(papszCreateOptions, "SERVER_DRIVER", NULL);
    2155               2 :             GDALPipeWrite(p, poDriver != NULL);
    2156               2 :             if( poDriver != NULL )
    2157                 :             {
    2158               2 :                 GDALClientDataset* poSrcDS = new GDALClientDataset(p);
    2159               4 :                 if( !poSrcDS->Init(NULL, GA_ReadOnly) )
    2160                 :                 {
    2161               0 :                     delete poSrcDS;
    2162               0 :                     CPLFree(pszFilename);
    2163               0 :                     CSLDestroy(papszCreateOptions);
    2164                 :                     break;
    2165                 :                 }
    2166               2 :                 poSrcDS->AttachAsyncProgress(&asyncp);
    2167                 : 
    2168                 :                 poDS = poDriver->CreateCopy(pszFilename, poSrcDS,
    2169                 :                                             bStrict, papszCreateOptions,
    2170               2 :                                             RunAsyncProgress, &asyncp);
    2171                 : 
    2172               2 :                 int bProgressRet = poSrcDS->ProcessAsyncProgress();
    2173               2 :                 GDALClose((GDALDatasetH)poSrcDS);
    2174                 : 
    2175               2 :                 if( !bProgressRet && poDS != NULL )
    2176                 :                 {
    2177               0 :                     GDALClose((GDALDatasetH)poDS);
    2178               0 :                     poDS = NULL;
    2179                 :                 }
    2180                 : 
    2181               2 :                 if( !GDALEmitEXIT(p, (poDS != NULL) ? INSTR_EXIT : INSTR_EXIT_FAIL) )
    2182                 :                     break;
    2183                 :             }
    2184                 :             else
    2185                 :                 CPLError(CE_Failure, CPLE_AppDefined, "Cannot find driver %s",
    2186               0 :                          (pszDriver) ? pszDriver : "(unknown)");
    2187                 : 
    2188               2 :             CPLFree(pszFilename);
    2189               2 :             CSLDestroy(papszCreateOptions);
    2190                 :         }
    2191             468 :         else if( instr == INSTR_QuietDelete )
    2192                 :         {
    2193               4 :             char* pszFilename = NULL;
    2194               4 :             char* pszCWD = NULL;
    2195                 : 
    2196               4 :             if( !GDALPipeRead(p, &pszFilename) ||
    2197                 :                 pszFilename == NULL ||
    2198                 :                 !GDALPipeRead(p, &pszCWD) )
    2199                 :             {
    2200               0 :                 CPLFree(pszFilename);
    2201               0 :                 CPLFree(pszCWD);
    2202               0 :                 break;
    2203                 :             }
    2204                 : 
    2205               4 :             if( pszCWD != NULL )
    2206                 :             {
    2207               4 :                 MyChdir(pszCWD);
    2208               4 :                 CPLFree(pszCWD);
    2209                 :             }
    2210                 : 
    2211               4 :             GDALDriver::QuietDelete(pszFilename);
    2212                 : 
    2213               4 :             GDALEmitEndOfJunkMarker(p);
    2214               4 :             CPLFree(pszFilename);
    2215                 :         }
    2216             464 :         else if( instr == INSTR_AddBand )
    2217                 :         {
    2218               2 :             if( poDS == NULL )
    2219               0 :                 break;
    2220                 :             int nType;
    2221               2 :             char** papszOptions = NULL;
    2222               2 :             if( !GDALPipeRead(p, &nType) ||
    2223                 :                 !GDALPipeRead(p, &papszOptions) )
    2224               0 :                 break;
    2225               2 :             CPLErr eErr = poDS->AddBand((GDALDataType)nType, papszOptions);
    2226               2 :             GDALEmitEndOfJunkMarker(p);
    2227               2 :             GDALPipeWrite(p, eErr);
    2228               2 :             if( eErr == CE_None )
    2229                 :             {
    2230               0 :                 int nBandCount = poDS->GetRasterCount();
    2231               0 :                 GDALPipeWrite(p, aBands, poDS->GetRasterBand(nBandCount));
    2232                 :             }
    2233               2 :             CSLDestroy(papszOptions);
    2234                 :         }
    2235             462 :         else if( instr == INSTR_GetGeoTransform )
    2236                 :         {
    2237              16 :             if( poDS == NULL )
    2238               0 :                 break;
    2239                 :             double adfGeoTransform[6];
    2240              16 :             CPLErr eErr = poDS->GetGeoTransform(adfGeoTransform);
    2241              16 :             GDALEmitEndOfJunkMarker(p);
    2242              16 :             GDALPipeWrite(p, eErr);
    2243              16 :             if( eErr != CE_Failure )
    2244                 :             {
    2245              16 :                 GDALPipeWrite(p, 6 * sizeof(double), adfGeoTransform);
    2246                 :             }
    2247                 :         }
    2248             446 :         else if( instr == INSTR_SetGeoTransform )
    2249                 :         {
    2250               4 :             if( poDS == NULL )
    2251               0 :                 break;
    2252                 :             double adfGeoTransform[6];
    2253               4 :             if( !GDALPipeRead(p, 6 * sizeof(double), adfGeoTransform) )
    2254               0 :                 break;
    2255               4 :             CPLErr eErr = poDS->SetGeoTransform(adfGeoTransform);
    2256               4 :             GDALEmitEndOfJunkMarker(p);
    2257               4 :             GDALPipeWrite(p, eErr);
    2258                 :         }
    2259             442 :         else if( instr == INSTR_GetProjectionRef )
    2260                 :         {
    2261              16 :             if( poDS == NULL )
    2262               0 :                 break;
    2263              16 :             const char* pszVal = poDS->GetProjectionRef();
    2264                 :             //GDALPipeWrite(p, strlen("some_junk\xDE"), "some_junk\xDE");
    2265              16 :             GDALEmitEndOfJunkMarker(p);
    2266              16 :             GDALPipeWrite(p, pszVal);
    2267                 :         }
    2268             426 :         else if( instr == INSTR_SetProjection )
    2269                 :         {
    2270               4 :             if( poDS == NULL )
    2271               0 :                 break;
    2272               4 :             char* pszProjection = NULL;
    2273               4 :             if( !GDALPipeRead(p, &pszProjection) )
    2274               0 :                 break;
    2275               4 :             CPLErr eErr = poDS->SetProjection(pszProjection);
    2276               4 :             GDALEmitEndOfJunkMarker(p);
    2277               4 :             GDALPipeWrite(p, eErr);
    2278               4 :             CPLFree(pszProjection);
    2279                 :         }
    2280             422 :         else if( instr == INSTR_GetGCPCount )
    2281                 :         {
    2282               9 :             if( poDS == NULL )
    2283               0 :                 break;
    2284               9 :             int nGCPCount = poDS->GetGCPCount();
    2285               9 :             GDALEmitEndOfJunkMarker(p);
    2286               9 :             GDALPipeWrite(p, nGCPCount );
    2287                 :         }
    2288             413 :         else if( instr == INSTR_GetGCPProjection )
    2289                 :         {
    2290               2 :             if( poDS == NULL )
    2291               0 :                 break;
    2292               2 :             const char* pszVal = poDS->GetGCPProjection();
    2293               2 :             GDALEmitEndOfJunkMarker(p);
    2294               2 :             GDALPipeWrite(p, pszVal);
    2295                 :         }
    2296             411 :         else if( instr == INSTR_GetGCPs )
    2297                 :         {
    2298               2 :             if( poDS == NULL )
    2299               0 :                 break;
    2300               2 :             int nGCPCount = poDS->GetGCPCount();
    2301               2 :             const GDAL_GCP* pasGCPs = poDS->GetGCPs();
    2302               2 :             GDALEmitEndOfJunkMarker(p);
    2303               2 :             GDALPipeWrite(p, nGCPCount, pasGCPs);
    2304                 :         }
    2305             409 :         else if( instr == INSTR_SetGCPs )
    2306                 :         {
    2307               0 :             if( poDS == NULL )
    2308               0 :                 break;
    2309                 :             int nGCPCount;
    2310               0 :             GDAL_GCP* pasGCPs = NULL;
    2311               0 :             if( !GDALPipeRead(p, &nGCPCount, &pasGCPs) )
    2312               0 :                 break;
    2313               0 :             char* pszGCPProjection = NULL;
    2314               0 :             if( !GDALPipeRead(p, &pszGCPProjection) )
    2315               0 :                 break;
    2316               0 :             CPLErr eErr = poDS->SetGCPs(nGCPCount, pasGCPs, pszGCPProjection);
    2317               0 :             GDALDeinitGCPs(nGCPCount, pasGCPs);
    2318               0 :             CPLFree(pasGCPs);
    2319               0 :             CPLFree(pszGCPProjection);
    2320                 : 
    2321               0 :             GDALEmitEndOfJunkMarker(p);
    2322               0 :             GDALPipeWrite(p, eErr );
    2323                 : 
    2324                 :         }
    2325             409 :         else if( instr == INSTR_GetFileList )
    2326                 :         {
    2327               4 :             if( poDS == NULL )
    2328               0 :                 break;
    2329               4 :             char** papszFileList = poDS->GetFileList();
    2330               4 :             GDALEmitEndOfJunkMarker(p);
    2331               4 :             GDALPipeWrite(p, papszFileList);
    2332               4 :             CSLDestroy(papszFileList);
    2333                 :         }
    2334             405 :         else if( instr == INSTR_FlushCache )
    2335                 :         {
    2336              19 :             if( poDS )
    2337              19 :                 poDS->FlushCache();
    2338              19 :             GDALEmitEndOfJunkMarker(p);
    2339                 :         }
    2340                 :         /*else if( instr == INSTR_SetDescription )
    2341                 :         {
    2342                 :             if( poDS == NULL )
    2343                 :                 break;
    2344                 :             char* pszDescription = NULL;
    2345                 :             if( !GDALPipeRead(p, &pszDescription) )
    2346                 :                 break;
    2347                 :             poDS->SetDescription(pszDescription);
    2348                 :             CPLFree(pszDescription);
    2349                 :             GDALEmitEndOfJunkMarker(p);
    2350                 :         }*/
    2351             386 :         else if( instr == INSTR_GetMetadata )
    2352                 :         {
    2353              39 :             if( poDS == NULL )
    2354               0 :                 break;
    2355              39 :             char* pszDomain = NULL;
    2356              39 :             if( !GDALPipeRead(p, &pszDomain) )
    2357               0 :                 break;
    2358              39 :             char** papszMD = poDS->GetMetadata(pszDomain);
    2359              39 :             GDALEmitEndOfJunkMarker(p);
    2360              39 :             CPLFree(pszDomain);
    2361              39 :             GDALPipeWrite(p, papszMD);
    2362                 :         }
    2363             347 :         else if( instr == INSTR_GetMetadataItem )
    2364                 :         {
    2365              33 :             if( poDS == NULL )
    2366               0 :                 break;
    2367              33 :             char* pszName = NULL;
    2368              33 :             char* pszDomain = NULL;
    2369              33 :             if( !GDALPipeRead(p, &pszName) ||
    2370                 :                 !GDALPipeRead(p, &pszDomain) )
    2371                 :             {
    2372               0 :                 CPLFree(pszName);
    2373               0 :                 CPLFree(pszDomain);
    2374               0 :                 break;
    2375                 :             }
    2376              33 :             const char* pszVal = poDS->GetMetadataItem(pszName, pszDomain);
    2377              33 :             GDALEmitEndOfJunkMarker(p);
    2378              33 :             GDALPipeWrite(p, pszVal);
    2379              33 :             CPLFree(pszName);
    2380              33 :             CPLFree(pszDomain);
    2381                 :         }
    2382             314 :         else if( instr == INSTR_SetMetadata )
    2383                 :         {
    2384               0 :             if( poDS == NULL )
    2385               0 :                 break;
    2386               0 :             char** papszMetadata = NULL;
    2387               0 :             char* pszDomain = NULL;
    2388               0 :             if( !GDALPipeRead(p, &papszMetadata) ||
    2389                 :                 !GDALPipeRead(p, &pszDomain) )
    2390                 :             {
    2391               0 :                 CSLDestroy(papszMetadata);
    2392               0 :                 CPLFree(pszDomain);
    2393               0 :                 break;
    2394                 :             }
    2395               0 :             CPLErr eErr = poDS->SetMetadata(papszMetadata, pszDomain);
    2396               0 :             GDALEmitEndOfJunkMarker(p);
    2397               0 :             GDALPipeWrite(p, eErr);
    2398               0 :             CSLDestroy(papszMetadata);
    2399               0 :             CPLFree(pszDomain);
    2400                 :         }
    2401             314 :         else if( instr == INSTR_SetMetadataItem )
    2402                 :         {
    2403               2 :             if( poDS == NULL )
    2404               0 :                 break;
    2405               2 :             char* pszName = NULL;
    2406               2 :             char* pszValue = NULL;
    2407               2 :             char* pszDomain = NULL;
    2408               2 :             if( !GDALPipeRead(p, &pszName) ||
    2409                 :                 !GDALPipeRead(p, &pszValue) ||
    2410                 :                 !GDALPipeRead(p, &pszDomain) )
    2411                 :             {
    2412               0 :                 CPLFree(pszName);
    2413               0 :                 CPLFree(pszValue);
    2414               0 :                 CPLFree(pszDomain);
    2415               0 :                 break;
    2416                 :             }
    2417               2 :             CPLErr eErr = poDS->SetMetadataItem(pszName, pszValue, pszDomain);
    2418               2 :             GDALEmitEndOfJunkMarker(p);
    2419               2 :             GDALPipeWrite(p, eErr);
    2420               2 :             CPLFree(pszName);
    2421               2 :             CPLFree(pszValue);
    2422               2 :             CPLFree(pszDomain);
    2423                 :         }
    2424             312 :         else if( instr == INSTR_IBuildOverviews )
    2425                 :         {
    2426               2 :             if( poDS == NULL )
    2427               0 :                 break;
    2428               2 :             char* pszResampling = NULL;
    2429                 :             int nOverviews;
    2430               2 :             int* panOverviewList = NULL;
    2431                 :             int nListBands;
    2432               2 :             int* panBandList = NULL;
    2433               2 :             if( !GDALPipeRead(p, &pszResampling) ||
    2434                 :                 !GDALPipeRead(p, &nOverviews) ||
    2435                 :                 !GDALPipeRead(p, nOverviews, &panOverviewList) ||
    2436                 :                 !GDALPipeRead(p, &nListBands) ||
    2437                 :                 !GDALPipeRead(p, nListBands, &panBandList) )
    2438                 :             {
    2439               0 :                 CPLFree(pszResampling);
    2440               0 :                 CPLFree(panOverviewList);
    2441               0 :                 CPLFree(panBandList);
    2442               0 :                 break;
    2443                 :             }
    2444                 : 
    2445                 :             CPLErr eErr = poDS->BuildOverviews(pszResampling,
    2446                 :                                                nOverviews, panOverviewList,
    2447                 :                                                nListBands, panBandList,
    2448               2 :                                                RunSyncProgress, p);
    2449                 : 
    2450               2 :             CPLFree(pszResampling);
    2451               2 :             CPLFree(panOverviewList);
    2452               2 :             CPLFree(panBandList);
    2453                 : 
    2454               2 :             if( !GDALEmitEXIT(p, (eErr != CE_Failure) ? INSTR_EXIT : INSTR_EXIT_FAIL) )
    2455               0 :                 break;
    2456                 :         }
    2457             310 :         else if( instr == INSTR_AdviseRead )
    2458                 :         {
    2459               0 :             if( poDS == NULL )
    2460               0 :                 break;
    2461                 :             int nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize;
    2462                 :             int nDT;
    2463                 :             int nBandCount;
    2464               0 :             int *panBandList = NULL;
    2465               0 :             char** papszOptions = NULL;
    2466               0 :             if( !GDALPipeRead(p, &nXOff) ||
    2467                 :                 !GDALPipeRead(p, &nYOff) ||
    2468                 :                 !GDALPipeRead(p, &nXSize) ||
    2469                 :                 !GDALPipeRead(p, &nYSize) ||
    2470                 :                 !GDALPipeRead(p, &nBufXSize) ||
    2471                 :                 !GDALPipeRead(p, &nBufYSize) ||
    2472                 :                 !GDALPipeRead(p, &nDT) ||
    2473                 :                 !GDALPipeRead(p, &nBandCount) ||
    2474                 :                 !GDALPipeRead(p, nBandCount, &panBandList) ||
    2475                 :                 !GDALPipeRead(p, &papszOptions) )
    2476                 :             {
    2477               0 :                 CPLFree(panBandList);
    2478               0 :                 CSLDestroy(papszOptions);
    2479               0 :                 break;
    2480                 :             }
    2481                 : 
    2482                 :             CPLErr eErr = poDS->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
    2483                 :                                            (GDALDataType)nDT,
    2484                 :                                            nBandCount, panBandList,
    2485               0 :                                            papszOptions);
    2486               0 :             GDALEmitEndOfJunkMarker(p);
    2487               0 :             GDALPipeWrite(p, eErr);
    2488               0 :             CPLFree(panBandList);
    2489               0 :             CSLDestroy(papszOptions);
    2490                 :         }
    2491             310 :         else if( instr == INSTR_IRasterIO_Read )
    2492                 :         {
    2493               9 :             if( poDS == NULL )
    2494               0 :                 break;
    2495                 :             int nXOff, nYOff, nXSize, nYSize;
    2496                 :             int nBufXSize, nBufYSize;
    2497                 :             GDALDataType eBufType;
    2498                 :             int nBufType;
    2499                 :             int nBandCount;
    2500                 :             int nPixelSpace, nLineSpace, nBandSpace;
    2501               9 :             int* panBandMap = NULL;
    2502               9 :             if( !GDALPipeRead(p, &nXOff) ||
    2503                 :                 !GDALPipeRead(p, &nYOff) ||
    2504                 :                 !GDALPipeRead(p, &nXSize) ||
    2505                 :                 !GDALPipeRead(p, &nYSize) ||
    2506                 :                 !GDALPipeRead(p, &nBufXSize) ||
    2507                 :                 !GDALPipeRead(p, &nBufYSize) ||
    2508                 :                 !GDALPipeRead(p, &nBufType) ||
    2509                 :                 !GDALPipeRead(p, &nBandCount) ||
    2510                 :                 !GDALPipeRead(p, nBandCount, &panBandMap) ||
    2511                 :                 !GDALPipeRead(p, &nPixelSpace) ||
    2512                 :                 !GDALPipeRead(p, &nLineSpace) ||
    2513                 :                 !GDALPipeRead(p, &nBandSpace) )
    2514                 :             {
    2515               0 :                 CPLFree(panBandMap);
    2516               0 :                 break;
    2517                 :             }
    2518                 :             /* Note: only combinations of nPixelSpace, nLineSpace and
    2519                 :                nBandSpace that lead to compate band-interleaved or pixel-
    2520                 :                interleaved buffers are valid. Other combinations will lead to segfault */
    2521               9 :             eBufType = (GDALDataType)nBufType;
    2522                 :             int nSize = nBufXSize * nBufYSize * nBandCount *
    2523               9 :                 (GDALGetDataTypeSize(eBufType) / 8);
    2524               9 :             if( nSize > nBufferSize )
    2525                 :             {
    2526               3 :                 nBufferSize = nSize;
    2527               3 :                 pBuffer = CPLRealloc(pBuffer, nSize);
    2528                 :             }
    2529                 : 
    2530                 :             CPLErr eErr = poDS->RasterIO(GF_Read,
    2531                 :                                          nXOff, nYOff, nXSize, nYSize,
    2532                 :                                          pBuffer, nBufXSize, nBufYSize,
    2533                 :                                          eBufType,
    2534                 :                                          nBandCount, panBandMap,
    2535               9 :                                          nPixelSpace, nLineSpace, nBandSpace);
    2536               9 :             CPLFree(panBandMap);
    2537               9 :             GDALEmitEndOfJunkMarker(p);
    2538               9 :             GDALPipeWrite(p, eErr);
    2539               9 :             if( eErr != CE_Failure )
    2540               9 :                 GDALPipeWrite(p, nSize, pBuffer);
    2541                 :         }
    2542             301 :         else if( instr == INSTR_IRasterIO_Write )
    2543                 :         {
    2544               2 :             if( poDS == NULL )
    2545               0 :                 break;
    2546                 :             int nXOff, nYOff, nXSize, nYSize;
    2547                 :             int nBufXSize, nBufYSize;
    2548                 :             GDALDataType eBufType;
    2549                 :             int nBufType;
    2550                 :             int nBandCount;
    2551                 :             int nPixelSpace, nLineSpace, nBandSpace;
    2552               2 :             int* panBandMap = NULL;
    2553               2 :             if( !GDALPipeRead(p, &nXOff) ||
    2554                 :                 !GDALPipeRead(p, &nYOff) ||
    2555                 :                 !GDALPipeRead(p, &nXSize) ||
    2556                 :                 !GDALPipeRead(p, &nYSize) ||
    2557                 :                 !GDALPipeRead(p, &nBufXSize) ||
    2558                 :                 !GDALPipeRead(p, &nBufYSize) ||
    2559                 :                 !GDALPipeRead(p, &nBufType) ||
    2560                 :                 !GDALPipeRead(p, &nBandCount) ||
    2561                 :                 !GDALPipeRead(p, nBandCount, &panBandMap) ||
    2562                 :                 !GDALPipeRead(p, &nPixelSpace) ||
    2563                 :                 !GDALPipeRead(p, &nLineSpace) ||
    2564                 :                 !GDALPipeRead(p, &nBandSpace) )
    2565                 :             {
    2566               0 :                 CPLFree(panBandMap);
    2567               0 :                 break;
    2568                 :             }
    2569                 :             /* Note: only combinations of nPixelSpace, nLineSpace and
    2570                 :                nBandSpace that lead to compate band-interleaved or pixel-
    2571                 :                interleaved buffers are valid. Other combinations will lead to segfault */
    2572               2 :             eBufType = (GDALDataType)nBufType;
    2573                 :             int nExpectedSize = nBufXSize * nBufYSize * nBandCount *
    2574               2 :                 (GDALGetDataTypeSize(eBufType) / 8);
    2575                 :             int nSize;
    2576               2 :             if( !GDALPipeRead(p, &nSize) )
    2577               0 :                 break;
    2578               2 :             if( nSize != nExpectedSize )
    2579               0 :                 break;
    2580               2 :             if( nSize > nBufferSize )
    2581                 :             {
    2582               0 :                 nBufferSize = nSize;
    2583               0 :                 pBuffer = CPLRealloc(pBuffer, nSize);
    2584                 :             }
    2585               2 :             if( !GDALPipeRead_nolength(p, nSize, pBuffer) )
    2586               0 :                 break;
    2587                 : 
    2588                 :             CPLErr eErr = poDS->RasterIO(GF_Write,
    2589                 :                                          nXOff, nYOff, nXSize, nYSize,
    2590                 :                                          pBuffer, nBufXSize, nBufYSize,
    2591                 :                                          eBufType,
    2592                 :                                          nBandCount, panBandMap,
    2593               2 :                                          nPixelSpace, nLineSpace, nBandSpace);
    2594               2 :             CPLFree(panBandMap);
    2595               2 :             GDALEmitEndOfJunkMarker(p);
    2596               2 :             GDALPipeWrite(p, eErr);
    2597                 :         }
    2598             299 :         else if( instr == INSTR_CreateMaskBand )
    2599                 :         {
    2600               2 :             if( poDS == NULL )
    2601               0 :                 break;
    2602                 :             int nFlags;
    2603               2 :             if( !GDALPipeRead(p, &nFlags) )
    2604               0 :                 break;
    2605               2 :             CPLErr eErr = poDS->CreateMaskBand(nFlags);
    2606               2 :             GDALEmitEndOfJunkMarker(p);
    2607               2 :             GDALPipeWrite(p, eErr);
    2608                 :         }
    2609             594 :         else if( instr > INSTR_Band_First && instr < INSTR_Band_End )
    2610                 :         {
    2611                 :             int iBand;
    2612             297 :             if( !GDALPipeRead(p, &iBand) )
    2613               0 :                 break;
    2614             297 :             if( iBand < 0 || iBand >= (int)aBands.size() )
    2615               0 :                 break;
    2616             297 :             poBand = aBands[iBand];
    2617                 :         }
    2618                 :         else
    2619               0 :             break;
    2620                 : 
    2621             521 :         if( instr == INSTR_Band_FlushCache )
    2622                 :         {
    2623              27 :             CPLErr eErr = poBand->FlushCache();
    2624              27 :             GDALEmitEndOfJunkMarker(p);
    2625              27 :             GDALPipeWrite(p, eErr);
    2626                 :         }
    2627             494 :         else if( instr == INSTR_Band_GetCategoryNames )
    2628                 :         {
    2629              14 :             char** papszCategoryNames = poBand->GetCategoryNames();
    2630              14 :             GDALEmitEndOfJunkMarker(p);
    2631              14 :             GDALPipeWrite(p, papszCategoryNames);
    2632                 :         }
    2633             480 :         else if( instr == INSTR_Band_SetCategoryNames )
    2634                 :         {
    2635               2 :             char** papszCategoryNames = NULL;
    2636               2 :             if( !GDALPipeRead(p, &papszCategoryNames) )
    2637               0 :                 break;
    2638               2 :             CPLErr eErr = poBand->SetCategoryNames(papszCategoryNames);
    2639               2 :             GDALEmitEndOfJunkMarker(p);
    2640               2 :             GDALPipeWrite(p, eErr);
    2641               2 :             CSLDestroy(papszCategoryNames);
    2642                 :         }
    2643             478 :         else if( instr == INSTR_Band_SetDescription )
    2644                 :         {
    2645               2 :             char* pszDescription = NULL;
    2646               2 :             if( !GDALPipeRead(p, &pszDescription) )
    2647               0 :                 break;
    2648               2 :             poBand->SetDescription(pszDescription);
    2649               2 :             CPLFree(pszDescription);
    2650               2 :             GDALEmitEndOfJunkMarker(p);
    2651                 :         }
    2652             476 :         else if( instr == INSTR_Band_GetMetadata )
    2653                 :         {
    2654              17 :             char* pszDomain = NULL;
    2655              17 :             if( !GDALPipeRead(p, &pszDomain) )
    2656               0 :                 break;
    2657              17 :             char** papszMD = poBand->GetMetadata(pszDomain);
    2658              17 :             GDALEmitEndOfJunkMarker(p);
    2659              17 :             CPLFree(pszDomain);
    2660              17 :             GDALPipeWrite(p, papszMD);
    2661                 :         }
    2662             459 :         else if( instr == INSTR_Band_GetMetadataItem )
    2663                 :         {
    2664              18 :             char* pszName = NULL;
    2665              18 :             char* pszDomain = NULL;
    2666              18 :             if( !GDALPipeRead(p, &pszName) ||
    2667                 :                 !GDALPipeRead(p, &pszDomain) )
    2668                 :             {
    2669               0 :                 CPLFree(pszName);
    2670               0 :                 CPLFree(pszDomain);
    2671               0 :                 break;
    2672                 :             }
    2673              18 :             const char* pszVal = poBand->GetMetadataItem(pszName, pszDomain);
    2674              18 :             GDALEmitEndOfJunkMarker(p);
    2675              18 :             GDALPipeWrite(p, pszVal);
    2676              18 :             CPLFree(pszName);
    2677              18 :             CPLFree(pszDomain);
    2678                 :         }
    2679             441 :         else if( instr == INSTR_Band_SetMetadata )
    2680                 :         {
    2681               4 :             char** papszMetadata = NULL;
    2682               4 :             char* pszDomain = NULL;
    2683               4 :             if( !GDALPipeRead(p, &papszMetadata) ||
    2684                 :                 !GDALPipeRead(p, &pszDomain) )
    2685                 :             {
    2686               0 :                 CSLDestroy(papszMetadata);
    2687               0 :                 CPLFree(pszDomain);
    2688               0 :                 break;
    2689                 :             }
    2690               4 :             CPLErr eErr = poBand->SetMetadata(papszMetadata, pszDomain);
    2691               4 :             GDALEmitEndOfJunkMarker(p);
    2692               4 :             GDALPipeWrite(p, eErr);
    2693               4 :             CSLDestroy(papszMetadata);
    2694               4 :             CPLFree(pszDomain);
    2695                 :         }
    2696             437 :         else if( instr == INSTR_Band_SetMetadataItem )
    2697                 :         {
    2698               2 :             char* pszName = NULL;
    2699               2 :             char* pszValue = NULL;
    2700               2 :             char* pszDomain = NULL;
    2701               2 :             if( !GDALPipeRead(p, &pszName) ||
    2702                 :                 !GDALPipeRead(p, &pszValue) ||
    2703                 :                 !GDALPipeRead(p, &pszDomain) )
    2704                 :             {
    2705               0 :                 CPLFree(pszName);
    2706               0 :                 CPLFree(pszValue);
    2707               0 :                 CPLFree(pszDomain);
    2708               0 :                 break;
    2709                 :             }
    2710               2 :             CPLErr eErr = poBand->SetMetadataItem(pszName, pszValue, pszDomain);
    2711               2 :             GDALEmitEndOfJunkMarker(p);
    2712               2 :             GDALPipeWrite(p, eErr);
    2713               2 :             CPLFree(pszName);
    2714               2 :             CPLFree(pszValue);
    2715               2 :             CPLFree(pszDomain);
    2716                 :         }
    2717             435 :         else if( instr == INSTR_Band_GetColorInterpretation )
    2718                 :         {
    2719              12 :             GDALColorInterp eInterp = poBand->GetColorInterpretation();
    2720              12 :             GDALEmitEndOfJunkMarker(p);
    2721              12 :             GDALPipeWrite(p, eInterp);
    2722                 :         }
    2723             423 :         else if( instr == INSTR_Band_SetColorInterpretation )
    2724                 :         {
    2725                 :             int nVal;
    2726               0 :             if( !GDALPipeRead(p, &nVal ) )
    2727               0 :                 break;
    2728               0 :             CPLErr eErr = poBand->SetColorInterpretation((GDALColorInterp)nVal);
    2729               0 :             GDALEmitEndOfJunkMarker(p);
    2730               0 :             GDALPipeWrite(p, eErr);
    2731                 :         }
    2732             423 :         else if( instr == INSTR_Band_GetNoDataValue )
    2733                 :         {
    2734                 :             int bSuccess;
    2735              14 :             double dfVal = poBand->GetNoDataValue(&bSuccess);
    2736              14 :             GDALEmitEndOfJunkMarker(p);
    2737              14 :             GDALPipeWrite(p, bSuccess);
    2738              14 :             GDALPipeWrite(p, dfVal);
    2739                 :         }
    2740             409 :         else if( instr == INSTR_Band_GetMinimum )
    2741                 :         {
    2742                 :             int bSuccess;
    2743               4 :             double dfVal = poBand->GetMinimum(&bSuccess);
    2744               4 :             GDALEmitEndOfJunkMarker(p);
    2745               4 :             GDALPipeWrite(p, bSuccess);
    2746               4 :             GDALPipeWrite(p, dfVal);
    2747                 :         }
    2748             405 :         else if( instr == INSTR_Band_GetMaximum )
    2749                 :         {
    2750                 :             int bSuccess;
    2751               2 :             double dfVal = poBand->GetMaximum(&bSuccess);
    2752               2 :             GDALEmitEndOfJunkMarker(p);
    2753               2 :             GDALPipeWrite(p, bSuccess);
    2754               2 :             GDALPipeWrite(p, dfVal);
    2755                 :         }
    2756             403 :         else if( instr == INSTR_Band_GetScale )
    2757                 :         {
    2758                 :             int bSuccess;
    2759              14 :             double dfVal = poBand->GetScale(&bSuccess);
    2760              14 :             GDALEmitEndOfJunkMarker(p);
    2761              14 :             GDALPipeWrite(p, bSuccess);
    2762              14 :             GDALPipeWrite(p, dfVal);
    2763                 :         }
    2764             389 :         else if( instr == INSTR_Band_GetOffset )
    2765                 :         {
    2766                 :             int bSuccess;
    2767              14 :             double dfVal = poBand->GetOffset(&bSuccess);
    2768              14 :             GDALEmitEndOfJunkMarker(p);
    2769              14 :             GDALPipeWrite(p, bSuccess);
    2770              14 :             GDALPipeWrite(p, dfVal);
    2771                 :         }
    2772             375 :         else if( instr == INSTR_Band_SetNoDataValue )
    2773                 :         {
    2774                 :             double dfVal;
    2775               2 :             if( !GDALPipeRead(p, &dfVal ) )
    2776               0 :                 break;
    2777               2 :             CPLErr eErr = poBand->SetNoDataValue(dfVal);
    2778               2 :             GDALEmitEndOfJunkMarker(p);
    2779               2 :             GDALPipeWrite(p, eErr);
    2780                 :         }
    2781             373 :         else if( instr == INSTR_Band_SetOffset )
    2782                 :         {
    2783                 :             double dfVal;
    2784               2 :             if( !GDALPipeRead(p, &dfVal ) )
    2785               0 :                 break;
    2786               2 :             CPLErr eErr = poBand->SetOffset(dfVal);
    2787               2 :             GDALEmitEndOfJunkMarker(p);
    2788               2 :             GDALPipeWrite(p, eErr);
    2789                 :         }
    2790             371 :         else if( instr == INSTR_Band_SetScale )
    2791                 :         {
    2792                 :             double dfVal;
    2793               2 :             if( !GDALPipeRead(p, &dfVal ) )
    2794               0 :                 break;
    2795               2 :             CPLErr eErr = poBand->SetScale(dfVal);
    2796               2 :             GDALEmitEndOfJunkMarker(p);
    2797               2 :             GDALPipeWrite(p, eErr);
    2798                 :         }
    2799             369 :         else if( instr == INSTR_Band_IReadBlock )
    2800                 :         {
    2801                 :             int nBlockXOff, nBlockYOff;
    2802               0 :             if( !GDALPipeRead(p, &nBlockXOff) ||
    2803                 :                 !GDALPipeRead(p, &nBlockYOff) )
    2804               0 :                 break;
    2805                 :             int nBlockXSize, nBlockYSize;
    2806               0 :             poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
    2807                 :             int nSize = nBlockXSize * nBlockYSize *
    2808               0 :                 (GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8);
    2809               0 :             if( nSize > nBufferSize )
    2810                 :             {
    2811               0 :                 nBufferSize = nSize;
    2812               0 :                 pBuffer = CPLRealloc(pBuffer, nSize);
    2813                 :             }
    2814               0 :             CPLErr eErr = poBand->ReadBlock(nBlockXOff, nBlockYOff, pBuffer);
    2815               0 :             GDALEmitEndOfJunkMarker(p);
    2816               0 :             GDALPipeWrite(p, eErr);
    2817               0 :             GDALPipeWrite(p, nSize, pBuffer);
    2818                 :         }
    2819             369 :         else if( instr == INSTR_Band_IWriteBlock )
    2820                 :         {
    2821                 :             int nBlockXOff, nBlockYOff, nSize;
    2822               0 :             if( !GDALPipeRead(p, &nBlockXOff) ||
    2823                 :                 !GDALPipeRead(p, &nBlockYOff) ||
    2824                 :                 !GDALPipeRead(p, &nSize) )
    2825               0 :                 break;
    2826                 :             int nBlockXSize, nBlockYSize;
    2827               0 :             poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
    2828                 :             int nExpectedSize = nBlockXSize * nBlockYSize *
    2829               0 :                 (GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8);
    2830               0 :             if( nExpectedSize != nSize )
    2831               0 :                 break;
    2832               0 :             if( nSize > nBufferSize )
    2833                 :             {
    2834               0 :                 nBufferSize = nSize;
    2835               0 :                 pBuffer = CPLRealloc(pBuffer, nSize);
    2836                 :             }
    2837               0 :             if( !GDALPipeRead_nolength(p, nSize, pBuffer) )
    2838               0 :                 break;
    2839                 : 
    2840               0 :             CPLErr eErr = poBand->WriteBlock(nBlockXOff, nBlockYOff, pBuffer);
    2841               0 :             GDALEmitEndOfJunkMarker(p);
    2842               0 :             GDALPipeWrite(p, eErr);
    2843                 :         }
    2844             369 :         else if( instr == INSTR_Band_IRasterIO_Read )
    2845                 :         {
    2846                 :             int nXOff, nYOff, nXSize, nYSize;
    2847                 :             int nBufXSize, nBufYSize;
    2848                 :             GDALDataType eBufType;
    2849                 :             int nBufType;
    2850              38 :             if( !GDALPipeRead(p, &nXOff) ||
    2851                 :                 !GDALPipeRead(p, &nYOff) ||
    2852                 :                 !GDALPipeRead(p, &nXSize) ||
    2853                 :                 !GDALPipeRead(p, &nYSize) ||
    2854                 :                 !GDALPipeRead(p, &nBufXSize) ||
    2855                 :                 !GDALPipeRead(p, &nBufYSize) ||
    2856                 :                 !GDALPipeRead(p, &nBufType) )
    2857               0 :                 break;
    2858              38 :             eBufType = (GDALDataType)nBufType;
    2859                 :             int nSize = nBufXSize * nBufYSize *
    2860              38 :                 (GDALGetDataTypeSize(eBufType) / 8);
    2861              38 :             if( nSize > nBufferSize )
    2862                 :             {
    2863               8 :                 nBufferSize = nSize;
    2864               8 :                 pBuffer = CPLRealloc(pBuffer, nSize);
    2865                 :             }
    2866                 : 
    2867                 :             CPLErr eErr = poBand->RasterIO(GF_Read,
    2868                 :                                            nXOff, nYOff, nXSize, nYSize,
    2869                 :                                            pBuffer, nBufXSize, nBufYSize,
    2870              38 :                                            eBufType, 0, 0);
    2871              38 :             GDALEmitEndOfJunkMarker(p);
    2872              38 :             GDALPipeWrite(p, eErr);
    2873              38 :             GDALPipeWrite(p, nSize, pBuffer);
    2874                 :         }
    2875             331 :         else if( instr == INSTR_Band_IRasterIO_Write )
    2876                 :         {
    2877                 :             int nXOff, nYOff, nXSize, nYSize;
    2878                 :             int nBufXSize, nBufYSize;
    2879                 :             GDALDataType eBufType;
    2880                 :             int nBufType;
    2881               2 :             if( !GDALPipeRead(p, &nXOff) ||
    2882                 :                 !GDALPipeRead(p, &nYOff) ||
    2883                 :                 !GDALPipeRead(p, &nXSize) ||
    2884                 :                 !GDALPipeRead(p, &nYSize) ||
    2885                 :                 !GDALPipeRead(p, &nBufXSize) ||
    2886                 :                 !GDALPipeRead(p, &nBufYSize) ||
    2887                 :                 !GDALPipeRead(p, &nBufType) )
    2888               0 :                 break;
    2889               2 :             eBufType = (GDALDataType)nBufType;
    2890                 :             int nExpectedSize = nBufXSize * nBufYSize *
    2891               2 :                 (GDALGetDataTypeSize(eBufType) / 8);
    2892                 :             int nSize;
    2893               2 :             if( !GDALPipeRead(p, &nSize) )
    2894               0 :                 break;
    2895               2 :             if( nSize != nExpectedSize )
    2896               0 :                 break;
    2897               2 :             if( nSize > nBufferSize )
    2898                 :             {
    2899               0 :                 nBufferSize = nSize;
    2900               0 :                 pBuffer = CPLRealloc(pBuffer, nSize);
    2901                 :             }
    2902               2 :             if( !GDALPipeRead_nolength(p, nSize, pBuffer) )
    2903               0 :                 break;
    2904                 : 
    2905                 :             CPLErr eErr = poBand->RasterIO(GF_Write,
    2906                 :                                            nXOff, nYOff, nXSize, nYSize,
    2907                 :                                            pBuffer, nBufXSize, nBufYSize,
    2908               2 :                                            eBufType, 0, 0);
    2909               2 :             GDALEmitEndOfJunkMarker(p);
    2910               2 :             GDALPipeWrite(p, eErr);
    2911                 :         }
    2912             329 :         else if( instr == INSTR_Band_GetStatistics )
    2913                 :         {
    2914                 :             int bApproxOK, bForce;
    2915               8 :             if( !GDALPipeRead(p, &bApproxOK) ||
    2916                 :                 !GDALPipeRead(p, &bForce) )
    2917               0 :                 break;
    2918               8 :             double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;
    2919                 :             CPLErr eErr = poBand->GetStatistics(bApproxOK, bForce,
    2920               8 :                                                 &dfMin, &dfMax, &dfMean, &dfStdDev);
    2921               8 :             GDALEmitEndOfJunkMarker(p);
    2922               8 :             GDALPipeWrite(p, eErr);
    2923               8 :             if( eErr == CE_None )
    2924                 :             {
    2925               6 :                 GDALPipeWrite(p, dfMin);
    2926               6 :                 GDALPipeWrite(p, dfMax);
    2927               6 :                 GDALPipeWrite(p, dfMean);
    2928               6 :                 GDALPipeWrite(p, dfStdDev);
    2929                 :             }
    2930                 :         }
    2931             321 :         else if( instr == INSTR_Band_ComputeStatistics )
    2932                 :         {
    2933                 :             int bApproxOK;
    2934               2 :             if( !GDALPipeRead(p, &bApproxOK) )
    2935               0 :                 break;
    2936               2 :             double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;
    2937                 :             CPLErr eErr = poBand->ComputeStatistics(bApproxOK,
    2938                 :                                                     &dfMin, &dfMax, &dfMean, &dfStdDev,
    2939               2 :                                                     NULL, NULL);
    2940               2 :             GDALEmitEndOfJunkMarker(p);
    2941               2 :             GDALPipeWrite(p, eErr);
    2942               2 :             if( eErr != CE_Failure )
    2943                 :             {
    2944               2 :                 GDALPipeWrite(p, dfMin);
    2945               2 :                 GDALPipeWrite(p, dfMax);
    2946               2 :                 GDALPipeWrite(p, dfMean);
    2947               2 :                 GDALPipeWrite(p, dfStdDev);
    2948                 :             }
    2949                 :         }
    2950             319 :         else if( instr == INSTR_Band_SetStatistics )
    2951                 :         {
    2952                 :             double dfMin, dfMax, dfMean, dfStdDev;
    2953               2 :             if( !GDALPipeRead(p, &dfMin) ||
    2954                 :                 !GDALPipeRead(p, &dfMax) ||
    2955                 :                 !GDALPipeRead(p, &dfMean) ||
    2956                 :                 !GDALPipeRead(p, &dfStdDev) )
    2957               0 :                 break;
    2958               2 :             CPLErr eErr = poBand->SetStatistics(dfMin, dfMax, dfMean, dfStdDev);
    2959               2 :             GDALEmitEndOfJunkMarker(p);
    2960               2 :             GDALPipeWrite(p, eErr);
    2961                 :         }
    2962             317 :         else if( instr == INSTR_Band_ComputeRasterMinMax )
    2963                 :         {
    2964                 :             int bApproxOK;
    2965               0 :             if( !GDALPipeRead(p, &bApproxOK) )
    2966               0 :                 break;
    2967                 :             double adfMinMax[2];
    2968               0 :             CPLErr eErr = poBand->ComputeRasterMinMax(bApproxOK, adfMinMax);
    2969               0 :             GDALEmitEndOfJunkMarker(p);
    2970               0 :             GDALPipeWrite(p, eErr);
    2971               0 :             if( eErr != CE_Failure )
    2972                 :             {
    2973               0 :                 GDALPipeWrite(p, adfMinMax[0]);
    2974               0 :                 GDALPipeWrite(p, adfMinMax[1]);
    2975                 :             }
    2976                 :         }
    2977             317 :         else if( instr == INSTR_Band_GetHistogram )
    2978                 :         {
    2979                 :             double dfMin, dfMax;
    2980                 :             int nBuckets, bIncludeOutOfRange, bApproxOK;
    2981               2 :             if( !GDALPipeRead(p, &dfMin) ||
    2982                 :                 !GDALPipeRead(p, &dfMax) ||
    2983                 :                 !GDALPipeRead(p, &nBuckets) ||
    2984                 :                 !GDALPipeRead(p, &bIncludeOutOfRange) ||
    2985                 :                 !GDALPipeRead(p, &bApproxOK) )
    2986               0 :                 break;
    2987               2 :             int* panHistogram = (int*) VSIMalloc2(sizeof(int), nBuckets);
    2988               2 :             if( panHistogram == NULL )
    2989               0 :                 break;
    2990                 :             CPLErr eErr = poBand->GetHistogram(dfMin, dfMax, 
    2991                 :                                      nBuckets, panHistogram, 
    2992               2 :                                      bIncludeOutOfRange, bApproxOK, NULL, NULL);
    2993               2 :             GDALEmitEndOfJunkMarker(p);
    2994               2 :             GDALPipeWrite(p, eErr);
    2995               2 :             if( eErr != CE_Failure )
    2996                 :             {
    2997               2 :                 GDALPipeWrite(p, nBuckets * sizeof(int), panHistogram);
    2998                 :             }
    2999               2 :             CPLFree(panHistogram);
    3000                 :         }
    3001             315 :         else if( instr == INSTR_Band_GetDefaultHistogram )
    3002                 :         {
    3003                 :             double dfMin, dfMax;
    3004                 :             int nBuckets;
    3005                 :             int bForce;
    3006               4 :             if( !GDALPipeRead(p, &bForce) )
    3007               0 :                 break;
    3008               4 :             int* panHistogram = NULL;
    3009                 :             CPLErr eErr = poBand->GetDefaultHistogram(&dfMin, &dfMax,
    3010                 :                                                       &nBuckets, &panHistogram,
    3011               4 :                                                       bForce, NULL, NULL);
    3012               4 :             GDALEmitEndOfJunkMarker(p);
    3013               4 :             GDALPipeWrite(p, eErr);
    3014               4 :             if( eErr != CE_Failure )
    3015                 :             {
    3016               4 :                 GDALPipeWrite(p, dfMin);
    3017               4 :                 GDALPipeWrite(p, dfMax);
    3018               4 :                 GDALPipeWrite(p, nBuckets);
    3019               4 :                 GDALPipeWrite(p, nBuckets * sizeof(int) , panHistogram);
    3020                 :             }
    3021               4 :             CPLFree(panHistogram);
    3022                 :         }
    3023             311 :         else if( instr == INSTR_Band_SetDefaultHistogram )
    3024                 :         {
    3025                 :             double dfMin, dfMax;
    3026                 :             int nBuckets;
    3027               2 :             int* panHistogram = NULL;
    3028               2 :             if( !GDALPipeRead(p, &dfMin) ||
    3029                 :                 !GDALPipeRead(p, &dfMax) ||
    3030                 :                 !GDALPipeRead(p, &nBuckets) ||
    3031                 :                 !GDALPipeRead(p, nBuckets, &panHistogram) )
    3032                 :             {
    3033               0 :                 CPLFree(panHistogram);
    3034               0 :                 break;
    3035                 :             }
    3036                 :             CPLErr eErr = poBand->SetDefaultHistogram(dfMin, dfMax,
    3037               2 :                                                       nBuckets, panHistogram);
    3038               2 :             GDALEmitEndOfJunkMarker(p);
    3039               2 :             GDALPipeWrite(p, eErr);
    3040               2 :             CPLFree(panHistogram);
    3041                 :         }
    3042             309 :         else if( instr == INSTR_Band_HasArbitraryOverviews )
    3043                 :         {
    3044               2 :             int nVal = poBand->HasArbitraryOverviews();
    3045               2 :             GDALEmitEndOfJunkMarker(p);
    3046               2 :             GDALPipeWrite(p, nVal);
    3047                 :         }
    3048             307 :         else if( instr == INSTR_Band_GetOverviewCount )
    3049                 :         {
    3050               7 :             int nVal = poBand->GetOverviewCount();
    3051               7 :             GDALEmitEndOfJunkMarker(p);
    3052               7 :             GDALPipeWrite(p, nVal);
    3053                 :         }
    3054             300 :         else if( instr == INSTR_Band_GetOverview )
    3055                 :         {
    3056                 :             int iOvr;
    3057               4 :             if( !GDALPipeRead(p, &iOvr) )
    3058               0 :                 break;
    3059               4 :             GDALRasterBand* poOvrBand = poBand->GetOverview(iOvr);
    3060               4 :             GDALEmitEndOfJunkMarker(p);
    3061               4 :             GDALPipeWrite(p, aBands, poOvrBand);
    3062                 :         }
    3063             296 :         else if( instr == INSTR_Band_GetMaskBand )
    3064                 :         {
    3065               2 :             GDALRasterBand* poMaskBand = poBand->GetMaskBand();
    3066               2 :             GDALEmitEndOfJunkMarker(p);
    3067               2 :             GDALPipeWrite(p, aBands, poMaskBand);
    3068                 :         }
    3069             294 :         else if( instr == INSTR_Band_GetMaskFlags )
    3070                 :         {
    3071              19 :             int nVal = poBand->GetMaskFlags();
    3072              19 :             GDALEmitEndOfJunkMarker(p);
    3073              19 :             GDALPipeWrite(p, nVal);
    3074                 :         }
    3075             275 :         else if( instr == INSTR_Band_CreateMaskBand )
    3076                 :         {
    3077                 :             int nFlags;
    3078               0 :             if( !GDALPipeRead(p, &nFlags) )
    3079               0 :                 break;
    3080               0 :             CPLErr eErr = poBand->CreateMaskBand(nFlags);
    3081               0 :             GDALEmitEndOfJunkMarker(p);
    3082               0 :             GDALPipeWrite(p, eErr);
    3083                 :         }
    3084             275 :         else if( instr == INSTR_Band_Fill )
    3085                 :         {
    3086                 :             double dfReal, dfImag;
    3087               4 :             if( !GDALPipeRead(p, &dfReal) ||
    3088                 :                 !GDALPipeRead(p, &dfImag) )
    3089               0 :                 break;
    3090               4 :             CPLErr eErr = poBand->Fill(dfReal, dfImag);
    3091               4 :             GDALEmitEndOfJunkMarker(p);
    3092               4 :             GDALPipeWrite(p, eErr);
    3093                 :         }
    3094             271 :         else if( instr == INSTR_Band_GetColorTable )
    3095                 :         {
    3096              24 :             GDALColorTable* poColorTable = poBand->GetColorTable();
    3097              24 :             GDALEmitEndOfJunkMarker(p);
    3098              24 :             GDALPipeWrite(p, poColorTable);
    3099                 :         }
    3100             247 :         else if( instr == INSTR_Band_SetColorTable )
    3101                 :         {
    3102               2 :             GDALColorTable* poColorTable = NULL;
    3103               2 :             if( !GDALPipeRead(p, &poColorTable) )
    3104               0 :                 break;
    3105               2 :             CPLErr eErr = poBand->SetColorTable(poColorTable);
    3106               2 :             GDALEmitEndOfJunkMarker(p);
    3107               2 :             GDALPipeWrite(p, eErr);
    3108               2 :             delete poColorTable;
    3109                 :         }
    3110             245 :         else if( instr == INSTR_Band_GetUnitType )
    3111                 :         {
    3112              12 :             const char* pszVal = poBand->GetUnitType();
    3113              12 :             GDALEmitEndOfJunkMarker(p);
    3114              12 :             GDALPipeWrite(p, pszVal);
    3115                 :         }
    3116             233 :         else if( instr == INSTR_Band_SetUnitType )
    3117                 :         {
    3118               2 :             char* pszUnitType = NULL;
    3119               2 :             if( !GDALPipeRead(p, &pszUnitType) )
    3120               0 :                 break;
    3121               2 :             CPLErr eErr = poBand->SetUnitType(pszUnitType);
    3122               2 :             GDALEmitEndOfJunkMarker(p);
    3123               2 :             GDALPipeWrite(p, eErr);
    3124               2 :             CPLFree(pszUnitType);
    3125                 :         }
    3126             231 :         else if( instr == INSTR_Band_BuildOverviews )
    3127                 :         {
    3128               0 :             char* pszResampling = NULL;
    3129                 :             int nOverviews;
    3130               0 :             int* panOverviewList = NULL;
    3131               0 :             if( !GDALPipeRead(p, &pszResampling) ||
    3132                 :                 !GDALPipeRead(p, &nOverviews) ||
    3133                 :                 !GDALPipeRead(p, nOverviews, &panOverviewList) )
    3134                 :             {
    3135               0 :                 CPLFree(pszResampling);
    3136               0 :                 CPLFree(panOverviewList);
    3137               0 :                 break;
    3138                 :             }
    3139                 :             CPLErr eErr = poBand->BuildOverviews(pszResampling, nOverviews,
    3140               0 :                                                  panOverviewList, NULL, NULL);
    3141               0 :             GDALEmitEndOfJunkMarker(p);
    3142               0 :             GDALPipeWrite(p, eErr);
    3143               0 :             CPLFree(pszResampling);
    3144               0 :             CPLFree(panOverviewList);
    3145                 :         }
    3146             231 :         else if( instr == INSTR_Band_GetDefaultRAT )
    3147                 :         {
    3148               7 :             const GDALRasterAttributeTable* poRAT = poBand->GetDefaultRAT();
    3149               7 :             GDALEmitEndOfJunkMarker(p);
    3150               7 :             GDALPipeWrite(p, poRAT);
    3151                 :         }
    3152             224 :         else if( instr == INSTR_Band_SetDefaultRAT )
    3153                 :         {
    3154               0 :             GDALRasterAttributeTable* poRAT = NULL;
    3155               0 :             if( !GDALPipeRead(p, &poRAT) )
    3156               0 :                 break;
    3157               0 :             CPLErr eErr = poBand->SetDefaultRAT(poRAT);
    3158               0 :             delete poRAT;
    3159                 : 
    3160               0 :             GDALEmitEndOfJunkMarker(p);
    3161               0 :             GDALPipeWrite(p, eErr);
    3162                 :         }
    3163             224 :         else if( instr == INSTR_Band_AdviseRead )
    3164                 :         {
    3165                 :             int nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize;
    3166                 :             int nDT;
    3167               0 :             char** papszOptions = NULL;
    3168               0 :             if( !GDALPipeRead(p, &nXOff) ||
    3169                 :                 !GDALPipeRead(p, &nYOff) ||
    3170                 :                 !GDALPipeRead(p, &nXSize) ||
    3171                 :                 !GDALPipeRead(p, &nYSize) ||
    3172                 :                 !GDALPipeRead(p, &nBufXSize) ||
    3173                 :                 !GDALPipeRead(p, &nBufYSize) ||
    3174                 :                 !GDALPipeRead(p, &nDT) ||
    3175                 :                 !GDALPipeRead(p, &papszOptions) )
    3176               0 :                 break;
    3177                 :             CPLErr eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
    3178               0 :                                              (GDALDataType)nDT, papszOptions);
    3179               0 :             GDALEmitEndOfJunkMarker(p);
    3180               0 :             GDALPipeWrite(p, eErr);
    3181               0 :             CSLDestroy(papszOptions);
    3182                 :         }
    3183                 : 
    3184             521 :         if( poSrcDS == NULL )
    3185                 :         {
    3186             374 :             GDALPipeWrite(p, (int)aoErrors.size());
    3187             376 :             for(int i=0;i<(int)aoErrors.size();i++)
    3188                 :             {
    3189               2 :                 GDALPipeWrite(p, aoErrors[i].eErr);
    3190               2 :                 GDALPipeWrite(p, aoErrors[i].nErrNo);
    3191               2 :                 GDALPipeWrite(p, aoErrors[i].osErrorMsg);
    3192                 :             }
    3193             374 :             aoErrors.resize(0);
    3194                 :         }
    3195                 :         else
    3196             147 :             GDALPipeWrite(p, 0);
    3197                 :     }
    3198                 : 
    3199              10 :     if( poSrcDS == NULL )
    3200               7 :         CPLPopErrorHandler();
    3201                 : 
    3202              10 :     CPLSetThreadLocalConfigOption("GDAL_API_PROXY", pszOldValDup);
    3203              10 :     CPLFree(pszOldValDup);
    3204                 : 
    3205                 :     // fprintf(stderr, "[%d] finished = %d\n", (int)getpid(), nRet);
    3206                 : 
    3207              10 :     if( poSrcDS == NULL && poDS != NULL )
    3208               0 :         GDALClose((GDALDatasetH)poDS);
    3209                 : 
    3210              10 :     CPLFree(pBuffer);
    3211                 : 
    3212              10 :     CPLFree(asyncp.pszProgressMsg);
    3213              10 :     if( asyncp.hMutex )
    3214               2 :         CPLDestroyMutex(asyncp.hMutex);
    3215                 : 
    3216              10 :     return nRet;
    3217                 : }
    3218                 : 
    3219                 : /************************************************************************/
    3220                 : /*                         GDALServerLoop()                             */
    3221                 : /************************************************************************/
    3222                 : 
    3223               0 : int GDALServerLoop(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout)
    3224                 : {
    3225                 : #ifndef WIN32
    3226               0 :     unsetenv("CPL_SHOW_MEM_STATS");
    3227                 : #endif
    3228               0 :     CPLSetConfigOption("GDAL_API_PROXY", "NO");
    3229                 : 
    3230               0 :     GDALPipe* p = GDALPipeBuild(fin, fout);
    3231                 : 
    3232               0 :     int nRet = GDALServerLoop(p, NULL, NULL, NULL);
    3233                 : 
    3234               0 :     GDALPipeFree(p);
    3235                 : 
    3236               0 :     return nRet;
    3237                 : }
    3238                 : 
    3239                 : /************************************************************************/
    3240                 : /*                      GDALServerLoopSocket()                          */
    3241                 : /************************************************************************/
    3242                 : 
    3243               4 : int GDALServerLoopSocket(CPL_SOCKET nSocket)
    3244                 : {
    3245                 : #ifndef WIN32
    3246               4 :     unsetenv("CPL_SHOW_MEM_STATS");
    3247                 : #endif
    3248               4 :     CPLSetConfigOption("GDAL_API_PROXY", "NO");
    3249                 : 
    3250               4 :     GDALPipe* p = GDALPipeBuild(nSocket);
    3251                 : 
    3252               4 :     int nRet = GDALServerLoop(p, NULL, NULL, NULL);
    3253                 : 
    3254               4 :     GDALPipeFree(p);
    3255                 : 
    3256               4 :     return nRet;
    3257                 : }
    3258                 : 
    3259                 : /************************************************************************/
    3260                 : /*                        GDALClientDataset()                           */
    3261                 : /************************************************************************/
    3262                 : 
    3263              18 : GDALClientDataset::GDALClientDataset(GDALServerSpawnedProcess* ssp)
    3264                 : {
    3265              18 :     this->ssp = ssp;
    3266              18 :     this->p = ssp->p;
    3267              18 :     bFreeDriver = FALSE;
    3268              18 :     nGCPCount = 0;
    3269              18 :     pasGCPs = NULL;
    3270              18 :     async = NULL;
    3271              18 :     memset(abyCaps, 0, sizeof(abyCaps));
    3272              18 : }
    3273                 : 
    3274                 : /************************************************************************/
    3275                 : /*                        GDALClientDataset()                           */
    3276                 : /************************************************************************/
    3277                 : 
    3278               2 : GDALClientDataset::GDALClientDataset(GDALPipe* p)
    3279                 : {
    3280               2 :     this->ssp = NULL;
    3281               2 :     this->p = p;
    3282               2 :     bFreeDriver = FALSE;
    3283               2 :     nGCPCount = 0;
    3284               2 :     pasGCPs = NULL;
    3285               2 :     async = NULL;
    3286               2 :     memset(abyCaps, 0, sizeof(abyCaps));
    3287               2 : }
    3288                 : /************************************************************************/
    3289                 : /*                       ~GDALClientDataset()                           */
    3290                 : /************************************************************************/
    3291                 : 
    3292              20 : GDALClientDataset::~GDALClientDataset()
    3293                 : {
    3294              20 :     FlushCache();
    3295                 : 
    3296              20 :     ProcessAsyncProgress();
    3297                 : 
    3298              20 :     std::map<CPLString, char**>::iterator oIter = aoMapMetadata.begin();
    3299              41 :     for( ; oIter != aoMapMetadata.end(); ++oIter )
    3300              21 :         CSLDestroy(oIter->second);
    3301                 : 
    3302                 :     std::map< std::pair<CPLString,CPLString>, char*>::iterator oIterItem =
    3303              20 :         aoMapMetadataItem.begin();
    3304              39 :     for( ; oIterItem != aoMapMetadataItem.end(); ++oIterItem )
    3305              19 :         CPLFree(oIterItem->second);
    3306                 : 
    3307              20 :     if( nGCPCount > 0 )
    3308                 :     {
    3309               0 :         GDALDeinitGCPs(nGCPCount, pasGCPs);
    3310               0 :         CPLFree(pasGCPs);
    3311                 :     }
    3312                 : 
    3313              20 :     if( ssp != NULL )
    3314              18 :         GDALServerSpawnAsyncFinish(ssp);
    3315              20 :     if( bFreeDriver )
    3316              20 :         delete poDriver;
    3317              20 : }
    3318                 : 
    3319                 : /************************************************************************/
    3320                 : /*                       ProcessAsyncProgress()                         */
    3321                 : /************************************************************************/
    3322                 : 
    3323             402 : int GDALClientDataset::ProcessAsyncProgress()
    3324                 : {
    3325             402 :     if( !async ) return TRUE;
    3326               6 :     CPLMutexHolderD(&(async->hMutex));
    3327               6 :     if( !async->bUpdated ) return async->bRet;
    3328               4 :     async->bUpdated = FALSE;
    3329               4 :     if( !GDALPipeWrite(p, INSTR_Progress) ||
    3330                 :         !GDALPipeWrite(p, async->dfComplete) ||
    3331                 :         !GDALPipeWrite(p, async->pszProgressMsg) )
    3332               0 :         return TRUE;
    3333               4 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3334               0 :         return TRUE;
    3335                 : 
    3336               4 :     int bRet = TRUE;
    3337               4 :     if( !GDALPipeRead(p, &bRet) )
    3338               0 :         return TRUE;
    3339               4 :     async->bRet = bRet;
    3340               4 :     GDALConsumeErrors(p);
    3341               4 :     return bRet;
    3342                 : }
    3343                 :  
    3344                 : /************************************************************************/
    3345                 : /*                          IBuildOverviews()                           */
    3346                 : /************************************************************************/
    3347                 : 
    3348               3 : CPLErr GDALClientDataset::IBuildOverviews( const char *pszResampling, 
    3349                 :                                            int nOverviews, int *panOverviewList, 
    3350                 :                                            int nListBands, int *panBandList,
    3351                 :                                            GDALProgressFunc pfnProgress, 
    3352                 :                                            void * pProgressData )
    3353                 : {
    3354               3 :     if( !SupportsInstr(INSTR_IBuildOverviews) )
    3355                 :         return GDALPamDataset::IBuildOverviews(pszResampling, nOverviews, panOverviewList,
    3356                 :                                                nListBands, panBandList,
    3357               0 :                                                pfnProgress, pProgressData);
    3358                 : 
    3359                 :     CLIENT_ENTER();
    3360               3 :     if( nOverviews < 0 || nOverviews > 1000 ||
    3361                 :         nListBands < 0 || nListBands > GetRasterCount() )
    3362               0 :         return CE_Failure;
    3363                 : 
    3364               3 :     GDALPipeWriteConfigOption(p, "BIGTIFF_OVERVIEW");
    3365               3 :     GDALPipeWriteConfigOption(p, "COMPRESS_OVERVIEW");
    3366               3 :     GDALPipeWriteConfigOption(p, "PREDICTOR_OVERVIEW");
    3367               3 :     GDALPipeWriteConfigOption(p, "JPEG_QUALITY_OVERVIEW");
    3368               3 :     GDALPipeWriteConfigOption(p, "PHOTOMETRIC_OVERVIEW");
    3369               3 :     GDALPipeWriteConfigOption(p, "USE_RRD");
    3370               3 :     GDALPipeWriteConfigOption(p, "HFA_USE_RRD");
    3371               3 :     GDALPipeWriteConfigOption(p, "GDAL_TIFF_OVR_BLOCKSIZE");
    3372               3 :     GDALPipeWriteConfigOption(p, "GTIFF_DONT_WRITE_BLOCKS");
    3373                 : 
    3374               3 :     if( !GDALPipeWrite(p, INSTR_IBuildOverviews) ||
    3375                 :         !GDALPipeWrite(p, pszResampling) ||
    3376                 :         !GDALPipeWrite(p, nOverviews) ||
    3377                 :         !GDALPipeWrite(p, nOverviews * sizeof(int), panOverviewList) ||
    3378                 :         !GDALPipeWrite(p, nListBands) ||
    3379                 :         !GDALPipeWrite(p, nListBands * sizeof(int), panBandList) )
    3380               0 :         return CE_Failure;
    3381                 : 
    3382               3 :     if( GDALServerLoop(p, NULL, pfnProgress, pProgressData) != 0 )
    3383                 :     {
    3384               0 :         GDALConsumeErrors(p);
    3385               0 :         return CE_Failure;
    3386                 :     }
    3387                 : 
    3388               3 :     GDALConsumeErrors(p);
    3389                 : 
    3390               6 :     for(int i=0; i<nBands;i++)
    3391               3 :         ((GDALClientRasterBand*)papoBands[i])->ClearOverviewCache();
    3392                 : 
    3393               3 :     return CE_None;
    3394                 : }
    3395                 : 
    3396                 : /************************************************************************/
    3397                 : /*                             IRasterIO()                              */
    3398                 : /************************************************************************/
    3399                 : 
    3400              14 : CPLErr GDALClientDataset::IRasterIO( GDALRWFlag eRWFlag,
    3401                 :                                  int nXOff, int nYOff, int nXSize, int nYSize,
    3402                 :                                  void * pData, int nBufXSize, int nBufYSize,
    3403                 :                                  GDALDataType eBufType, 
    3404                 :                                  int nBandCount, int *panBandMap,
    3405                 :                                  int nPixelSpace, int nLineSpace, int nBandSpace)
    3406                 : {
    3407              14 :     if( !SupportsInstr(( eRWFlag == GF_Read ) ? INSTR_IRasterIO_Read : INSTR_IRasterIO_Write ) )
    3408                 :         return GDALPamDataset::IRasterIO( eRWFlag,
    3409                 :                                           nXOff, nYOff, nXSize, nYSize,
    3410                 :                                           pData, nBufXSize, nBufYSize,
    3411                 :                                           eBufType, 
    3412                 :                                           nBandCount, panBandMap,
    3413               0 :                                           nPixelSpace, nLineSpace, nBandSpace );
    3414                 : 
    3415                 :     CLIENT_ENTER();
    3416              14 :     CPLErr eRet = CE_Failure;
    3417                 : 
    3418              14 :     ProcessAsyncProgress();
    3419                 : 
    3420              14 :     int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
    3421                 :     int bDirectCopy;
    3422              28 :     if( nPixelSpace == nDataTypeSize &&
    3423                 :         nLineSpace == nBufXSize * nDataTypeSize &&
    3424                 :         (nBandSpace == nBufYSize * nLineSpace ||
    3425                 :             (nBandSpace == 0 && nBandCount == 1)) )
    3426                 :     {
    3427              14 :         bDirectCopy = TRUE;
    3428                 :     }
    3429               0 :     else if( nBandCount > 1 &&
    3430                 :                 nPixelSpace == nBandCount * nDataTypeSize &&
    3431                 :                 nLineSpace == nBufXSize * nPixelSpace &&
    3432                 :                 nBandSpace == nBandCount )
    3433                 :     {
    3434               0 :         bDirectCopy = TRUE;
    3435                 :     }
    3436                 :     else
    3437               0 :         bDirectCopy = FALSE;
    3438                 : 
    3439              14 :     if( eRWFlag == GF_Write )
    3440                 :     {
    3441               6 :         for(int i=0;i<nBands;i++)
    3442               3 :             ((GDALClientRasterBand*)GetRasterBand(i+1))->InvalidateCachedLines();
    3443                 :     }
    3444                 : 
    3445              14 :     if( !GDALPipeWrite(p, ( eRWFlag == GF_Read ) ? INSTR_IRasterIO_Read : INSTR_IRasterIO_Write ) ||
    3446                 :         !GDALPipeWrite(p, nXOff) ||
    3447                 :         !GDALPipeWrite(p, nYOff) ||
    3448                 :         !GDALPipeWrite(p, nXSize) ||
    3449                 :         !GDALPipeWrite(p, nYSize) ||
    3450                 :         !GDALPipeWrite(p, nBufXSize) ||
    3451                 :         !GDALPipeWrite(p, nBufYSize) ||
    3452                 :         !GDALPipeWrite(p, eBufType) ||
    3453                 :         !GDALPipeWrite(p, nBandCount) ||
    3454                 :         !GDALPipeWrite(p, nBandCount * sizeof(int), panBandMap) )
    3455               0 :         return CE_Failure;
    3456                 : 
    3457              14 :     if( bDirectCopy )
    3458                 :     {
    3459              14 :         if( !GDALPipeWrite(p, nPixelSpace) ||
    3460                 :             !GDALPipeWrite(p, nLineSpace) ||
    3461                 :             !GDALPipeWrite(p, nBandSpace) )
    3462               0 :             return CE_Failure;
    3463                 :     }
    3464                 :     else
    3465                 :     {
    3466               0 :         if( !GDALPipeWrite(p, 0) ||
    3467                 :             !GDALPipeWrite(p, 0) ||
    3468                 :             !GDALPipeWrite(p, 0) )
    3469               0 :             return CE_Failure;
    3470                 :     }
    3471                 : 
    3472              14 :     if( eRWFlag == GF_Read )
    3473                 :     {
    3474              11 :         if( !GDALSkipUntilEndOfJunkMarker(p) )
    3475               0 :             return CE_Failure;
    3476                 : 
    3477              11 :         if( !GDALPipeRead(p, &eRet) )
    3478               0 :             return eRet;
    3479              11 :         if( eRet != CE_Failure )
    3480                 :         {
    3481                 :             int nSize;
    3482              11 :             if( !GDALPipeRead(p, &nSize) )
    3483               0 :                 return CE_Failure;
    3484              11 :             GIntBig nExpectedSize = (GIntBig)nBufXSize * nBufYSize * nBandCount * nDataTypeSize;
    3485              11 :             if( nSize != nExpectedSize )
    3486               0 :                 return CE_Failure;
    3487              11 :             if( bDirectCopy )
    3488                 :             {
    3489              11 :                 if( !GDALPipeRead_nolength(p, nSize, pData) )
    3490               0 :                     return CE_Failure;
    3491                 :             }
    3492                 :             else
    3493                 :             {
    3494               0 :                 GByte* pBuf = (GByte*)VSIMalloc(nSize);
    3495               0 :                 if( pBuf == NULL )
    3496               0 :                     return CE_Failure;
    3497               0 :                 if( !GDALPipeRead_nolength(p, nSize, pBuf) )
    3498                 :                 {
    3499               0 :                     VSIFree(pBuf);
    3500               0 :                     return CE_Failure;
    3501                 :                 }
    3502               0 :                 for(int iBand=0;iBand<nBandCount;iBand++)
    3503                 :                 {
    3504               0 :                     for(int j=0;j<nBufYSize;j++)
    3505                 :                     {
    3506                 :                         GDALCopyWords( pBuf + (iBand * nBufYSize + j) * nBufXSize * nDataTypeSize,
    3507                 :                                        eBufType, nDataTypeSize,
    3508                 :                                        (GByte*)pData + iBand * nBandSpace + j * nLineSpace,
    3509                 :                                        eBufType, nPixelSpace,
    3510               0 :                                        nBufXSize);
    3511                 :                     }
    3512                 :                 }
    3513               0 :                 VSIFree(pBuf);
    3514                 :             }
    3515                 :         }
    3516                 :     }
    3517                 :     else
    3518                 :     {
    3519               3 :         GIntBig nSizeBig = (GIntBig)nBufXSize * nBufYSize * nBandCount * nDataTypeSize;
    3520               3 :         int nSize = (int)nSizeBig;
    3521               3 :         if( nSizeBig != nSize )
    3522               0 :             return CE_Failure;
    3523               3 :         if( bDirectCopy  )
    3524                 :         {
    3525               3 :             if( !GDALPipeWrite(p, nSize, pData) )
    3526               0 :                 return CE_Failure;
    3527                 :         }
    3528                 :         else
    3529                 :         {
    3530               0 :             GByte* pBuf = (GByte*)VSIMalloc(nSize);
    3531               0 :             if( pBuf == NULL )
    3532               0 :                 return CE_Failure;
    3533               0 :             for(int iBand=0;iBand<nBandCount;iBand++)
    3534                 :             {
    3535               0 :                 for(int j=0;j<nBufYSize;j++)
    3536                 :                 {
    3537                 :                     GDALCopyWords( (GByte*)pData + iBand * nBandSpace + j * nLineSpace,
    3538                 :                                    eBufType, nPixelSpace,
    3539                 :                                    pBuf + (iBand * nBufYSize + j) * nBufXSize * nDataTypeSize,
    3540                 :                                    eBufType, nDataTypeSize,
    3541               0 :                                    nBufXSize );
    3542                 :                 }
    3543                 :             }
    3544               0 :             if( !GDALPipeWrite(p, nSize, pBuf) )
    3545                 :             {
    3546               0 :                 VSIFree(pBuf);
    3547               0 :                 return CE_Failure;
    3548                 :             }
    3549               0 :             VSIFree(pBuf);
    3550                 :         }
    3551                 : 
    3552               3 :         if( !GDALSkipUntilEndOfJunkMarker(p) )
    3553               0 :             return CE_Failure;
    3554               3 :         if( !GDALPipeRead(p, &eRet) )
    3555               0 :             return eRet;
    3556                 :     }
    3557                 : 
    3558              14 :     GDALConsumeErrors(p);
    3559              14 :     return eRet;
    3560                 : }
    3561                 : 
    3562                 : /************************************************************************/
    3563                 : /*                          GetGeoTransform()                           */
    3564                 : /************************************************************************/
    3565                 : 
    3566              19 : CPLErr GDALClientDataset::GetGeoTransform( double * padfTransform )
    3567                 : {
    3568              19 :     if( !SupportsInstr(INSTR_GetGeoTransform) )
    3569               0 :         return GDALPamDataset::GetGeoTransform(padfTransform);
    3570                 : 
    3571                 :     CLIENT_ENTER();
    3572              19 :     if( !GDALPipeWrite(p, INSTR_GetGeoTransform) )
    3573               0 :         return CE_Failure;
    3574              19 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3575               0 :         return CE_Failure;
    3576                 : 
    3577              19 :     CPLErr eRet = CE_Failure;
    3578              19 :     if( !GDALPipeRead(p, &eRet) )
    3579               0 :         return eRet;
    3580              19 :     if( eRet != CE_Failure )
    3581                 :     {
    3582              19 :         if( !GDALPipeRead(p, 6 * sizeof(double), padfTransform) )
    3583               0 :             return CE_Failure;
    3584                 :     }
    3585              19 :     GDALConsumeErrors(p);
    3586              19 :     return eRet;
    3587                 : }
    3588                 : 
    3589                 : /************************************************************************/
    3590                 : /*                          SetGeoTransform()                           */
    3591                 : /************************************************************************/
    3592                 : 
    3593               6 : CPLErr GDALClientDataset::SetGeoTransform( double * padfTransform )
    3594                 : {
    3595               6 :     if( !SupportsInstr(INSTR_SetGeoTransform) )
    3596               0 :         return GDALPamDataset::SetGeoTransform(padfTransform);
    3597                 : 
    3598                 :     CLIENT_ENTER();
    3599               6 :     if( !GDALPipeWrite(p, INSTR_SetGeoTransform) ||
    3600                 :         !GDALPipeWrite(p, 6 * sizeof(double), padfTransform) )
    3601               0 :         return CE_Failure;
    3602               6 :     return CPLErrOnlyRet(p);
    3603                 : }
    3604                 : 
    3605                 : /************************************************************************/
    3606                 : /*                          GetProjectionRef()                          */
    3607                 : /************************************************************************/
    3608                 : 
    3609              19 : const char* GDALClientDataset::GetProjectionRef()
    3610                 : {
    3611              19 :     if( !SupportsInstr(INSTR_GetProjectionRef) )
    3612               0 :         return GDALPamDataset::GetProjectionRef();
    3613                 : 
    3614                 :     CLIENT_ENTER();
    3615              19 :     if( !GDALPipeWrite(p, INSTR_GetProjectionRef) )
    3616               0 :         return osProjection;
    3617              19 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3618               0 :         return osProjection;
    3619                 : 
    3620              19 :     char* pszStr = NULL;
    3621              19 :     if( !GDALPipeRead(p, &pszStr) )
    3622               0 :         return osProjection;
    3623              19 :     GDALConsumeErrors(p);
    3624              19 :     if( pszStr == NULL )
    3625               0 :         return NULL;
    3626              19 :     osProjection = pszStr;
    3627              19 :     CPLFree(pszStr);
    3628              19 :     return osProjection;
    3629                 : }
    3630                 : 
    3631                 : /************************************************************************/
    3632                 : /*                           SetProjection()                            */
    3633                 : /************************************************************************/
    3634                 : 
    3635               6 : CPLErr GDALClientDataset::SetProjection(const char* pszProjection)
    3636                 : {
    3637               6 :     if( !SupportsInstr(INSTR_SetProjection) )
    3638               0 :         return GDALPamDataset::SetProjection(pszProjection);
    3639                 : 
    3640                 :     CLIENT_ENTER();
    3641               6 :     if( !GDALPipeWrite(p, INSTR_SetProjection) ||
    3642                 :         !GDALPipeWrite(p, pszProjection))
    3643               0 :         return CE_Failure;
    3644               6 :     return CPLErrOnlyRet(p);
    3645                 : }
    3646                 : 
    3647                 : /************************************************************************/
    3648                 : /*                            GetGCPCount()                             */
    3649                 : /************************************************************************/
    3650                 : 
    3651              11 : int GDALClientDataset::GetGCPCount()
    3652                 : {
    3653              11 :     if( !SupportsInstr(INSTR_GetGCPCount) )
    3654               0 :         return GDALPamDataset::GetGCPCount();
    3655                 : 
    3656                 :     CLIENT_ENTER();
    3657              11 :     if( !GDALPipeWrite(p, INSTR_GetGCPCount) )
    3658               0 :         return 0;
    3659              11 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3660               0 :         return 0;
    3661                 : 
    3662                 :     int nGCPCount;
    3663              11 :     if( !GDALPipeRead(p, &nGCPCount) )
    3664               0 :         return 0;
    3665              11 :     GDALConsumeErrors(p);
    3666              11 :     return nGCPCount;
    3667                 : }
    3668                 : 
    3669                 : /************************************************************************/
    3670                 : /*                          GetGCPProjection()                          */
    3671                 : /************************************************************************/
    3672                 : 
    3673               3 : const char * GDALClientDataset::GetGCPProjection()
    3674                 : {
    3675               3 :     if( !SupportsInstr(INSTR_GetGCPProjection) )
    3676               0 :         return GDALPamDataset::GetGCPProjection();
    3677                 : 
    3678                 :     CLIENT_ENTER();
    3679               3 :     if( !GDALPipeWrite(p, INSTR_GetGCPProjection) )
    3680               0 :         return osGCPProjection;
    3681               3 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3682               0 :         return osGCPProjection;
    3683                 : 
    3684               3 :     char* pszStr = NULL;
    3685               3 :     if( !GDALPipeRead(p, &pszStr) )
    3686               0 :         return osGCPProjection;
    3687               3 :     GDALConsumeErrors(p);
    3688               3 :     if( pszStr == NULL )
    3689               0 :         return NULL;
    3690               3 :     osGCPProjection = pszStr;
    3691               3 :     CPLFree(pszStr);
    3692               3 :     return osGCPProjection;
    3693                 : }
    3694                 : 
    3695                 : /************************************************************************/
    3696                 : /*                               GetGCPs()                              */
    3697                 : /************************************************************************/
    3698                 : 
    3699               3 : const GDAL_GCP * GDALClientDataset::GetGCPs()
    3700                 : {
    3701               3 :     if( !SupportsInstr(INSTR_GetGCPs) )
    3702               0 :         return GDALPamDataset::GetGCPs();
    3703                 : 
    3704                 :     CLIENT_ENTER();
    3705               3 :     if( !GDALPipeWrite(p, INSTR_GetGCPs) )
    3706               0 :         return NULL;
    3707               3 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3708               0 :         return NULL;
    3709                 : 
    3710               3 :     if( nGCPCount > 0 )
    3711                 :     {
    3712               0 :         GDALDeinitGCPs(nGCPCount, pasGCPs);
    3713               0 :         CPLFree(pasGCPs);
    3714               0 :         pasGCPs = NULL;
    3715                 :     }
    3716               3 :     nGCPCount = 0;
    3717                 : 
    3718               3 :     if( !GDALPipeRead(p, &nGCPCount, &pasGCPs) )
    3719               0 :         return NULL;
    3720                 : 
    3721               3 :     GDALConsumeErrors(p);
    3722               3 :     return pasGCPs;
    3723                 : }
    3724                 : 
    3725                 : /************************************************************************/
    3726                 : /*                               SetGCPs()                              */
    3727                 : /************************************************************************/
    3728                 : 
    3729               0 : CPLErr GDALClientDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
    3730                 :                                    const char *pszGCPProjection ) 
    3731                 : {
    3732               0 :     if( !SupportsInstr(INSTR_SetGCPs) )
    3733               0 :         return GDALPamDataset::SetGCPs(nGCPCount, pasGCPList, pszGCPProjection);
    3734                 : 
    3735                 :     CLIENT_ENTER();
    3736               0 :     if( !GDALPipeWrite(p, INSTR_SetGCPs) ||
    3737                 :         !GDALPipeWrite(p, nGCPCount, pasGCPList) ||
    3738                 :         !GDALPipeWrite(p, pszGCPProjection) )
    3739               0 :         return CE_Failure;
    3740               0 :     return CPLErrOnlyRet(p);
    3741                 : }
    3742                 : 
    3743                 : /************************************************************************/
    3744                 : /*                            GetFileList()                             */
    3745                 : /************************************************************************/
    3746                 : 
    3747               6 : char** GDALClientDataset::GetFileList()
    3748                 : {
    3749               6 :     if( !SupportsInstr(INSTR_GetFileList) )
    3750               0 :         return GDALPamDataset::GetFileList();
    3751                 : 
    3752                 :     CLIENT_ENTER();
    3753               6 :     if( !GDALPipeWrite(p, INSTR_GetFileList) )
    3754               0 :         return NULL;
    3755               6 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3756               0 :         return NULL;
    3757                 : 
    3758               6 :     char** papszFileList = NULL;
    3759               6 :     if( !GDALPipeRead(p, &papszFileList) )
    3760               0 :         return NULL;
    3761               6 :     GDALConsumeErrors(p);
    3762                 : 
    3763                 :     /* If server is Windows and client is Unix, then replace backslahes */
    3764                 :     /* by slashes */
    3765                 : #ifndef WIN32
    3766               6 :     char** papszIter = papszFileList;
    3767              24 :     while( papszIter != NULL && *papszIter != NULL )
    3768                 :     {
    3769              12 :         char* pszIter = *papszIter;
    3770                 :         char* pszBackSlash;
    3771              24 :         while( (pszBackSlash = strchr(pszIter, '\\')) != NULL )
    3772                 :         {
    3773               0 :             *pszBackSlash = '/';
    3774               0 :             pszIter = pszBackSlash + 1;
    3775                 :         }
    3776              12 :         papszIter ++;
    3777                 :     }
    3778                 : #endif
    3779                 : 
    3780               6 :     return papszFileList;
    3781                 : }
    3782                 : 
    3783                 : /************************************************************************/
    3784                 : /*                            GetMetadata()                             */
    3785                 : /************************************************************************/
    3786                 : 
    3787              41 : char** GDALClientDataset::GetMetadata( const char * pszDomain )
    3788                 : {
    3789              41 :     if( !SupportsInstr(INSTR_GetMetadata) )
    3790               0 :         return GDALPamDataset::GetMetadata(pszDomain);
    3791                 : 
    3792                 :     CLIENT_ENTER();
    3793              41 :     if( pszDomain == NULL )
    3794               0 :         pszDomain = "";
    3795              41 :     std::map<CPLString, char**>::iterator oIter = aoMapMetadata.find(CPLString(pszDomain));
    3796              41 :     if( oIter != aoMapMetadata.end() )
    3797                 :     {
    3798              20 :         CSLDestroy(oIter->second);
    3799              20 :         aoMapMetadata.erase(oIter);
    3800                 :     }
    3801              41 :     if( !GDALPipeWrite(p, INSTR_GetMetadata) ||
    3802                 :         !GDALPipeWrite(p, pszDomain) )
    3803               0 :         return NULL;
    3804              41 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3805               0 :         return NULL;
    3806                 : 
    3807              41 :     char** papszMD = NULL;
    3808              41 :     if( !GDALPipeRead(p, &papszMD) )
    3809               0 :         return NULL;
    3810              41 :     aoMapMetadata[pszDomain] = papszMD;
    3811              41 :     GDALConsumeErrors(p);
    3812              41 :     return papszMD;
    3813                 : }
    3814                 : 
    3815                 : /************************************************************************/
    3816                 : /*                        SetDescription()                              */
    3817                 : /************************************************************************/
    3818                 : 
    3819                 : /*void GDALClientDataset::SetDescription( const char * pszDescription )
    3820                 : {
    3821                 :     sDescription = pszDescription;
    3822                 :     if( !GDALPipeWrite(p, INSTR_SetDescription) ||
    3823                 :         !GDALPipeWrite(p, pszDescription) ||
    3824                 :         !GDALSkipUntilEndOfJunkMarker(p))
    3825                 :         return;
    3826                 :     GDALConsumeErrors(p);
    3827                 : }*/
    3828                 : 
    3829                 : /************************************************************************/
    3830                 : /*                        GetMetadataItem()                             */
    3831                 : /************************************************************************/
    3832                 : 
    3833              37 : const char* GDALClientDataset::GetMetadataItem( const char * pszName,
    3834                 :                                                 const char * pszDomain )
    3835                 : {
    3836              37 :     if( !SupportsInstr(INSTR_GetMetadataItem) )
    3837               0 :         return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
    3838                 : 
    3839                 :     CLIENT_ENTER();
    3840              37 :     if( pszDomain == NULL )
    3841               0 :         pszDomain = "";
    3842                 :     std::pair<CPLString,CPLString> oPair =
    3843              37 :         std::pair<CPLString,CPLString> (CPLString(pszDomain), CPLString(pszName));
    3844                 :     std::map< std::pair<CPLString,CPLString>, char*>::iterator oIter =
    3845              37 :         aoMapMetadataItem.find(oPair);
    3846              37 :     if( oIter != aoMapMetadataItem.end() )
    3847                 :     {
    3848              18 :         CPLFree(oIter->second);
    3849              18 :         aoMapMetadataItem.erase(oIter);
    3850                 :     }
    3851              37 :     if( !GDALPipeWrite(p, INSTR_GetMetadataItem) ||
    3852                 :         !GDALPipeWrite(p, pszName) ||
    3853                 :         !GDALPipeWrite(p, pszDomain) )
    3854               0 :         return NULL;
    3855              37 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3856               0 :         return NULL;
    3857                 : 
    3858              37 :     char* pszItem = NULL;
    3859              37 :     if( !GDALPipeRead(p, &pszItem) )
    3860               0 :         return NULL;
    3861              37 :     aoMapMetadataItem[oPair] = pszItem;
    3862              37 :     GDALConsumeErrors(p);
    3863              37 :     return pszItem;
    3864                 : }
    3865                 : 
    3866                 : /************************************************************************/
    3867                 : /*                            GetMetadata()                             */
    3868                 : /************************************************************************/
    3869                 : 
    3870               0 : CPLErr GDALClientDataset::SetMetadata( char ** papszMetadata,
    3871                 :                                        const char * pszDomain )
    3872                 : {
    3873               0 :     if( !SupportsInstr(INSTR_SetMetadata) )
    3874               0 :         return GDALPamDataset::SetMetadata(papszMetadata, pszDomain);
    3875                 : 
    3876                 :     CLIENT_ENTER();
    3877               0 :     if( !GDALPipeWrite(p, INSTR_SetMetadata) ||
    3878                 :         !GDALPipeWrite(p, papszMetadata) ||
    3879                 :         !GDALPipeWrite(p, pszDomain) )
    3880               0 :         return CE_Failure;
    3881               0 :     return CPLErrOnlyRet(p);
    3882                 : }
    3883                 : 
    3884                 : /************************************************************************/
    3885                 : /*                        SetMetadataItem()                             */
    3886                 : /************************************************************************/
    3887                 : 
    3888               3 : CPLErr GDALClientDataset::SetMetadataItem( const char * pszName,
    3889                 :                                            const char * pszValue,
    3890                 :                                            const char * pszDomain )
    3891                 : {
    3892               3 :     if( !SupportsInstr(INSTR_SetMetadataItem) )
    3893               0 :         return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
    3894                 : 
    3895                 :     CLIENT_ENTER();
    3896               3 :     if( !GDALPipeWrite(p, INSTR_SetMetadataItem) ||
    3897                 :         !GDALPipeWrite(p, pszName) ||
    3898                 :         !GDALPipeWrite(p, pszValue) ||
    3899                 :         !GDALPipeWrite(p, pszDomain) )
    3900               0 :         return CE_Failure;
    3901               3 :     return CPLErrOnlyRet(p);
    3902                 : }
    3903                 : 
    3904                 : /************************************************************************/
    3905                 : /*                             FlushCache()                             */
    3906                 : /************************************************************************/
    3907                 : 
    3908              26 : void GDALClientDataset::FlushCache()
    3909                 : {
    3910              26 :     if( !SupportsInstr(INSTR_FlushCache) )
    3911                 :     {
    3912               0 :         GDALPamDataset::FlushCache();
    3913               0 :         return;
    3914                 :     }
    3915                 : 
    3916              58 :     for(int i=0;i<nBands;i++)
    3917              32 :         ((GDALClientRasterBand*)GetRasterBand(i+1))->InvalidateCachedLines();
    3918                 : 
    3919                 :     CLIENT_ENTER();
    3920              26 :     SetPamFlags(0);
    3921              26 :     GDALPamDataset::FlushCache();
    3922              26 :     if( !GDALPipeWrite(p, INSTR_FlushCache) ||
    3923                 :         !GDALSkipUntilEndOfJunkMarker(p) )
    3924               0 :         return;
    3925              26 :     GDALConsumeErrors(p);
    3926                 : }
    3927                 : 
    3928                 : /************************************************************************/
    3929                 : /*                              AddBand()                               */
    3930                 : /************************************************************************/
    3931                 : 
    3932               3 : CPLErr GDALClientDataset::AddBand( GDALDataType eType, 
    3933                 :                                    char **papszOptions )
    3934                 : {
    3935               3 :     if( !SupportsInstr(INSTR_AddBand) )
    3936               0 :         return GDALPamDataset::AddBand(eType, papszOptions);
    3937                 : 
    3938                 :     CLIENT_ENTER();
    3939               3 :     if( !GDALPipeWrite(p, INSTR_AddBand) ||
    3940                 :         !GDALPipeWrite(p, eType) ||
    3941                 :         !GDALPipeWrite(p, papszOptions) )
    3942               0 :         return CE_Failure;
    3943               3 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    3944               0 :         return CE_Failure;
    3945               3 :     CPLErr eRet = CE_Failure;
    3946               3 :     if( !GDALPipeRead(p, &eRet) )
    3947               0 :         return eRet;
    3948               3 :     if( eRet == CE_None )
    3949                 :     {
    3950               0 :         GDALRasterBand* poBand = NULL;
    3951               0 :         if( !GDALPipeRead(p, this, &poBand, abyCaps) )
    3952               0 :             return CE_Failure;
    3953               0 :         SetBand(GetRasterCount() + 1, poBand);
    3954                 :     }
    3955               3 :     GDALConsumeErrors(p);
    3956               3 :     return eRet;    
    3957                 : }
    3958                 : 
    3959                 : 
    3960                 : /************************************************************************/
    3961                 : /*                             AdviseRead()                             */
    3962                 : /************************************************************************/
    3963                 : 
    3964               0 : CPLErr GDALClientDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
    3965                 :                                   int nBufXSize, int nBufYSize, 
    3966                 :                                   GDALDataType eDT, 
    3967                 :                                   int nBandCount, int *panBandList,
    3968                 :                                   char **papszOptions )
    3969                 : {
    3970               0 :     if( !SupportsInstr(INSTR_AdviseRead) )
    3971                 :         return GDALPamDataset::AdviseRead(nXOff, nYOff, nXSize, nYSize,
    3972                 :                                           nBufXSize, nBufYSize, eDT, nBandCount, panBandList,
    3973               0 :                                           papszOptions);
    3974                 : 
    3975                 :     CLIENT_ENTER();
    3976               0 :     if( !GDALPipeWrite(p, INSTR_AdviseRead) ||
    3977                 :         !GDALPipeWrite(p, nXOff) ||
    3978                 :         !GDALPipeWrite(p, nYOff) ||
    3979                 :         !GDALPipeWrite(p, nXSize) ||
    3980                 :         !GDALPipeWrite(p, nYSize) ||
    3981                 :         !GDALPipeWrite(p, nBufXSize) ||
    3982                 :         !GDALPipeWrite(p, nBufYSize) ||
    3983                 :         !GDALPipeWrite(p, eDT) ||
    3984                 :         !GDALPipeWrite(p, nBandCount) ||
    3985                 :         !GDALPipeWrite(p, nBandCount * sizeof(int), panBandList) ||
    3986                 :         !GDALPipeWrite(p, papszOptions) )
    3987               0 :         return CE_Failure;
    3988               0 :     return CPLErrOnlyRet(p);
    3989                 : }
    3990                 : 
    3991                 : /************************************************************************/
    3992                 : /*                           CreateMaskBand()                           */
    3993                 : /************************************************************************/
    3994                 : 
    3995               3 : CPLErr GDALClientDataset::CreateMaskBand( int nFlags )
    3996                 : {
    3997               3 :     if( !SupportsInstr(INSTR_CreateMaskBand) )
    3998               0 :         return GDALPamDataset::CreateMaskBand(nFlags);
    3999                 : 
    4000                 :     CLIENT_ENTER();
    4001               3 :     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK_TO_8BIT", bRecycleChild);
    4002               3 :     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK", bRecycleChild);
    4003               3 :     if( !GDALPipeWrite(p, INSTR_CreateMaskBand) ||
    4004                 :         !GDALPipeWrite(p, nFlags) )
    4005               0 :         return CE_Failure;
    4006               3 :     return CPLErrOnlyRet(p);
    4007                 : }
    4008                 : 
    4009                 : /************************************************************************/
    4010                 : /*                       GDALClientRasterBand()                         */
    4011                 : /************************************************************************/
    4012                 : 
    4013              32 : GDALClientRasterBand::GDALClientRasterBand(GDALPipe* p, int iSrvBand, 
    4014                 :                                            GDALClientDataset* poDS,
    4015                 :                                            int nBand, GDALAccess eAccess,
    4016                 :                                            int nRasterXSize, int nRasterYSize,
    4017                 :                                            GDALDataType eDataType,
    4018                 :                                            int nBlockXSize, int nBlockYSize,
    4019              32 :                                            GByte abyCapsIn[16])
    4020                 : {
    4021              32 :     this->p = p;
    4022              32 :     this->iSrvBand = iSrvBand;
    4023              32 :     this->poDS = poDS;
    4024              32 :     this->nBand = nBand;
    4025              32 :     this->eAccess = eAccess;
    4026              32 :     this->nRasterXSize = nRasterXSize;
    4027              32 :     this->nRasterYSize = nRasterYSize;
    4028              32 :     this->eDataType = eDataType;
    4029              32 :     this->nBlockXSize = nBlockXSize;
    4030              32 :     this->nBlockYSize = nBlockYSize;
    4031              32 :     papszCategoryNames = NULL;
    4032              32 :     poColorTable = NULL;
    4033              32 :     pszUnitType = NULL;
    4034              32 :     poMaskBand = NULL;
    4035              32 :     poRAT = NULL;
    4036              32 :     memcpy(abyCaps, abyCapsIn, sizeof(abyCaps));
    4037              32 :     bEnableLineCaching = CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_LINE_CACHING", "YES"));
    4038              32 :     nSuccessiveLinesRead = 0;
    4039              32 :     eLastBufType = GDT_Unknown;
    4040              32 :     nLastYOff = -1;
    4041              32 :     pabyCachedLines = NULL;
    4042              32 :     eCachedBufType = GDT_Unknown;
    4043              32 :     nCachedYStart = -1;
    4044              32 :     nCachedLines = 0;
    4045                 : 
    4046              32 : }
    4047                 : 
    4048                 : /************************************************************************/
    4049                 : /*                         ~GDALClientRasterBand()                      */
    4050                 : /************************************************************************/
    4051                 : 
    4052              32 : GDALClientRasterBand::~GDALClientRasterBand()
    4053                 : {
    4054              32 :     CSLDestroy(papszCategoryNames);
    4055              32 :     delete poColorTable;
    4056              32 :     CPLFree(pszUnitType);
    4057              32 :     delete poMaskBand;
    4058              32 :     delete poRAT;
    4059              32 :     CPLFree(pabyCachedLines);
    4060                 : 
    4061              32 :     std::map<int, GDALRasterBand*>::iterator oIter = aMapOvrBands.begin();
    4062              38 :     for( ; oIter != aMapOvrBands.end(); ++oIter )
    4063               6 :         delete oIter->second;
    4064                 : 
    4065                 :     std::map< std::pair<CPLString,CPLString>, char*>::iterator oIterItem =
    4066              32 :         aoMapMetadataItem.begin();
    4067              48 :     for( ; oIterItem != aoMapMetadataItem.end(); ++oIterItem )
    4068              16 :         CPLFree(oIterItem->second);
    4069                 : 
    4070              32 :     std::map<CPLString, char**>::iterator oIterMD = aoMapMetadata.begin();
    4071              40 :     for( ; oIterMD != aoMapMetadata.end(); ++oIterMD )
    4072               8 :         CSLDestroy(oIterMD->second);
    4073                 :     
    4074              32 :     for(int i=0; i < (int)apoOldMaskBands.size(); i++)
    4075               0 :         delete apoOldMaskBands[i];
    4076              32 : }
    4077                 : 
    4078                 : /************************************************************************/
    4079                 : /*                       CreateFakeMaskBand()                           */
    4080                 : /************************************************************************/
    4081                 : 
    4082               0 : GDALRasterBand* GDALClientRasterBand::CreateFakeMaskBand()
    4083                 : {
    4084               0 :     if( poMaskBand == NULL )
    4085               0 :         poMaskBand = new GDALAllValidMaskBand(this);
    4086               0 :     return poMaskBand;
    4087                 : }
    4088                 : 
    4089                 : /************************************************************************/
    4090                 : /*                             WriteInstr()                             */
    4091                 : /************************************************************************/
    4092                 : 
    4093             378 : int GDALClientRasterBand::WriteInstr(InstrEnum instr)
    4094                 : {
    4095                 :     return GDALPipeWrite(p, instr) &&
    4096             378 :            GDALPipeWrite(p, iSrvBand);
    4097                 : }
    4098                 : 
    4099                 : /************************************************************************/
    4100                 : /*                             FlushCache()                             */
    4101                 : /************************************************************************/
    4102                 : 
    4103              38 : CPLErr GDALClientRasterBand::FlushCache()
    4104                 : {
    4105              38 :     if( !SupportsInstr(INSTR_Band_FlushCache) )
    4106               0 :         return GDALPamRasterBand::FlushCache();
    4107                 : 
    4108              38 :     InvalidateCachedLines();
    4109                 : 
    4110                 :     CLIENT_ENTER();
    4111              38 :     CPLErr eErr = GDALPamRasterBand::FlushCache();
    4112              38 :     if( eErr == CE_None )
    4113                 :     {
    4114              38 :         if( !WriteInstr(INSTR_Band_FlushCache) )
    4115               0 :             return CE_Failure;
    4116              38 :         return CPLErrOnlyRet(p);
    4117                 :     }
    4118               0 :     return eErr;
    4119                 : }
    4120                 : /************************************************************************/
    4121                 : /*                          GetCategoryNames()                          */
    4122                 : /************************************************************************/
    4123                 : 
    4124              16 : char ** GDALClientRasterBand::GetCategoryNames()
    4125                 : {
    4126              16 :     if( !SupportsInstr(INSTR_Band_GetCategoryNames) )
    4127               0 :         return GDALPamRasterBand::GetCategoryNames();
    4128                 : 
    4129                 :     CLIENT_ENTER();
    4130              16 :     if( !WriteInstr(INSTR_Band_GetCategoryNames) )
    4131               0 :         return NULL;
    4132              16 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4133               0 :         return NULL;
    4134                 : 
    4135              16 :     CSLDestroy(papszCategoryNames);
    4136              16 :     papszCategoryNames = NULL;
    4137              16 :     if( !GDALPipeRead(p, &papszCategoryNames) )
    4138               0 :         return NULL;
    4139              16 :     GDALConsumeErrors(p);
    4140              16 :     return papszCategoryNames;
    4141                 : }
    4142                 : 
    4143                 : /************************************************************************/
    4144                 : /*                          SetCategoryNames()                          */
    4145                 : /************************************************************************/
    4146                 : 
    4147               3 : CPLErr GDALClientRasterBand::SetCategoryNames( char ** papszCategoryNames )
    4148                 : {
    4149               3 :     if( !SupportsInstr(INSTR_Band_SetCategoryNames) )
    4150               0 :         return GDALPamRasterBand::SetCategoryNames(papszCategoryNames);
    4151                 : 
    4152                 :     CLIENT_ENTER();
    4153               3 :     if( !WriteInstr(INSTR_Band_SetCategoryNames) ||
    4154                 :         !GDALPipeWrite(p, papszCategoryNames) )
    4155               0 :         return CE_Failure;
    4156               3 :     return CPLErrOnlyRet(p);
    4157                 : }
    4158                 : 
    4159                 : /************************************************************************/
    4160                 : /*                        SetDescription()                              */
    4161                 : /************************************************************************/
    4162                 : 
    4163               3 : void GDALClientRasterBand::SetDescription( const char * pszDescription )
    4164                 : {
    4165               3 :     if( !SupportsInstr(INSTR_Band_SetDescription) )
    4166                 :     {
    4167               0 :         GDALPamRasterBand::SetDescription(pszDescription);
    4168               0 :         return;
    4169                 :     }
    4170                 : 
    4171                 :     CLIENT_ENTER();
    4172               3 :     sDescription = pszDescription;
    4173               6 :     if( !WriteInstr(INSTR_Band_SetDescription) ||
    4174                 :         !GDALPipeWrite(p, pszDescription) ||
    4175                 :         !GDALSkipUntilEndOfJunkMarker(p))
    4176               0 :         return;
    4177               3 :     GDALConsumeErrors(p);
    4178                 : }
    4179                 : 
    4180                 : /************************************************************************/
    4181                 : /*                            GetMetadata()                             */
    4182                 : /************************************************************************/
    4183                 : 
    4184              18 : char** GDALClientRasterBand::GetMetadata( const char * pszDomain )
    4185                 : {
    4186              18 :     if( !SupportsInstr(INSTR_Band_GetMetadata) )
    4187               0 :         return GDALPamRasterBand::GetMetadata(pszDomain);
    4188                 : 
    4189                 :     CLIENT_ENTER();
    4190              18 :     if( pszDomain == NULL )
    4191               0 :         pszDomain = "";
    4192              18 :     std::map<CPLString, char**>::iterator oIter = aoMapMetadata.find(CPLString(pszDomain));
    4193              18 :     if( oIter != aoMapMetadata.end() )
    4194                 :     {
    4195              10 :         CSLDestroy(oIter->second);
    4196              10 :         aoMapMetadata.erase(oIter);
    4197                 :     }
    4198              18 :     if( !WriteInstr(INSTR_Band_GetMetadata) ||
    4199                 :         !GDALPipeWrite(p, pszDomain) )
    4200               0 :         return NULL;
    4201              18 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4202               0 :         return NULL;
    4203                 : 
    4204              18 :     char** papszMD = NULL;
    4205              18 :     if( !GDALPipeRead(p, &papszMD) )
    4206               0 :         return NULL;
    4207              18 :     aoMapMetadata[pszDomain] = papszMD;
    4208              18 :     GDALConsumeErrors(p);
    4209              18 :     return papszMD;
    4210                 : }
    4211                 : 
    4212                 : /************************************************************************/
    4213                 : /*                        GetMetadataItem()                             */
    4214                 : /************************************************************************/
    4215                 : 
    4216              22 : const char* GDALClientRasterBand::GetMetadataItem( const char * pszName,
    4217                 :                                                    const char * pszDomain )
    4218                 : {
    4219              22 :     if( !SupportsInstr(INSTR_Band_GetMetadataItem) )
    4220               0 :         return GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
    4221                 : 
    4222                 :     CLIENT_ENTER();
    4223              22 :     if( pszDomain == NULL )
    4224               0 :         pszDomain = "";
    4225                 :     std::pair<CPLString,CPLString> oPair =
    4226              22 :         std::pair<CPLString,CPLString> (CPLString(pszDomain), CPLString(pszName));
    4227                 :     std::map< std::pair<CPLString,CPLString>, char*>::iterator oIter =
    4228              22 :         aoMapMetadataItem.find(oPair);
    4229              22 :     if( oIter != aoMapMetadataItem.end() )
    4230                 :     {
    4231               6 :         CPLFree(oIter->second);
    4232               6 :         aoMapMetadataItem.erase(oIter);
    4233                 :     }
    4234              22 :     if( !WriteInstr(INSTR_Band_GetMetadataItem) ||
    4235                 :         !GDALPipeWrite(p, pszName) ||
    4236                 :         !GDALPipeWrite(p, pszDomain) )
    4237               0 :         return NULL;
    4238              22 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4239               0 :         return NULL;
    4240                 : 
    4241              22 :     char* pszItem = NULL;
    4242              22 :     if( !GDALPipeRead(p, &pszItem) )
    4243               0 :         return NULL;
    4244              22 :     aoMapMetadataItem[oPair] = pszItem;
    4245              22 :     GDALConsumeErrors(p);
    4246              22 :     return pszItem;
    4247                 : }
    4248                 : 
    4249                 : /************************************************************************/
    4250                 : /*                            SetMetadata()                             */
    4251                 : /************************************************************************/
    4252                 : 
    4253               6 : CPLErr GDALClientRasterBand::SetMetadata( char ** papszMetadata,
    4254                 :                                    const char * pszDomain )
    4255                 : {
    4256               6 :     if( !SupportsInstr(INSTR_Band_SetMetadata) )
    4257               0 :         return GDALPamRasterBand::SetMetadata(papszMetadata, pszDomain);
    4258                 : 
    4259                 :     CLIENT_ENTER();
    4260               6 :     if( !WriteInstr(INSTR_Band_SetMetadata) ||
    4261                 :         !GDALPipeWrite(p, papszMetadata) ||
    4262                 :         !GDALPipeWrite(p, pszDomain) )
    4263               0 :         return CE_Failure;
    4264               6 :     return CPLErrOnlyRet(p);
    4265                 : }
    4266                 : 
    4267                 : /************************************************************************/
    4268                 : /*                        SetMetadataItem()                             */
    4269                 : /************************************************************************/
    4270                 : 
    4271               3 : CPLErr GDALClientRasterBand::SetMetadataItem( const char * pszName,
    4272                 :                                           const char * pszValue,
    4273                 :                                           const char * pszDomain )
    4274                 : {
    4275               3 :     if( !SupportsInstr(INSTR_Band_SetMetadataItem) )
    4276               0 :         return GDALPamRasterBand::SetMetadataItem(pszName, pszValue, pszDomain);
    4277                 : 
    4278                 :     CLIENT_ENTER();
    4279               3 :     if( !WriteInstr(INSTR_Band_SetMetadataItem) ||
    4280                 :         !GDALPipeWrite(p, pszName) ||
    4281                 :         !GDALPipeWrite(p, pszValue) ||
    4282                 :         !GDALPipeWrite(p, pszDomain) )
    4283               0 :         return CE_Failure;
    4284               3 :     return CPLErrOnlyRet(p);
    4285                 : }
    4286                 : 
    4287                 : /************************************************************************/
    4288                 : /*                       GetColorInterpretation()                       */
    4289                 : /************************************************************************/
    4290                 : 
    4291              13 : GDALColorInterp GDALClientRasterBand::GetColorInterpretation()
    4292                 : {
    4293              13 :     if( !SupportsInstr(INSTR_Band_GetColorInterpretation) )
    4294               0 :         return GDALPamRasterBand::GetColorInterpretation();
    4295                 : 
    4296                 :     CLIENT_ENTER();
    4297              13 :     if( !WriteInstr(INSTR_Band_GetColorInterpretation) )
    4298               0 :         return GCI_Undefined;
    4299              13 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4300               0 :         return GCI_Undefined;
    4301                 : 
    4302                 :     int nInt;
    4303              13 :     if( !GDALPipeRead(p, &nInt) )
    4304               0 :         return GCI_Undefined;
    4305              13 :     GDALConsumeErrors(p);
    4306              13 :     return (GDALColorInterp)nInt;
    4307                 : }
    4308                 : 
    4309                 : /************************************************************************/
    4310                 : /*                       SetColorInterpretation()                       */
    4311                 : /************************************************************************/
    4312                 : 
    4313               0 : CPLErr GDALClientRasterBand::SetColorInterpretation(GDALColorInterp eInterp)
    4314                 : {
    4315               0 :     if( !SupportsInstr(INSTR_Band_SetColorInterpretation) )
    4316               0 :         return GDALPamRasterBand::SetColorInterpretation(eInterp);
    4317                 : 
    4318                 :     CLIENT_ENTER();
    4319               0 :     if( !WriteInstr(INSTR_Band_SetColorInterpretation) ||
    4320                 :         !GDALPipeWrite(p, eInterp) )
    4321               0 :         return CE_Failure;
    4322               0 :     return CPLErrOnlyRet(p);
    4323                 : }
    4324                 : 
    4325                 : /************************************************************************/
    4326                 : /*                           GetStatistics()                            */
    4327                 : /************************************************************************/
    4328                 : 
    4329              12 : CPLErr GDALClientRasterBand::GetStatistics( int bApproxOK, int bForce,
    4330                 :                                             double *pdfMin, double *pdfMax, 
    4331                 :                                             double *pdfMean, double *pdfStdDev )
    4332                 : {
    4333              12 :     if( !SupportsInstr(INSTR_Band_GetStatistics) )
    4334                 :         return GDALPamRasterBand::GetStatistics(
    4335               0 :             bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev);
    4336                 : 
    4337                 :     CLIENT_ENTER();
    4338              12 :     if( !bApproxOK && CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
    4339               0 :         bApproxOK = TRUE;
    4340              12 :     CPLErr eDefaultRet = CE_Failure;
    4341              12 :     if( CSLTestBoolean(CPLGetConfigOption("QGIS_HACK", "NO")) )
    4342                 :     {
    4343               0 :         if( pdfMin ) *pdfMin = 0;
    4344               0 :         if( pdfMax ) *pdfMax = 255;
    4345               0 :         if( pdfMean ) *pdfMean = 0;
    4346               0 :         if( pdfStdDev ) *pdfStdDev = 0;
    4347               0 :         eDefaultRet = CE_None;
    4348                 :     }
    4349              12 :     if( !WriteInstr( INSTR_Band_GetStatistics) ||
    4350                 :         !GDALPipeWrite(p, bApproxOK) ||
    4351                 :         !GDALPipeWrite(p, bForce) )
    4352               0 :         return eDefaultRet;
    4353              12 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4354               0 :         return eDefaultRet;
    4355                 : 
    4356              12 :     CPLErr eRet = eDefaultRet;
    4357              12 :     if( !GDALPipeRead(p, &eRet) )
    4358               0 :         return eRet;
    4359              12 :     if( eRet == CE_None )
    4360                 :     {
    4361                 :         double dfMin, dfMax, dfMean, dfStdDev;
    4362               9 :         if( !GDALPipeRead(p, &dfMin) ||
    4363                 :             !GDALPipeRead(p, &dfMax) ||
    4364                 :             !GDALPipeRead(p, &dfMean) ||
    4365                 :             !GDALPipeRead(p, &dfStdDev) )
    4366               0 :             return eDefaultRet;
    4367               9 :         if( pdfMin ) *pdfMin = dfMin;
    4368               9 :         if( pdfMax ) *pdfMax = dfMax;
    4369               9 :         if( pdfMean ) *pdfMean = dfMean;
    4370               9 :         if( pdfStdDev ) *pdfStdDev = dfStdDev;
    4371                 :     }
    4372               3 :     else if( eDefaultRet == CE_None )
    4373               0 :         eRet = eDefaultRet;
    4374              12 :     GDALConsumeErrors(p);
    4375              12 :     return eRet;
    4376                 : }
    4377                 : 
    4378                 : /************************************************************************/
    4379                 : /*                         ComputeStatistics()                          */
    4380                 : /************************************************************************/
    4381                 : 
    4382               3 : CPLErr GDALClientRasterBand::ComputeStatistics( int bApproxOK, 
    4383                 :                                                 double *pdfMin,
    4384                 :                                                 double *pdfMax, 
    4385                 :                                                 double *pdfMean,
    4386                 :                                                 double *pdfStdDev,
    4387                 :                                                 GDALProgressFunc pfnProgress,
    4388                 :                                                 void *pProgressData )
    4389                 : {
    4390               3 :     if( !SupportsInstr(INSTR_Band_ComputeStatistics) )
    4391                 :         return GDALPamRasterBand::ComputeStatistics(
    4392               0 :             bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev, pfnProgress, pProgressData);
    4393                 : 
    4394                 :     CLIENT_ENTER();
    4395               3 :     if( !bApproxOK && CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
    4396               0 :         bApproxOK = TRUE;
    4397               3 :     if( !WriteInstr(INSTR_Band_ComputeStatistics) ||
    4398                 :         !GDALPipeWrite(p, bApproxOK) )
    4399               0 :         return CE_Failure;
    4400               3 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4401               0 :         return CE_Failure;
    4402                 : 
    4403               3 :     CPLErr eRet = CE_Failure;
    4404               3 :     if( !GDALPipeRead(p, &eRet) )
    4405               0 :         return eRet;
    4406               3 :     if( eRet != CE_Failure )
    4407                 :     {
    4408                 :         double dfMin, dfMax, dfMean, dfStdDev;
    4409               3 :         if( !GDALPipeRead(p, &dfMin) ||
    4410                 :             !GDALPipeRead(p, &dfMax) ||
    4411                 :             !GDALPipeRead(p, &dfMean) ||
    4412                 :             !GDALPipeRead(p, &dfStdDev) )
    4413               0 :             return CE_Failure;
    4414               3 :         if( pdfMin ) *pdfMin = dfMin;
    4415               3 :         if( pdfMax ) *pdfMax = dfMax;
    4416               3 :         if( pdfMean ) *pdfMean = dfMean;
    4417               3 :         if( pdfStdDev ) *pdfStdDev = dfStdDev;
    4418                 :     }
    4419               3 :     GDALConsumeErrors(p);
    4420               3 :     return eRet;
    4421                 : }
    4422                 : 
    4423                 : /************************************************************************/
    4424                 : /*                           SetStatistics()                            */
    4425                 : /************************************************************************/
    4426                 : 
    4427               3 : CPLErr GDALClientRasterBand::SetStatistics( double dfMin, double dfMax, 
    4428                 :                                         double dfMean, double dfStdDev )
    4429                 : {
    4430               3 :     if( !SupportsInstr(INSTR_Band_SetStatistics) )
    4431               0 :         return GDALPamRasterBand::SetStatistics(dfMin, dfMax, dfMean, dfStdDev);
    4432                 : 
    4433                 :     CLIENT_ENTER();
    4434               3 :     if( !WriteInstr(INSTR_Band_SetStatistics) ||
    4435                 :         !GDALPipeWrite(p, dfMin) ||
    4436                 :         !GDALPipeWrite(p, dfMax) ||
    4437                 :         !GDALPipeWrite(p, dfMean) ||
    4438                 :         !GDALPipeWrite(p, dfStdDev) )
    4439               0 :         return CE_Failure;
    4440               3 :     return CPLErrOnlyRet(p);
    4441                 : }
    4442                 : 
    4443                 : /************************************************************************/
    4444                 : /*                        ComputeRasterMinMax()                         */
    4445                 : /************************************************************************/
    4446                 : 
    4447               0 : CPLErr GDALClientRasterBand::ComputeRasterMinMax( int bApproxOK,
    4448                 :                                                   double* padfMinMax )
    4449                 : {
    4450               0 :     if( !SupportsInstr(INSTR_Band_ComputeRasterMinMax) )
    4451               0 :         return GDALPamRasterBand::ComputeRasterMinMax(bApproxOK, padfMinMax);
    4452                 : 
    4453                 :     CLIENT_ENTER();
    4454               0 :     if( !bApproxOK && CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
    4455               0 :         bApproxOK = TRUE;
    4456               0 :     if( !WriteInstr(INSTR_Band_ComputeRasterMinMax) ||
    4457                 :         !GDALPipeWrite(p, bApproxOK) )
    4458               0 :         return CE_Failure;
    4459               0 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4460               0 :         return CE_Failure;
    4461                 : 
    4462               0 :     CPLErr eRet = CE_Failure;
    4463               0 :     if( !GDALPipeRead(p, &eRet) )
    4464               0 :         return eRet;
    4465               0 :     if( eRet != CE_Failure )
    4466                 :     {
    4467               0 :         if( !GDALPipeRead(p, padfMinMax + 0) ||
    4468                 :             !GDALPipeRead(p, padfMinMax + 1) )
    4469               0 :             return CE_Failure;
    4470                 :     }
    4471               0 :     GDALConsumeErrors(p);
    4472               0 :     return eRet;
    4473                 : }
    4474                 : 
    4475                 : /************************************************************************/
    4476                 : /*                            GetHistogram()                            */
    4477                 : /************************************************************************/
    4478                 : 
    4479               3 : CPLErr GDALClientRasterBand::GetHistogram( double dfMin, double dfMax, 
    4480                 :                                            int nBuckets, int *panHistogram, 
    4481                 :                                            int bIncludeOutOfRange,
    4482                 :                                            int bApproxOK,
    4483                 :                                            GDALProgressFunc pfnProgress, 
    4484                 :                                            void *pProgressData )
    4485                 : {
    4486               3 :     if( !SupportsInstr(INSTR_Band_GetHistogram) )
    4487                 :         return GDALPamRasterBand::GetHistogram(
    4488               0 :             dfMin, dfMax, nBuckets, panHistogram, bIncludeOutOfRange, bApproxOK, pfnProgress, pProgressData);
    4489                 : 
    4490                 :     CLIENT_ENTER();
    4491               3 :     if( !bApproxOK && CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
    4492               0 :         bApproxOK = TRUE;
    4493               3 :     CPLErr eDefaultRet = CE_Failure;
    4494               3 :     if( CSLTestBoolean(CPLGetConfigOption("QGIS_HACK", "NO")) )
    4495                 :     {
    4496               0 :         memset(panHistogram, 0, sizeof(int) * nBuckets);
    4497               0 :         eDefaultRet = CE_None;
    4498                 :     }
    4499               3 :     if( !WriteInstr(INSTR_Band_GetHistogram) ||
    4500                 :         !GDALPipeWrite(p, dfMin) ||
    4501                 :         !GDALPipeWrite(p, dfMax) ||
    4502                 :         !GDALPipeWrite(p, nBuckets) ||
    4503                 :         !GDALPipeWrite(p, bIncludeOutOfRange) ||
    4504                 :         !GDALPipeWrite(p, bApproxOK) )
    4505               0 :         return eDefaultRet;
    4506               3 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4507               0 :         return eDefaultRet;
    4508                 : 
    4509               3 :     CPLErr eRet = eDefaultRet;
    4510               3 :     if( !GDALPipeRead(p, &eRet) )
    4511               0 :         return eRet;
    4512               3 :     if( eRet != CE_Failure )
    4513                 :     {
    4514                 :         int nSize;
    4515               3 :         if( !GDALPipeRead(p, &nSize) ||
    4516                 :             nSize != nBuckets * (int)sizeof(int) ||
    4517                 :             !GDALPipeRead_nolength(p, nSize, panHistogram) )
    4518               0 :             return eDefaultRet;
    4519                 :     }
    4520               0 :     else if( eDefaultRet == CE_None )
    4521               0 :         eRet = eDefaultRet;
    4522               3 :     GDALConsumeErrors(p);
    4523               3 :     return eRet;
    4524                 : }
    4525                 : 
    4526                 : /************************************************************************/
    4527                 : /*                        GetDefaultHistogram()                         */
    4528                 : /************************************************************************/
    4529                 : 
    4530               6 : CPLErr GDALClientRasterBand::GetDefaultHistogram( double *pdfMin,
    4531                 :                                                   double *pdfMax,
    4532                 :                                                   int *pnBuckets,
    4533                 :                                                   int ** ppanHistogram,
    4534                 :                                                   int bForce,
    4535                 :                                                   GDALProgressFunc pfnProgress,
    4536                 :                                                   void *pProgressData )
    4537                 : {
    4538               6 :     if( !SupportsInstr(INSTR_Band_GetDefaultHistogram) )
    4539                 :         return GDALPamRasterBand::GetDefaultHistogram(
    4540               0 :             pdfMin, pdfMax, pnBuckets, ppanHistogram, bForce, pfnProgress, pProgressData);
    4541                 : 
    4542                 :     CLIENT_ENTER();
    4543               6 :     if( !WriteInstr(INSTR_Band_GetDefaultHistogram) ||
    4544                 :         !GDALPipeWrite(p, bForce) )
    4545               0 :         return CE_Failure;
    4546               6 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4547               0 :         return CE_Failure;
    4548               6 :     CPLErr eRet = CE_Failure;
    4549               6 :     if( !GDALPipeRead(p, &eRet) )
    4550               0 :         return eRet;
    4551               6 :     if( eRet != CE_Failure )
    4552                 :     {
    4553                 :         double dfMin, dfMax;
    4554                 :         int nBuckets, nSize;
    4555               6 :         if( !GDALPipeRead(p, &dfMin) ||
    4556                 :             !GDALPipeRead(p, &dfMax) ||
    4557                 :             !GDALPipeRead(p, &nBuckets) ||
    4558                 :             !GDALPipeRead(p, &nSize) )
    4559               0 :             return CE_Failure;
    4560               6 :         if( nSize != nBuckets * (int)sizeof(int) )
    4561               0 :             return CE_Failure;
    4562               6 :         if( pdfMin ) *pdfMin = dfMin;
    4563               6 :         if( pdfMax ) *pdfMax = dfMax;
    4564               6 :         if( pnBuckets ) *pnBuckets = nBuckets;
    4565               6 :         if( ppanHistogram )
    4566                 :         {
    4567               6 :             *ppanHistogram = (int*)VSIMalloc(nSize);
    4568               6 :             if( *ppanHistogram == NULL )
    4569               0 :                 return CE_Failure;
    4570               6 :             if( !GDALPipeRead_nolength(p, nSize, *ppanHistogram) )
    4571               0 :                 return CE_Failure;
    4572                 :         }
    4573                 :         else
    4574                 :         {
    4575               0 :             int *panHistogram = (int*)VSIMalloc(nSize);
    4576               0 :             if( panHistogram == NULL )
    4577               0 :                 return CE_Failure;
    4578               0 :             if( !GDALPipeRead_nolength(p, nSize, panHistogram) )
    4579                 :             {
    4580               0 :                 CPLFree(panHistogram);
    4581               0 :                 return CE_Failure;
    4582                 :             }
    4583               0 :             CPLFree(panHistogram);
    4584                 :         }
    4585                 :     }
    4586               6 :     GDALConsumeErrors(p);
    4587               6 :     return eRet;
    4588                 : }
    4589                 : 
    4590                 : /************************************************************************/
    4591                 : /*                        SetDefaultHistogram()                         */
    4592                 : /************************************************************************/
    4593                 : 
    4594               3 : CPLErr GDALClientRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
    4595                 :                                               int nBuckets, int *panHistogram )
    4596                 : {
    4597               3 :     if( !SupportsInstr(INSTR_Band_SetDefaultHistogram) )
    4598               0 :         return GDALPamRasterBand::SetDefaultHistogram(dfMin, dfMax, nBuckets, panHistogram);
    4599                 : 
    4600                 :     CLIENT_ENTER();
    4601               3 :     if( !WriteInstr(INSTR_Band_SetDefaultHistogram) ||
    4602                 :         !GDALPipeWrite(p, dfMin) ||
    4603                 :         !GDALPipeWrite(p, dfMax) ||
    4604                 :         !GDALPipeWrite(p, nBuckets) ||
    4605                 :         !GDALPipeWrite(p, nBuckets * sizeof(int), panHistogram) )
    4606               0 :         return CE_Failure;
    4607               3 :     return CPLErrOnlyRet(p);
    4608                 : }
    4609                 : 
    4610                 : /************************************************************************/
    4611                 : /*                            IReadBlock()                              */
    4612                 : /************************************************************************/
    4613                 : 
    4614               0 : CPLErr GDALClientRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void* pImage)
    4615                 : {
    4616               0 :     if( !SupportsInstr(INSTR_Band_IReadBlock) )
    4617               0 :         return CE_Failure;
    4618                 : 
    4619                 :     CLIENT_ENTER();
    4620               0 :     if( poDS != NULL )
    4621               0 :         ((GDALClientDataset*)poDS)->ProcessAsyncProgress();
    4622                 : 
    4623               0 :     if( !WriteInstr(INSTR_Band_IReadBlock) ||
    4624                 :         !GDALPipeWrite(p, nBlockXOff) ||
    4625                 :         !GDALPipeWrite(p, nBlockYOff) )
    4626               0 :         return CE_Failure;
    4627               0 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4628               0 :         return CE_Failure;
    4629                 : 
    4630               0 :     CPLErr eRet = CE_Failure;
    4631               0 :     if( !GDALPipeRead(p, &eRet) )
    4632               0 :         return eRet;
    4633                 :     int nSize;
    4634               0 :     if( !GDALPipeRead(p, &nSize) ||
    4635                 :         nSize != nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) ||
    4636                 :         !GDALPipeRead_nolength(p, nSize, pImage) )
    4637               0 :         return CE_Failure;
    4638                 : 
    4639               0 :     GDALConsumeErrors(p);
    4640               0 :     return eRet;
    4641                 : }
    4642                 : 
    4643                 : /************************************************************************/
    4644                 : /*                            IWriteBlock()                             */
    4645                 : /************************************************************************/
    4646                 : 
    4647               0 : CPLErr GDALClientRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void* pImage)
    4648                 : {
    4649               0 :     if( !SupportsInstr(INSTR_Band_IWriteBlock) )
    4650               0 :         return CE_Failure;
    4651                 : 
    4652               0 :     InvalidateCachedLines();
    4653                 : 
    4654                 :     CLIENT_ENTER();
    4655               0 :     int nSize = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
    4656               0 :     if( !WriteInstr(INSTR_Band_IWriteBlock) ||
    4657                 :         !GDALPipeWrite(p, nBlockXOff) ||
    4658                 :         !GDALPipeWrite(p, nBlockYOff) ||
    4659                 :         !GDALPipeWrite(p, nSize, pImage) )
    4660               0 :         return CE_Failure;
    4661               0 :     return CPLErrOnlyRet(p);
    4662                 : }
    4663                 : 
    4664                 : /************************************************************************/
    4665                 : /*                      IRasterIO_read_internal()                       */
    4666                 : /************************************************************************/
    4667                 : 
    4668              57 : CPLErr GDALClientRasterBand::IRasterIO_read_internal(
    4669                 :                                     int nXOff, int nYOff, int nXSize, int nYSize,
    4670                 :                                     void * pData, int nBufXSize, int nBufYSize,
    4671                 :                                     GDALDataType eBufType,
    4672                 :                                     int nPixelSpace, int nLineSpace )
    4673                 : {
    4674              57 :     CPLErr eRet = CE_Failure;
    4675                 : 
    4676              57 :     if( !WriteInstr(INSTR_Band_IRasterIO_Read) ||
    4677                 :         !GDALPipeWrite(p, nXOff) ||
    4678                 :         !GDALPipeWrite(p, nYOff) ||
    4679                 :         !GDALPipeWrite(p, nXSize) ||
    4680                 :         !GDALPipeWrite(p, nYSize) ||
    4681                 :         !GDALPipeWrite(p, nBufXSize) ||
    4682                 :         !GDALPipeWrite(p, nBufYSize) ||
    4683                 :         !GDALPipeWrite(p, eBufType) )
    4684               0 :         return CE_Failure;
    4685              57 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4686               0 :         return CE_Failure;
    4687                 : 
    4688              57 :     if( !GDALPipeRead(p, &eRet) )
    4689               0 :         return eRet;
    4690                 : 
    4691                 :     int nSize;
    4692              57 :     if( !GDALPipeRead(p, &nSize) )
    4693               0 :         return CE_Failure;
    4694              57 :     int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
    4695              57 :     GIntBig nExpectedSize = (GIntBig)nBufXSize * nBufYSize * nDataTypeSize;
    4696              57 :     if( nSize != nExpectedSize )
    4697               0 :         return CE_Failure;
    4698             114 :     if( nPixelSpace == nDataTypeSize &&
    4699                 :         nLineSpace == nBufXSize * nDataTypeSize )
    4700                 :     {
    4701              57 :         if( !GDALPipeRead_nolength(p, nSize, pData) )
    4702               0 :             return CE_Failure;
    4703                 :     }
    4704                 :     else
    4705                 :     {
    4706               0 :         GByte* pBuf = (GByte*)VSIMalloc(nSize);
    4707               0 :         if( pBuf == NULL )
    4708               0 :             return CE_Failure;
    4709               0 :         if( !GDALPipeRead_nolength(p, nSize, pBuf) )
    4710                 :         {
    4711               0 :             VSIFree(pBuf);
    4712               0 :             return CE_Failure;
    4713                 :         }
    4714               0 :         for(int j=0;j<nBufYSize;j++)
    4715                 :         {
    4716                 :             GDALCopyWords( pBuf + j * nBufXSize * nDataTypeSize,
    4717                 :                             eBufType, nDataTypeSize,
    4718                 :                             (GByte*)pData + j * nLineSpace,
    4719                 :                             eBufType, nPixelSpace,
    4720               0 :                             nBufXSize );
    4721                 :         }
    4722               0 :         VSIFree(pBuf);
    4723                 :     }
    4724                 : 
    4725              57 :     GDALConsumeErrors(p);
    4726              57 :     return eRet;
    4727                 : }
    4728                 : 
    4729                 : /************************************************************************/
    4730                 : /*                       InvalidateCachedLines()                        */
    4731                 : /************************************************************************/
    4732                 : 
    4733             103 : void GDALClientRasterBand::InvalidateCachedLines()
    4734                 : {
    4735             103 :     nSuccessiveLinesRead = 0;
    4736             103 :     nCachedYStart = -1;
    4737             103 : }
    4738                 : 
    4739                 : /************************************************************************/
    4740                 : /*                             IRasterIO()                              */
    4741                 : /************************************************************************/
    4742                 : 
    4743             366 : CPLErr GDALClientRasterBand::IRasterIO( GDALRWFlag eRWFlag,
    4744                 :                                     int nXOff, int nYOff, int nXSize, int nYSize,
    4745                 :                                     void * pData, int nBufXSize, int nBufYSize,
    4746                 :                                     GDALDataType eBufType,
    4747                 :                                     int nPixelSpace, int nLineSpace )
    4748                 : {
    4749             366 :     if( !SupportsInstr( (eRWFlag == GF_Read) ? INSTR_Band_IRasterIO_Read : INSTR_Band_IRasterIO_Write) )
    4750                 :         return GDALPamRasterBand::IRasterIO( eRWFlag,
    4751                 :                                              nXOff, nYOff, nXSize, nYSize,
    4752                 :                                              pData, nBufXSize, nBufYSize,
    4753                 :                                              eBufType, 
    4754               0 :                                              nPixelSpace, nLineSpace );
    4755                 : 
    4756                 :     CLIENT_ENTER();
    4757             366 :     CPLErr eRet = CE_Failure;
    4758                 : 
    4759             366 :     if( poDS != NULL )
    4760             366 :         ((GDALClientDataset*)poDS)->ProcessAsyncProgress();
    4761                 : 
    4762             366 :     if( eRWFlag == GF_Read )
    4763                 :     {
    4764                 :         /*if( GetAccess() == GA_Update )
    4765                 :             FlushCache();*/
    4766                 : 
    4767                 :         /* Detect scanline reading pattern and read several rows in advance */
    4768                 :         /* to save a few client/server roundtrips */
    4769             399 :         if( bEnableLineCaching &&
    4770                 :             nXOff == 0 && nXSize == nRasterXSize && nYSize == 1 &&
    4771                 :             nBufXSize == nXSize && nBufYSize == nYSize )
    4772                 :         {
    4773             360 :             int nBufTypeSize = GDALGetDataTypeSize(eBufType) / 8;
    4774                 : 
    4775                 :             /* Is the current line already cached ? */
    4776             360 :             if( nCachedYStart >= 0 &&
    4777                 :                 nYOff >= nCachedYStart && nYOff < nCachedYStart + nCachedLines &&
    4778                 :                 eBufType == eCachedBufType )
    4779                 :             {
    4780             306 :                 nSuccessiveLinesRead ++;
    4781                 : 
    4782             306 :                 int nCachedBufTypeSize = GDALGetDataTypeSize(eCachedBufType) / 8;
    4783                 :                 GDALCopyWords(pabyCachedLines + (nYOff - nCachedYStart) * nXSize * nCachedBufTypeSize,
    4784                 :                               eCachedBufType, nCachedBufTypeSize,
    4785                 :                               pData, eBufType, nPixelSpace,
    4786             306 :                               nXSize);
    4787             306 :                 nLastYOff = nYOff;
    4788             306 :                 eLastBufType = eBufType;
    4789             306 :                 return CE_None;
    4790                 :             }
    4791                 : 
    4792              72 :             if( nYOff == nLastYOff + 1 &&
    4793                 :                 eBufType == eLastBufType )
    4794                 :             {
    4795              36 :                 nSuccessiveLinesRead ++;
    4796              36 :                 if( nSuccessiveLinesRead >= 2 )
    4797                 :                 {
    4798              18 :                     if( pabyCachedLines == NULL )
    4799                 :                     {
    4800               9 :                         nCachedLines = 10 * 1024 * 1024 / (nXSize * nBufTypeSize);
    4801               9 :                         if( nCachedLines > 1 )
    4802                 :                             pabyCachedLines = (GByte*) VSIMalloc(
    4803               9 :                                 nCachedLines * nXSize * nBufTypeSize);
    4804                 :                     }
    4805              18 :                     if( pabyCachedLines != NULL )
    4806                 :                     {
    4807              18 :                         int nLinesToRead = nCachedLines;
    4808              18 :                         if( nYOff + nLinesToRead > nRasterYSize )
    4809              18 :                             nLinesToRead = nRasterYSize - nYOff;
    4810                 :                         eRet = IRasterIO_read_internal( nXOff, nYOff, nXSize, nLinesToRead,
    4811                 :                                                         pabyCachedLines, nXSize, nLinesToRead,
    4812                 :                                                         eBufType,
    4813              18 :                                                         nBufTypeSize, nBufTypeSize * nXSize );
    4814              18 :                         if( eRet == CE_None )
    4815                 :                         {
    4816              18 :                             eCachedBufType = eBufType;
    4817              18 :                             nCachedYStart = nYOff;
    4818                 : 
    4819              18 :                             int nCachedBufTypeSize = GDALGetDataTypeSize(eCachedBufType) / 8;
    4820                 :                             GDALCopyWords(pabyCachedLines + (nYOff - nCachedYStart) * nXSize * nCachedBufTypeSize,
    4821                 :                                         eCachedBufType, nCachedBufTypeSize,
    4822                 :                                         pData, eBufType, nPixelSpace,
    4823              18 :                                         nXSize);
    4824              18 :                             nLastYOff = nYOff;
    4825              18 :                             eLastBufType = eBufType;
    4826                 : 
    4827              18 :                             return CE_None;
    4828                 :                         }
    4829                 :                         else
    4830               0 :                             InvalidateCachedLines();
    4831                 :                     }
    4832                 :                 }
    4833                 :             }
    4834                 :             else
    4835              18 :                 InvalidateCachedLines();
    4836                 :         }
    4837                 :         else
    4838               3 :             InvalidateCachedLines();
    4839                 : 
    4840              39 :         nLastYOff = nYOff;
    4841              39 :         eLastBufType = eBufType;
    4842                 : 
    4843                 :         return IRasterIO_read_internal( nXOff, nYOff, nXSize, nYSize,
    4844                 :                                         pData, nBufXSize, nBufYSize,
    4845                 :                                         eBufType,
    4846              39 :                                         nPixelSpace, nLineSpace );
    4847                 :     }
    4848                 :     else
    4849                 :     {
    4850               3 :         InvalidateCachedLines();
    4851                 : 
    4852               3 :         if( !WriteInstr(INSTR_Band_IRasterIO_Write) ||
    4853                 :             !GDALPipeWrite(p, nXOff) ||
    4854                 :             !GDALPipeWrite(p, nYOff) ||
    4855                 :             !GDALPipeWrite(p, nXSize) ||
    4856                 :             !GDALPipeWrite(p, nYSize) ||
    4857                 :             !GDALPipeWrite(p, nBufXSize) ||
    4858                 :             !GDALPipeWrite(p, nBufYSize) ||
    4859                 :             !GDALPipeWrite(p, eBufType) )
    4860               0 :             return CE_Failure;
    4861                 : 
    4862               3 :         int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
    4863               3 :         GIntBig nSizeBig = (GIntBig)nBufXSize * nBufYSize * nDataTypeSize;
    4864               3 :         int nSize = (int)nSizeBig;
    4865               3 :         if( nSizeBig != nSize )
    4866               0 :             return CE_Failure;
    4867               6 :         if( nPixelSpace == nDataTypeSize &&
    4868                 :             nLineSpace == nBufXSize * nDataTypeSize )
    4869                 :         {
    4870               3 :             if( !GDALPipeWrite(p, nSize, pData) )
    4871               0 :                 return CE_Failure;
    4872                 :         }
    4873                 :         else
    4874                 :         {
    4875               0 :             GByte* pBuf = (GByte*)VSIMalloc(nSize);
    4876               0 :             if( pBuf == NULL )
    4877               0 :                 return CE_Failure;
    4878               0 :             for(int j=0;j<nBufYSize;j++)
    4879                 :             {
    4880                 :                 GDALCopyWords( (GByte*)pData + j * nLineSpace,
    4881                 :                                eBufType, nPixelSpace,
    4882                 :                                pBuf + j * nBufXSize * nDataTypeSize,
    4883                 :                                eBufType, nDataTypeSize,
    4884               0 :                                nBufXSize );
    4885                 :             }
    4886               0 :             if( !GDALPipeWrite(p, nSize, pBuf) )
    4887                 :             {
    4888               0 :                 VSIFree(pBuf);
    4889               0 :                 return CE_Failure;
    4890                 :             }
    4891               0 :             VSIFree(pBuf);
    4892                 :         }
    4893                 : 
    4894               3 :         if( !GDALSkipUntilEndOfJunkMarker(p) )
    4895               0 :             return CE_Failure;
    4896               3 :         if( !GDALPipeRead(p, &eRet) )
    4897               0 :             return eRet;
    4898                 : 
    4899               3 :         GDALConsumeErrors(p);
    4900               3 :         return eRet;
    4901                 :     }
    4902                 : }
    4903                 : 
    4904                 : /************************************************************************/
    4905                 : /*                       HasArbitraryOverviews()                        */
    4906                 : /************************************************************************/
    4907                 : 
    4908               3 : int GDALClientRasterBand::HasArbitraryOverviews()
    4909                 : {
    4910               3 :     if( !SupportsInstr(INSTR_Band_HasArbitraryOverviews) )
    4911               0 :         return GDALPamRasterBand::HasArbitraryOverviews();
    4912                 : 
    4913                 :     CLIENT_ENTER();
    4914               3 :     if( !WriteInstr(INSTR_Band_HasArbitraryOverviews) )
    4915               0 :         return 0;
    4916               3 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4917               0 :         return 0;
    4918                 : 
    4919                 :     int nInt;
    4920               3 :     if( !GDALPipeRead(p, &nInt) )
    4921               0 :         return 0;
    4922               3 :     GDALConsumeErrors(p);
    4923               3 :     return nInt;
    4924                 : }
    4925                 : 
    4926                 : /************************************************************************/
    4927                 : /*                          GetOverviewCount()                          */
    4928                 : /************************************************************************/
    4929                 : 
    4930               8 : int GDALClientRasterBand::GetOverviewCount()
    4931                 : {
    4932               8 :     if( !SupportsInstr(INSTR_Band_GetOverviewCount) )
    4933               0 :         return GDALPamRasterBand::GetOverviewCount();
    4934                 : 
    4935                 :     CLIENT_ENTER();
    4936               8 :     if( !WriteInstr(INSTR_Band_GetOverviewCount) )
    4937               0 :         return 0;
    4938               8 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4939               0 :         return 0;
    4940                 : 
    4941                 :     int nInt;
    4942               8 :     if( !GDALPipeRead(p, &nInt) )
    4943               0 :         return 0;
    4944               8 :     GDALConsumeErrors(p);
    4945               8 :     return nInt;
    4946                 : }
    4947                 : 
    4948                 : /************************************************************************/
    4949                 : /*                             GetDouble()                              */
    4950                 : /************************************************************************/
    4951                 : 
    4952              57 : double GDALClientRasterBand::GetDouble( InstrEnum instr, int *pbSuccess )
    4953                 : {
    4954              57 :     if( pbSuccess ) *pbSuccess = FALSE;
    4955              57 :     if( !WriteInstr( instr) )
    4956               0 :         return 0;
    4957              57 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    4958               0 :         return 0;
    4959                 : 
    4960                 :     int bSuccess;
    4961                 :     double dfRet;
    4962              57 :     if( !GDALPipeRead(p, &bSuccess) ||
    4963                 :         !GDALPipeRead(p, &dfRet) )
    4964               0 :         return 0;
    4965              57 :     if( pbSuccess )
    4966              53 :         *pbSuccess = bSuccess;
    4967              57 :     GDALConsumeErrors(p);
    4968              57 :     return dfRet;
    4969                 : }
    4970                 : 
    4971                 : /************************************************************************/
    4972                 : /*                           GetNoDataValue()                           */
    4973                 : /************************************************************************/
    4974                 : 
    4975              16 : double GDALClientRasterBand::GetNoDataValue( int *pbSuccess )
    4976                 : {
    4977              16 :     if( !SupportsInstr(INSTR_Band_GetNoDataValue) )
    4978               0 :         return GDALPamRasterBand::GetNoDataValue(pbSuccess);
    4979                 : 
    4980                 :     CLIENT_ENTER();
    4981              16 :     return GetDouble(INSTR_Band_GetNoDataValue, pbSuccess);
    4982                 : }
    4983                 : 
    4984                 : /************************************************************************/
    4985                 : /*                             GetMaximum()                             */
    4986                 : /************************************************************************/
    4987                 : 
    4988               3 : double GDALClientRasterBand::GetMaximum( int *pbSuccess )
    4989                 : {
    4990               3 :     if( !SupportsInstr(INSTR_Band_GetMaximum) )
    4991               0 :         return GDALPamRasterBand::GetMaximum(pbSuccess);
    4992                 : 
    4993                 :     CLIENT_ENTER();
    4994               3 :     return GetDouble(INSTR_Band_GetMaximum, pbSuccess);
    4995                 : }
    4996                 : 
    4997                 : /************************************************************************/
    4998                 : /*                             GetMinimum()                             */
    4999                 : /************************************************************************/
    5000                 : 
    5001               6 : double GDALClientRasterBand::GetMinimum( int *pbSuccess )
    5002                 : {
    5003               6 :     if( !SupportsInstr(INSTR_Band_GetMinimum) )
    5004               0 :         return GDALPamRasterBand::GetMinimum(pbSuccess);
    5005                 : 
    5006                 :     CLIENT_ENTER();
    5007               6 :     return GetDouble(INSTR_Band_GetMinimum, pbSuccess);
    5008                 : }
    5009                 : 
    5010                 : /************************************************************************/
    5011                 : /*                             GetOffset()                              */
    5012                 : /************************************************************************/
    5013                 : 
    5014              16 : double GDALClientRasterBand::GetOffset( int *pbSuccess )
    5015                 : {
    5016              16 :     if( !SupportsInstr(INSTR_Band_GetOffset) )
    5017               0 :         return GDALPamRasterBand::GetOffset(pbSuccess);
    5018                 : 
    5019                 :     CLIENT_ENTER();
    5020              16 :     return GetDouble(INSTR_Band_GetOffset, pbSuccess);
    5021                 : }
    5022                 : 
    5023                 : /************************************************************************/
    5024                 : /*                              GetScale()                              */
    5025                 : /************************************************************************/
    5026                 : 
    5027              16 : double GDALClientRasterBand::GetScale( int *pbSuccess )
    5028                 : {
    5029              16 :     if( !SupportsInstr(INSTR_Band_GetScale) )
    5030               0 :         return GDALPamRasterBand::GetScale(pbSuccess);
    5031                 : 
    5032                 :     CLIENT_ENTER();
    5033              16 :     return GetDouble(INSTR_Band_GetScale, pbSuccess);
    5034                 : }
    5035                 : 
    5036                 : /************************************************************************/
    5037                 : /*                           GetColorTable()                            */
    5038                 : /************************************************************************/
    5039                 : 
    5040              26 : GDALColorTable *GDALClientRasterBand::GetColorTable()
    5041                 : {
    5042              26 :     if( !SupportsInstr(INSTR_Band_GetColorTable) )
    5043               0 :         return GDALPamRasterBand::GetColorTable();
    5044                 : 
    5045                 :     CLIENT_ENTER();
    5046              26 :     if( !WriteInstr(INSTR_Band_GetColorTable) )
    5047               0 :         return NULL;
    5048              26 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    5049               0 :         return NULL;
    5050                 : 
    5051              26 :     GDALColorTable* poNewColorTable = NULL;
    5052              26 :     if( !GDALPipeRead(p, &poNewColorTable) )
    5053               0 :         return NULL;
    5054                 : 
    5055              26 :     if( poNewColorTable != NULL && poColorTable != NULL )
    5056                 :     {
    5057               0 :         *poColorTable = *poNewColorTable;
    5058               0 :         delete poNewColorTable;
    5059                 :     }
    5060              29 :     else if( poNewColorTable != NULL && poColorTable == NULL )
    5061                 :     {
    5062               3 :         poColorTable = poNewColorTable;
    5063                 :     }
    5064              23 :     else if( poColorTable != NULL )
    5065                 :     {
    5066               0 :         delete poColorTable;
    5067               0 :         poColorTable = NULL;
    5068                 :     }
    5069                 : 
    5070              26 :     GDALConsumeErrors(p);
    5071              26 :     return poColorTable;
    5072                 : }
    5073                 : 
    5074                 : /************************************************************************/
    5075                 : /*                            GetUnitType()                             */
    5076                 : /************************************************************************/
    5077                 : 
    5078              13 : const char *GDALClientRasterBand::GetUnitType()
    5079                 : {
    5080              13 :     if( !SupportsInstr(INSTR_Band_GetUnitType) )
    5081               0 :         return GDALPamRasterBand::GetUnitType();
    5082                 : 
    5083                 :     CLIENT_ENTER();
    5084              13 :     if( !WriteInstr(INSTR_Band_GetUnitType) )
    5085               0 :         return "";
    5086              13 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    5087               0 :         return "";
    5088                 : 
    5089              13 :     CPLFree(pszUnitType);
    5090              13 :     pszUnitType = NULL;
    5091              13 :     if( !GDALPipeRead(p, &pszUnitType) )
    5092               0 :         return "";
    5093              13 :     GDALConsumeErrors(p);
    5094              13 :     return pszUnitType ? pszUnitType : "";
    5095                 : }
    5096                 : 
    5097                 : /************************************************************************/
    5098                 : /*                            SetUnitType()                             */
    5099                 : /************************************************************************/
    5100                 : 
    5101               3 : CPLErr GDALClientRasterBand::SetUnitType( const char * pszUnit )
    5102                 : {
    5103               3 :     if( !SupportsInstr(INSTR_Band_SetUnitType) )
    5104               0 :         return GDALPamRasterBand::SetUnitType(pszUnit);
    5105                 : 
    5106                 :     CLIENT_ENTER();
    5107               3 :     if( !WriteInstr(INSTR_Band_SetUnitType) ||
    5108                 :         !GDALPipeWrite(p, pszUnit) )
    5109               0 :         return CE_Failure;
    5110               3 :     return CPLErrOnlyRet(p);
    5111                 : }
    5112                 : /************************************************************************/
    5113                 : /*                           SetColorTable()                            */
    5114                 : /************************************************************************/
    5115                 : 
    5116               3 : CPLErr GDALClientRasterBand::SetColorTable(GDALColorTable* poColorTable)
    5117                 : {
    5118               3 :     if( !SupportsInstr(INSTR_Band_SetColorTable) )
    5119               0 :         return GDALPamRasterBand::SetColorTable(poColorTable);
    5120                 : 
    5121                 :     CLIENT_ENTER();
    5122               3 :     if( !WriteInstr(INSTR_Band_SetColorTable) )
    5123               0 :         return CE_Failure;
    5124               3 :     if( !GDALPipeWrite(p, poColorTable) )
    5125               0 :         return CE_Failure;
    5126               3 :     return CPLErrOnlyRet(p);
    5127                 : }
    5128                 : 
    5129                 : /************************************************************************/
    5130                 : /*                              SetDouble()                             */
    5131                 : /************************************************************************/
    5132                 : 
    5133               9 : CPLErr GDALClientRasterBand::SetDouble( InstrEnum instr, double dfVal )
    5134                 : {
    5135               9 :     if( !WriteInstr(instr) ||
    5136                 :         !GDALPipeWrite(p, dfVal) )
    5137               0 :         return CE_Failure;
    5138               9 :     return CPLErrOnlyRet(p);
    5139                 : }
    5140                 : 
    5141                 : /************************************************************************/
    5142                 : /*                           SetNoDataValue()                           */
    5143                 : /************************************************************************/
    5144                 : 
    5145               3 : CPLErr GDALClientRasterBand::SetNoDataValue( double dfVal )
    5146                 : {
    5147               3 :     if( !SupportsInstr(INSTR_Band_SetNoDataValue) )
    5148               0 :         return GDALPamRasterBand::SetNoDataValue(dfVal);
    5149                 : 
    5150                 :     CLIENT_ENTER();
    5151               3 :     return SetDouble(INSTR_Band_SetNoDataValue, dfVal);
    5152                 : }
    5153                 : 
    5154                 : /************************************************************************/
    5155                 : /*                             SetScale()                               */
    5156                 : /************************************************************************/
    5157                 : 
    5158               3 : CPLErr GDALClientRasterBand::SetScale( double dfVal )
    5159                 : {
    5160               3 :     if( !SupportsInstr(INSTR_Band_SetScale) )
    5161               0 :         return GDALPamRasterBand::SetScale(dfVal);
    5162                 : 
    5163                 :     CLIENT_ENTER();
    5164               3 :     return SetDouble(INSTR_Band_SetScale, dfVal);
    5165                 : }
    5166                 : 
    5167                 : /************************************************************************/
    5168                 : /*                             SetOffset()                              */
    5169                 : /************************************************************************/
    5170                 : 
    5171               3 : CPLErr GDALClientRasterBand::SetOffset( double dfVal )
    5172                 : {
    5173               3 :     if( !SupportsInstr(INSTR_Band_SetOffset) )
    5174               0 :         return GDALPamRasterBand::SetOffset(dfVal);
    5175                 : 
    5176                 :     CLIENT_ENTER();
    5177               3 :     return SetDouble(INSTR_Band_SetOffset, dfVal);
    5178                 : }
    5179                 : 
    5180                 : /************************************************************************/
    5181                 : /*                            GetOverview()                             */
    5182                 : /************************************************************************/
    5183                 : 
    5184               6 : GDALRasterBand *GDALClientRasterBand::GetOverview(int iOverview)
    5185                 : {
    5186               6 :     if( !SupportsInstr(INSTR_Band_GetOverview) )
    5187               0 :         return GDALPamRasterBand::GetOverview(iOverview);
    5188                 : 
    5189                 :     CLIENT_ENTER();
    5190                 :     std::map<int, GDALRasterBand*>::iterator oIter =
    5191               6 :         aMapOvrBandsCurrent.find(iOverview);
    5192               6 :     if( oIter != aMapOvrBandsCurrent.end() )
    5193               0 :         return oIter->second;
    5194                 : 
    5195               6 :     if( !WriteInstr(INSTR_Band_GetOverview) ||
    5196                 :         !GDALPipeWrite(p, iOverview) )
    5197               0 :         return NULL;
    5198                 : 
    5199               6 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    5200               0 :         return NULL;
    5201                 :     
    5202               6 :     GDALRasterBand* poBand = NULL;
    5203               6 :     if( !GDALPipeRead(p, (GDALClientDataset*) NULL, &poBand, abyCaps) )
    5204               0 :         return NULL;
    5205                 : 
    5206               6 :     GDALConsumeErrors(p);
    5207                 : 
    5208               6 :     aMapOvrBands[iOverview] = poBand;
    5209               6 :     aMapOvrBandsCurrent[iOverview] = poBand;
    5210               6 :     return poBand;
    5211                 : }
    5212                 : 
    5213                 : /************************************************************************/
    5214                 : /*                            GetMaskBand()                             */
    5215                 : /************************************************************************/
    5216                 : 
    5217               6 : GDALRasterBand *GDALClientRasterBand::GetMaskBand()
    5218                 : {
    5219               6 :     if( !SupportsInstr(INSTR_Band_GetMaskBand) )
    5220               0 :         return GDALPamRasterBand::GetMaskBand();
    5221                 : 
    5222                 :     CLIENT_ENTER();
    5223               6 :     if( poMaskBand )
    5224               3 :         return poMaskBand;
    5225                 : 
    5226               3 :     if( !WriteInstr(INSTR_Band_GetMaskBand) )
    5227               0 :         return CreateFakeMaskBand();
    5228                 : 
    5229               3 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    5230               0 :         return CreateFakeMaskBand();
    5231                 : 
    5232               3 :     GDALRasterBand* poBand = NULL;
    5233               3 :     if( !GDALPipeRead(p, (GDALClientDataset*) NULL, &poBand, abyCaps) )
    5234               0 :         return CreateFakeMaskBand();
    5235                 : 
    5236               3 :     GDALConsumeErrors(p);
    5237                 : 
    5238               3 :     poMaskBand = poBand;
    5239               3 :     return poMaskBand;
    5240                 : }
    5241                 : 
    5242                 : /************************************************************************/
    5243                 : /*                            GetMaskFlags()                            */
    5244                 : /************************************************************************/
    5245                 : 
    5246              21 : int GDALClientRasterBand::GetMaskFlags()
    5247                 : {
    5248              21 :     if( !SupportsInstr(INSTR_Band_GetMaskFlags) )
    5249               0 :         return GDALPamRasterBand::GetMaskFlags();
    5250                 : 
    5251                 :     CLIENT_ENTER();
    5252              21 :     if( !WriteInstr(INSTR_Band_GetMaskFlags) )
    5253               0 :         return 0;
    5254              21 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    5255               0 :         return 0;
    5256                 :     int nFlags;
    5257              21 :     if( !GDALPipeRead(p, &nFlags) )
    5258               0 :         return 0;
    5259              21 :     GDALConsumeErrors(p);
    5260              21 :     return nFlags;
    5261                 : }
    5262                 : 
    5263                 : /************************************************************************/
    5264                 : /*                           CreateMaskBand()                           */
    5265                 : /************************************************************************/
    5266                 : 
    5267               0 : CPLErr GDALClientRasterBand::CreateMaskBand( int nFlags )
    5268                 : {
    5269               0 :     if( !SupportsInstr(INSTR_Band_CreateMaskBand) )
    5270               0 :         return GDALPamRasterBand::CreateMaskBand(nFlags);
    5271                 : 
    5272                 :     CLIENT_ENTER();
    5273               0 :     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK_TO_8BIT", bRecycleChild);
    5274               0 :     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK", bRecycleChild);
    5275               0 :     if( !WriteInstr(INSTR_Band_CreateMaskBand) ||
    5276                 :         !GDALPipeWrite(p, nFlags) )
    5277               0 :         return CE_Failure;
    5278               0 :     CPLErr eErr = CPLErrOnlyRet(p);
    5279               0 :     if( eErr == CE_None && poMaskBand != NULL )
    5280                 :     {
    5281               0 :         apoOldMaskBands.push_back(poMaskBand);
    5282               0 :         poMaskBand = NULL;
    5283                 :     }
    5284               0 :     return eErr;
    5285                 : }
    5286                 : 
    5287                 : /************************************************************************/
    5288                 : /*                                Fill()                                */
    5289                 : /************************************************************************/
    5290                 : 
    5291               6 : CPLErr GDALClientRasterBand::Fill(double dfRealValue, double dfImaginaryValue)
    5292                 : {
    5293               6 :     if( !SupportsInstr(INSTR_Band_Fill) )
    5294               0 :         return GDALPamRasterBand::Fill(dfRealValue, dfImaginaryValue);
    5295                 : 
    5296               6 :     InvalidateCachedLines();
    5297                 : 
    5298                 :     CLIENT_ENTER();
    5299               6 :     if( !WriteInstr(INSTR_Band_Fill) ||
    5300                 :         !GDALPipeWrite(p, dfRealValue) ||
    5301                 :         !GDALPipeWrite(p, dfImaginaryValue) )
    5302               0 :         return CE_Failure;
    5303               6 :     return CPLErrOnlyRet(p);
    5304                 : }
    5305                 : 
    5306                 : /************************************************************************/
    5307                 : /*                           BuildOverviews()                           */
    5308                 : /************************************************************************/
    5309                 : 
    5310               0 : CPLErr GDALClientRasterBand::BuildOverviews( const char * pszResampling,
    5311                 :                                              int nOverviews,
    5312                 :                                              int * panOverviewList,
    5313                 :                                              GDALProgressFunc pfnProgress,
    5314                 :                                              void * pProgressData )
    5315                 : {
    5316               0 :     if( !SupportsInstr(INSTR_Band_BuildOverviews) )
    5317                 :         return GDALPamRasterBand::BuildOverviews(pszResampling, nOverviews, panOverviewList,
    5318               0 :                                                  pfnProgress, pProgressData);
    5319                 : 
    5320               0 :     InvalidateCachedLines();
    5321                 : 
    5322                 :     CLIENT_ENTER();
    5323               0 :     if( !WriteInstr(INSTR_Band_BuildOverviews) ||
    5324                 :         !GDALPipeWrite(p, pszResampling) ||
    5325                 :         !GDALPipeWrite(p, nOverviews) ||
    5326                 :         !GDALPipeWrite(p, nOverviews * sizeof(int), panOverviewList) )
    5327               0 :         return CE_Failure;
    5328               0 :     return CPLErrOnlyRet(p);
    5329                 : }
    5330                 : 
    5331                 : /************************************************************************/
    5332                 : /*                           GetDefaultRAT()                            */
    5333                 : /************************************************************************/
    5334                 : 
    5335               8 : const GDALRasterAttributeTable *GDALClientRasterBand::GetDefaultRAT()
    5336                 : {
    5337               8 :     if( !SupportsInstr(INSTR_Band_GetDefaultRAT) )
    5338               0 :         return GDALPamRasterBand::GetDefaultRAT();
    5339                 : 
    5340                 :     CLIENT_ENTER();
    5341               8 :     if( !WriteInstr(INSTR_Band_GetDefaultRAT) )
    5342               0 :         return NULL;
    5343               8 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    5344               0 :         return NULL;
    5345                 : 
    5346               8 :     GDALRasterAttributeTable* poNewRAT = NULL;
    5347               8 :     if( !GDALPipeRead(p, &poNewRAT) )
    5348               0 :         return NULL;
    5349                 :     
    5350               8 :     if( poNewRAT != NULL && poRAT != NULL )
    5351                 :     {
    5352               0 :         *poRAT = *poNewRAT;
    5353               0 :         delete poNewRAT;
    5354                 :     }
    5355               8 :     else if( poNewRAT != NULL && poRAT == NULL )
    5356                 :     {
    5357               0 :         poRAT = poNewRAT;
    5358                 :     }
    5359               8 :     else if( poRAT != NULL )
    5360                 :     {
    5361               0 :         delete poRAT;
    5362               0 :         poRAT = NULL;
    5363                 :     }
    5364                 : 
    5365               8 :     GDALConsumeErrors(p);
    5366               8 :     return poRAT;
    5367                 : }
    5368                 : 
    5369                 : /************************************************************************/
    5370                 : /*                           SetDefaultRAT()                            */
    5371                 : /************************************************************************/
    5372                 : 
    5373               0 : CPLErr GDALClientRasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRAT )
    5374                 : {
    5375               0 :     if( !SupportsInstr(INSTR_Band_SetDefaultRAT) )
    5376               0 :         return GDALPamRasterBand::SetDefaultRAT(poRAT);
    5377                 : 
    5378                 :     CLIENT_ENTER();
    5379               0 :     if( !WriteInstr(INSTR_Band_SetDefaultRAT) ||
    5380                 :         !GDALPipeWrite(p, poRAT) )
    5381               0 :         return CE_Failure;
    5382               0 :     return CPLErrOnlyRet(p);
    5383                 : }
    5384                 : 
    5385                 : /************************************************************************/
    5386                 : /*                             AdviseRead()                             */
    5387                 : /************************************************************************/
    5388                 : 
    5389               0 : CPLErr GDALClientRasterBand::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
    5390                 :                                      int nBufXSize, int nBufYSize, 
    5391                 :                                      GDALDataType eDT, char **papszOptions )
    5392                 : {
    5393               0 :     if( !SupportsInstr(INSTR_Band_AdviseRead) )
    5394                 :         return GDALPamRasterBand::AdviseRead(nXOff, nYOff, nXSize, nYSize,
    5395                 :                                              nBufXSize, nBufYSize,
    5396               0 :                                              eDT, papszOptions);
    5397                 : 
    5398                 :     CLIENT_ENTER();
    5399               0 :     if( !WriteInstr(INSTR_Band_AdviseRead) ||
    5400                 :         !GDALPipeWrite(p, nXOff) ||
    5401                 :         !GDALPipeWrite(p, nYOff) ||
    5402                 :         !GDALPipeWrite(p, nXSize) ||
    5403                 :         !GDALPipeWrite(p, nYSize) ||
    5404                 :         !GDALPipeWrite(p, nBufXSize) ||
    5405                 :         !GDALPipeWrite(p, nBufYSize) ||
    5406                 :         !GDALPipeWrite(p, eDT) ||
    5407                 :         !GDALPipeWrite(p, papszOptions) )
    5408               0 :         return CE_Failure;
    5409               0 :     return CPLErrOnlyRet(p);
    5410                 : }
    5411                 : 
    5412                 : /************************************************************************/
    5413                 : /*                        CreateAndConnect()                            */
    5414                 : /************************************************************************/
    5415                 : 
    5416              18 : GDALClientDataset* GDALClientDataset::CreateAndConnect()
    5417                 : {
    5418              18 :     GDALServerSpawnedProcess* ssp = GDALServerSpawnAsync();
    5419              18 :     if( ssp == NULL )
    5420               0 :         return NULL;
    5421              18 :     return new GDALClientDataset(ssp);
    5422                 : }
    5423                 : 
    5424                 : /************************************************************************/
    5425                 : /*                                Init()                                */
    5426                 : /************************************************************************/
    5427                 : 
    5428              20 : int GDALClientDataset::Init(const char* pszFilename, GDALAccess eAccess)
    5429                 : {
    5430                 :     // FIXME find a way of transmitting the relevant config options to the forked Open() ?
    5431              20 :     GDALPipeWriteConfigOption(p, "GTIFF_POINT_GEO_IGNORE", bRecycleChild);
    5432              20 :     GDALPipeWriteConfigOption(p, "GDAL_TIFF_OVR_BLOCKSIZE", bRecycleChild);
    5433              20 :     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK_TO_8BIT", bRecycleChild);
    5434              20 :     GDALPipeWriteConfigOption(p, "GTIFF_LINEAR_UNITS", bRecycleChild);
    5435              20 :     GDALPipeWriteConfigOption(p, "GTIFF_IGNORE_READ_ERRORS", bRecycleChild);
    5436              20 :     GDALPipeWriteConfigOption(p, "GDAL_PDF_RENDERING_OPTIONS", bRecycleChild);
    5437              20 :     GDALPipeWriteConfigOption(p, "GDAL_PDF_DPI", bRecycleChild);
    5438              20 :     GDALPipeWriteConfigOption(p, "GDAL_PDF_LIB", bRecycleChild);
    5439              20 :     GDALPipeWriteConfigOption(p, "GDAL_PDF_LAYERS", bRecycleChild);
    5440              20 :     GDALPipeWriteConfigOption(p, "GDAL_PDF_LAYERS_OFF", bRecycleChild);
    5441              20 :     GDALPipeWriteConfigOption(p, "GDAL_JPEG_TO_RGB", bRecycleChild);
    5442              20 :     GDALPipeWriteConfigOption(p, "RPFTOC_FORCE_RGBA", bRecycleChild);
    5443              20 :     GDALPipeWriteConfigOption(p, "GDAL_NETCDF_BOTTOMUP", bRecycleChild);
    5444              20 :     GDALPipeWriteConfigOption(p, "OGR_SQLITE_SYNCHRONOUS", bRecycleChild);
    5445                 : 
    5446              20 :     char* pszCWD = CPLGetCurrentDir();
    5447                 : 
    5448              20 :     if( !GDALPipeWrite(p, INSTR_Open) ||
    5449                 :         !GDALPipeWrite(p, eAccess) ||
    5450                 :         !GDALPipeWrite(p, pszFilename) ||
    5451                 :         !GDALPipeWrite(p, pszCWD))
    5452                 :     {
    5453               0 :         CPLFree(pszCWD);
    5454               0 :         return FALSE;
    5455                 :     }
    5456              20 :     CPLFree(pszCWD);
    5457              20 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    5458               0 :         return FALSE;
    5459              20 :     int bRet = FALSE;
    5460              20 :     if( !GDALPipeRead(p, &bRet) )
    5461               0 :         return FALSE;
    5462                 : 
    5463              20 :     if( bRet == FALSE )
    5464                 :     {
    5465               0 :         GDALConsumeErrors(p);
    5466               0 :         return FALSE;
    5467                 :     }
    5468                 : 
    5469              20 :     if( !GDALPipeRead(p, sizeof(abyCaps), abyCaps) )
    5470               0 :         return FALSE;
    5471                 : 
    5472              20 :     this->eAccess = eAccess;
    5473                 : 
    5474              20 :     char* pszDescription = NULL;
    5475              20 :     if( !GDALPipeRead(p, &pszDescription) )
    5476               0 :         return FALSE;
    5477              20 :     if( pszDescription != NULL )
    5478              20 :         SetDescription(pszDescription);
    5479              20 :     CPLFree(pszDescription);
    5480                 : 
    5481              20 :     char* pszDriverName = NULL;
    5482              20 :     if( !GDALPipeRead(p, &pszDriverName) )
    5483               0 :         return FALSE;
    5484                 : 
    5485              20 :     if( pszDriverName != NULL )
    5486                 :     {
    5487              20 :         bFreeDriver = TRUE;
    5488              20 :         poDriver = new GDALDriver();
    5489              20 :         poDriver->SetDescription(pszDriverName);
    5490              20 :         CPLFree(pszDriverName);
    5491              20 :         pszDriverName = NULL;
    5492                 : 
    5493             200 :         while(TRUE)
    5494                 :         {
    5495             220 :             char* pszKey = NULL, *pszVal = NULL;
    5496             220 :             if( !GDALPipeRead(p, &pszKey) )
    5497               0 :                 return FALSE;
    5498             220 :             if( pszKey == NULL )
    5499              20 :                 break;
    5500             200 :             if( !GDALPipeRead(p, &pszVal) )
    5501                 :             {
    5502               0 :                 CPLFree(pszKey);
    5503               0 :                 CPLFree(pszVal);
    5504               0 :                 return FALSE;
    5505                 :             }
    5506             200 :             poDriver->SetMetadataItem( pszKey, pszVal );
    5507             200 :             CPLFree(pszKey);
    5508             200 :             CPLFree(pszVal);
    5509                 :         }
    5510                 :     }
    5511              20 :     CPLFree(pszDriverName);
    5512                 : 
    5513                 :     int bAllSame;
    5514              20 :     if( !GDALPipeRead(p, &nRasterXSize) ||
    5515                 :         !GDALPipeRead(p, &nRasterYSize) ||
    5516                 :         !GDALPipeRead(p, &nBands) ||
    5517                 :         !GDALPipeRead(p, &bAllSame) )
    5518               0 :         return FALSE;
    5519                 : 
    5520              46 :     for(int i=0;i<nBands;i++)
    5521                 :     {
    5522              26 :         GDALRasterBand* poBand = NULL;
    5523              32 :         if( i > 0 && bAllSame )
    5524                 :         {
    5525               6 :             GDALClientRasterBand* poFirstBand = (GDALClientRasterBand*) GetRasterBand(1);
    5526                 :             int nBlockXSize, nBlockYSize;
    5527               6 :             poFirstBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
    5528                 :             poBand = new GDALClientRasterBand(p, poFirstBand->GetSrvBand() + i,
    5529                 :                                               this, i + 1, poFirstBand->GetAccess(),
    5530                 :                                               poFirstBand->GetXSize(),
    5531                 :                                               poFirstBand->GetYSize(),
    5532                 :                                               poFirstBand->GetRasterDataType(),
    5533                 :                                               nBlockXSize, nBlockYSize,
    5534               6 :                                               abyCaps);
    5535                 :         }
    5536                 :         else
    5537                 :         {
    5538              20 :             if( !GDALPipeRead(p, this, &poBand, abyCaps) )
    5539               0 :                 return FALSE;
    5540              20 :             if( poBand == NULL )
    5541               0 :                 return FALSE;
    5542                 :         }
    5543                 : 
    5544              26 :         SetBand(i+1, poBand);
    5545                 :     }
    5546                 : 
    5547              20 :     GDALConsumeErrors(p);
    5548                 : 
    5549              20 :     return TRUE;
    5550                 : }
    5551                 : 
    5552                 : /************************************************************************/
    5553                 : /*                     GDALClientDatasetGetFilename()                   */
    5554                 : /************************************************************************/
    5555                 : 
    5556               0 : static int IsSeparateExecutable()
    5557                 : {
    5558                 : #ifdef WIN32
    5559                 :     return TRUE;
    5560                 : #else
    5561               0 :     const char* pszSpawnServer = CPLGetConfigOption("GDAL_API_PROXY_SERVER", "NO");
    5562               0 :     if( EQUAL(pszSpawnServer, "NO") || EQUAL(pszSpawnServer, "OFF") ||
    5563                 :         EQUAL(pszSpawnServer, "FALSE")  || EQUAL(pszSpawnServer, "0") )
    5564               0 :         return FALSE;
    5565                 :     else
    5566               0 :         return TRUE;
    5567                 : #endif
    5568                 : }
    5569                 : 
    5570           29768 : const char* GDALClientDatasetGetFilename(const char* pszFilename)
    5571                 : {
    5572                 :     const char* pszSpawn;
    5573           29768 :     if( EQUALN(pszFilename, "API_PROXY:", strlen("API_PROXY:")) )
    5574                 :     {
    5575               0 :         pszFilename += strlen("API_PROXY:");
    5576               0 :         pszSpawn = "YES";
    5577                 :     }
    5578                 :     else
    5579                 :     {
    5580           29768 :         pszSpawn = CPLGetConfigOption("GDAL_API_PROXY", "NO");
    5581           29768 :         if( EQUAL(pszSpawn, "NO") || EQUAL(pszSpawn, "OFF") ||
    5582                 :             EQUAL(pszSpawn, "FALSE") || EQUAL(pszSpawn, "0") )
    5583                 :         {
    5584           29747 :             return NULL;
    5585                 :         }
    5586                 :     }
    5587                 : 
    5588                 :     /* Those datasets cannot work in a multi-process context */
    5589                 :      /* /vsistdin/ and /vsistdout/ can work on Unix in the fork() only context (i.e. GDAL_API_PROXY_SERVER undefined) */
    5590                 :      /* since the forked process will inherit the same descriptors as the parent */
    5591                 : 
    5592              21 :     if( EQUALN(pszFilename, "MEM:::", 6) ||
    5593                 :         strstr(pszFilename, "/vsimem/") != NULL ||
    5594                 :         strstr(pszFilename, "/vsimem\\") != NULL ||
    5595                 :         (strstr(pszFilename, "/vsistdout/") != NULL && IsSeparateExecutable()) ||
    5596                 :         (strstr(pszFilename, "/vsistdin/") != NULL && IsSeparateExecutable()) ||
    5597                 :         EQUALN(pszFilename,"NUMPY:::",8) )
    5598               0 :         return NULL;
    5599                 : 
    5600              21 :     if( !(EQUAL(pszSpawn, "YES") || EQUAL(pszSpawn, "ON") ||
    5601                 :           EQUAL(pszSpawn, "TRUE") || EQUAL(pszSpawn, "1")) )
    5602                 :     {
    5603               0 :         CPLString osExt(CPLGetExtension(pszFilename));
    5604                 : 
    5605                 :         /* If the file extension is listed in the GDAL_API_PROXY, then */
    5606                 :         /* we have a match */
    5607               0 :         char** papszTokens = CSLTokenizeString2( pszSpawn, " ,", CSLT_HONOURSTRINGS );
    5608               0 :         if( CSLFindString(papszTokens, osExt) >= 0 )
    5609                 :         {
    5610               0 :             CSLDestroy(papszTokens);
    5611               0 :             return pszFilename;
    5612                 :         }
    5613                 : 
    5614                 :         /* Otherwise let's suppose that driver names are listed in GDAL_API_PROXY */
    5615                 :         /* and check if the file extension matches the extension declared by the */
    5616                 :         /* driver */
    5617               0 :         char** papszIter = papszTokens;
    5618               0 :         while( *papszIter != NULL )
    5619                 :         {
    5620               0 :             GDALDriverH hDriver = GDALGetDriverByName(*papszIter);
    5621               0 :             if( hDriver != NULL )
    5622                 :             {
    5623                 :                 const char* pszDriverExt =
    5624               0 :                     GDALGetMetadataItem(hDriver, GDAL_DMD_EXTENSION, NULL);
    5625               0 :                 if( pszDriverExt != NULL && EQUAL(pszDriverExt, osExt) )
    5626                 :                 {
    5627               0 :                     CSLDestroy(papszTokens);
    5628               0 :                     return pszFilename;
    5629                 :                 }
    5630                 :             }
    5631               0 :             papszIter++;
    5632                 :         }
    5633               0 :         CSLDestroy(papszTokens);
    5634               0 :         return NULL;
    5635                 :     }
    5636                 : 
    5637              21 :     return pszFilename;
    5638                 : }
    5639                 : 
    5640                 : /************************************************************************/
    5641                 : /*                                Open()                                */
    5642                 : /************************************************************************/
    5643                 : 
    5644            9021 : GDALDataset *GDALClientDataset::Open( GDALOpenInfo * poOpenInfo )
    5645                 : {
    5646                 :     const char* pszFilename =
    5647            9021 :         GDALClientDatasetGetFilename(poOpenInfo->pszFilename);
    5648            9021 :     if( pszFilename == NULL )
    5649            9009 :         return NULL;
    5650                 : 
    5651                 :     CLIENT_ENTER();
    5652                 : 
    5653              12 :     GDALClientDataset* poDS = CreateAndConnect();
    5654              12 :     if( poDS == NULL )
    5655               0 :         return NULL;
    5656                 : 
    5657              12 :     CPLErrorReset();
    5658              12 :     if( !poDS->Init(pszFilename, poOpenInfo->eAccess) )
    5659                 :     {
    5660               0 :         if( CPLGetLastErrorType() == 0 )
    5661                 :         {
    5662                 :             CPLError(CE_Failure, CPLE_AppDefined, "Could not open %s",
    5663               0 :                     pszFilename);
    5664                 :         }
    5665               0 :         delete poDS;
    5666               0 :         return NULL;
    5667                 :     }
    5668              12 :     if( poDS != NULL )
    5669              12 :         CPLErrorReset();
    5670                 : 
    5671              12 :     return poDS;
    5672                 : }
    5673                 : 
    5674                 : /************************************************************************/
    5675                 : /*                              Identify()                              */
    5676                 : /************************************************************************/
    5677                 : 
    5678           10388 : int GDALClientDataset::Identify( GDALOpenInfo * poOpenInfo )
    5679                 : {
    5680                 :     const char* pszFilename =
    5681           10388 :         GDALClientDatasetGetFilename(poOpenInfo->pszFilename);
    5682           10388 :     if( pszFilename == NULL )
    5683           10385 :         return FALSE;
    5684                 : 
    5685                 :     CLIENT_ENTER();
    5686                 : 
    5687               3 :     GDALServerSpawnedProcess* ssp = GDALServerSpawnAsync();
    5688               3 :     if( ssp == NULL )
    5689               0 :         return FALSE;
    5690                 : 
    5691               3 :     char* pszCWD = CPLGetCurrentDir();
    5692                 : 
    5693               3 :     GDALPipe* p = ssp->p;
    5694               3 :     if( !GDALPipeWrite(p, INSTR_Identify) ||
    5695                 :         !GDALPipeWrite(p, pszFilename) ||
    5696                 :         !GDALPipeWrite(p, pszCWD) ||
    5697                 :         !GDALSkipUntilEndOfJunkMarker(p) )
    5698                 :     {
    5699               0 :         GDALServerSpawnAsyncFinish(ssp);
    5700               0 :         CPLFree(pszCWD);
    5701               0 :         return FALSE;
    5702                 :     }
    5703                 : 
    5704               3 :     CPLFree(pszCWD);
    5705                 : 
    5706                 :     int bRet;
    5707               3 :     if( !GDALPipeRead(p, &bRet) )
    5708                 :     {
    5709               0 :         GDALServerSpawnAsyncFinish(ssp);
    5710               0 :         return FALSE;
    5711                 :     }
    5712                 : 
    5713               3 :     GDALServerSpawnAsyncFinish(ssp);
    5714               3 :     return bRet;
    5715                 : }
    5716                 : 
    5717                 : /************************************************************************/
    5718                 : /*                     GDALClientDatasetQuietDelete()                   */
    5719                 : /************************************************************************/
    5720                 : 
    5721               6 : static int GDALClientDatasetQuietDelete(GDALPipe* p,
    5722                 :                                     const char* pszFilename)
    5723                 : {
    5724               6 :     char* pszCWD = CPLGetCurrentDir();
    5725               6 :     if( !GDALPipeWrite(p, INSTR_QuietDelete) ||
    5726                 :         !GDALPipeWrite(p, pszFilename) ||
    5727                 :         !GDALPipeWrite(p, pszCWD) ||
    5728                 :         !GDALSkipUntilEndOfJunkMarker(p) )
    5729                 :     {
    5730               0 :         CPLFree(pszCWD);
    5731               0 :         return FALSE;
    5732                 :     }
    5733               6 :     CPLFree(pszCWD);
    5734               6 :     GDALConsumeErrors(p);
    5735               6 :     return TRUE;
    5736                 : }
    5737                 : 
    5738                 : /************************************************************************/
    5739                 : /*                          mCreateCopy()                               */
    5740                 : /************************************************************************/
    5741                 : 
    5742               3 : int GDALClientDataset::mCreateCopy( const char* pszFilename,
    5743                 :                                     GDALDataset* poSrcDS,
    5744                 :                                     int bStrict, char** papszOptions, 
    5745                 :                                     GDALProgressFunc pfnProgress,
    5746                 :                                     void * pProgressData )
    5747                 : {
    5748                 :     /*if( !SupportsInstr(INSTR_CreateCopy) )
    5749                 :     {
    5750                 :         CPLError(CE_Failure, CPLE_NotSupported, "CreateCopy() not supported by server");
    5751                 :         return FALSE;
    5752                 :     }*/
    5753                 : 
    5754                 :     const char* pszServerDriver =
    5755               3 :         CSLFetchNameValue(papszOptions, "SERVER_DRIVER");
    5756               3 :     if( pszServerDriver == NULL )
    5757                 :     {
    5758                 :         CPLError(CE_Failure, CPLE_AppDefined,
    5759               0 :                  "Creation options should contain a SERVER_DRIVER item");
    5760               0 :         return FALSE;
    5761                 :     }
    5762                 : 
    5763               3 :     if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) )
    5764                 :     {
    5765               3 :         if( !GDALClientDatasetQuietDelete(p, pszFilename) )
    5766               0 :             return FALSE;
    5767                 :     }
    5768                 : 
    5769               3 :     GDALPipeWriteConfigOption(p, "GTIFF_POINT_GEO_IGNORE", bRecycleChild);
    5770               3 :     GDALPipeWriteConfigOption(p, "GTIFF_DELETE_ON_ERROR", bRecycleChild);
    5771               3 :     GDALPipeWriteConfigOption(p, "ESRI_XML_PAM", bRecycleChild);
    5772               3 :     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK_TO_8BIT", bRecycleChild);
    5773               3 :     GDALPipeWriteConfigOption(p, "OGR_SQLITE_SYNCHRONOUS", bRecycleChild);
    5774               3 :     GDALPipeWriteConfigOption(p, "GDAL_PDF_WRITE_GEOREF_ON_IMAGE", bRecycleChild);
    5775               3 :     GDALPipeWriteConfigOption(p, "GDAL_PDF_OGC_BP_WRITE_WKT", bRecycleChild);
    5776                 : 
    5777               3 :     char* pszCWD = CPLGetCurrentDir();
    5778                 : 
    5779               6 :     if( !GDALPipeWrite(p, INSTR_CreateCopy) ||
    5780                 :         !GDALPipeWrite(p, pszFilename) ||
    5781               3 :         !GDALPipeWrite(p, poSrcDS->GetDescription()) ||
    5782                 :         !GDALPipeWrite(p, pszCWD) ||
    5783                 :         !GDALPipeWrite(p, bStrict) ||
    5784                 :         !GDALPipeWrite(p, papszOptions) )
    5785                 :     {
    5786               0 :         CPLFree(pszCWD);
    5787               0 :         return FALSE;
    5788                 :     }
    5789               3 :     CPLFree(pszCWD);
    5790                 : 
    5791                 :     int bDriverOK;
    5792               3 :     if( !GDALPipeRead(p, &bDriverOK) )
    5793               0 :         return FALSE;
    5794                 : 
    5795               3 :     if( !bDriverOK )
    5796                 :     {
    5797               0 :         GDALConsumeErrors(p);
    5798               0 :         return FALSE;
    5799                 :     }
    5800                 : 
    5801               3 :     if( GDALServerLoop(p,
    5802                 :                        poSrcDS,
    5803                 :                        pfnProgress, pProgressData) != 0 )
    5804                 :     {
    5805               0 :         GDALConsumeErrors(p);
    5806               0 :         return FALSE;
    5807                 :     }
    5808                 : 
    5809               3 :     GDALConsumeErrors(p);
    5810                 : 
    5811               3 :     return Init(NULL, GA_Update);
    5812                 : }
    5813                 : 
    5814                 : /************************************************************************/
    5815                 : /*                          CreateCopy()                                */
    5816                 : /************************************************************************/
    5817                 : 
    5818               3 : GDALDataset *GDALClientDataset::CreateCopy( const char * pszFilename, 
    5819                 :                                             GDALDataset * poSrcDS, int bStrict,
    5820                 :                                             char ** papszOptions, 
    5821                 :                                             GDALProgressFunc pfnProgress,
    5822                 :                                             void * pProgressData )
    5823                 : {
    5824                 :     CLIENT_ENTER();
    5825                 : 
    5826               3 :     GDALClientDataset* poDS = CreateAndConnect();
    5827               3 :     if( poDS !=NULL && !poDS->mCreateCopy(pszFilename, poSrcDS, bStrict,
    5828                 :                                           papszOptions,
    5829                 :                                           pfnProgress, pProgressData) )
    5830                 :     {
    5831               0 :         delete poDS;
    5832               0 :         return NULL;
    5833                 :     }
    5834                 : 
    5835               3 :     return poDS;
    5836                 : }
    5837                 : 
    5838                 : /************************************************************************/
    5839                 : /*                            mCreate()                                 */
    5840                 : /************************************************************************/
    5841                 : 
    5842               3 : int GDALClientDataset::mCreate( const char * pszFilename,
    5843                 :                             int nXSize, int nYSize, int nBands,
    5844                 :                             GDALDataType eType,
    5845                 :                             char ** papszOptions )
    5846                 : {
    5847                 :     /*if( !SupportsInstr(INSTR_Create) )
    5848                 :     {
    5849                 :         CPLError(CE_Failure, CPLE_NotSupported, "Create() not supported by server");
    5850                 :         return FALSE;
    5851                 :     }*/
    5852                 : 
    5853                 :     const char* pszServerDriver =
    5854               3 :         CSLFetchNameValue(papszOptions, "SERVER_DRIVER");
    5855               3 :     if( pszServerDriver == NULL )
    5856                 :     {
    5857                 :         CPLError(CE_Failure, CPLE_AppDefined,
    5858               0 :                  "Creation options should contain a SERVER_DRIVER item");
    5859               0 :         return FALSE;
    5860                 :     }
    5861                 : 
    5862               3 :     if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) )
    5863                 :     {
    5864               3 :         if( !GDALClientDatasetQuietDelete(p, pszFilename) )
    5865               0 :             return FALSE;
    5866                 :     }
    5867                 : 
    5868               3 :     GDALPipeWriteConfigOption(p,"GTIFF_POINT_GEO_IGNORE", bRecycleChild);
    5869               3 :     GDALPipeWriteConfigOption(p,"GTIFF_DELETE_ON_ERROR", bRecycleChild);
    5870               3 :     GDALPipeWriteConfigOption(p,"ESRI_XML_PAM", bRecycleChild);
    5871               3 :     GDALPipeWriteConfigOption(p,"GTIFF_DONT_WRITE_BLOCKS", bRecycleChild);
    5872                 : 
    5873               3 :     char* pszCWD = CPLGetCurrentDir();
    5874                 : 
    5875               3 :     if( !GDALPipeWrite(p, INSTR_Create) ||
    5876                 :         !GDALPipeWrite(p, pszFilename) ||
    5877                 :         !GDALPipeWrite(p, pszCWD) ||
    5878                 :         !GDALPipeWrite(p, nXSize) ||
    5879                 :         !GDALPipeWrite(p, nYSize) ||
    5880                 :         !GDALPipeWrite(p, nBands) ||
    5881                 :         !GDALPipeWrite(p, eType) ||
    5882                 :         !GDALPipeWrite(p, papszOptions) )
    5883                 :     {
    5884               0 :         CPLFree(pszCWD);
    5885               0 :         return FALSE;
    5886                 :     }
    5887               3 :     CPLFree(pszCWD);
    5888               3 :     if( !GDALSkipUntilEndOfJunkMarker(p) )
    5889               0 :         return FALSE;
    5890                 :     int bOK;
    5891               3 :     if( !GDALPipeRead(p, &bOK) )
    5892               0 :         return FALSE;
    5893                 : 
    5894               3 :     if( !bOK )
    5895                 :     {
    5896               0 :         GDALConsumeErrors(p);
    5897               0 :         return FALSE;
    5898                 :     }
    5899                 : 
    5900               3 :     GDALConsumeErrors(p);
    5901                 : 
    5902               3 :     return Init(NULL, GA_Update);
    5903                 : }
    5904                 : 
    5905                 : /************************************************************************/
    5906                 : /*                              Create()                                */
    5907                 : /************************************************************************/
    5908                 : 
    5909               3 : GDALDataset* GDALClientDataset::Create( const char * pszName,
    5910                 :                                     int nXSize, int nYSize, int nBands,
    5911                 :                                     GDALDataType eType,
    5912                 :                                     char ** papszOptions )
    5913                 : {
    5914                 :     CLIENT_ENTER();
    5915                 : 
    5916               3 :     GDALClientDataset* poDS = CreateAndConnect();
    5917               3 :     if( poDS != NULL && !poDS->mCreate(pszName, nXSize, nYSize, nBands,
    5918                 :                                        eType, papszOptions) )
    5919                 :     {
    5920               0 :         delete poDS;
    5921               0 :         return NULL;
    5922                 :     }
    5923                 : 
    5924               3 :     return poDS;
    5925                 : }
    5926                 : 
    5927                 : /************************************************************************/
    5928                 : /*                              Delete()                                */
    5929                 : /************************************************************************/
    5930                 : 
    5931               0 : CPLErr GDALClientDataset::Delete( const char * pszFilename )
    5932                 : {
    5933                 :     pszFilename =
    5934               0 :         GDALClientDatasetGetFilename(pszFilename);
    5935               0 :     if( pszFilename == NULL )
    5936               0 :         return CE_Failure;
    5937                 : 
    5938                 :     CLIENT_ENTER();
    5939                 : 
    5940               0 :     GDALServerSpawnedProcess* ssp = GDALServerSpawnAsync();
    5941               0 :     if( ssp == NULL )
    5942               0 :         return CE_Failure;
    5943                 : 
    5944               0 :     GDALPipe* p = ssp->p;
    5945               0 :     if( !GDALClientDatasetQuietDelete(p, pszFilename) )
    5946                 :     {
    5947               0 :         GDALServerSpawnAsyncFinish(ssp);
    5948               0 :         return CE_Failure;
    5949                 :     }
    5950                 : 
    5951               0 :     GDALServerSpawnAsyncFinish(ssp);
    5952               0 :     return CE_None;
    5953                 : }
    5954                 : 
    5955                 : /************************************************************************/
    5956                 : /*                      GDALUnloadAPIPROXYDriver()                      */
    5957                 : /************************************************************************/
    5958                 : static GDALDriver* poAPIPROXYDriver = NULL;
    5959                 : 
    5960             550 : static void GDALUnloadAPIPROXYDriver(GDALDriver* poDriver)
    5961                 : {
    5962             550 :     if( bRecycleChild )
    5963                 :     {
    5964                 :         /* Kill all unused descriptors */
    5965             550 :         bRecycleChild = FALSE;
    5966            2750 :         for(int i=0;i<nMaxRecycled;i++)
    5967                 :         {
    5968            2200 :             if( aspRecycled[i] != NULL )
    5969                 :             {
    5970               6 :                 GDALServerSpawnAsyncFinish(aspRecycled[i]);
    5971               6 :                 aspRecycled[i] = NULL;
    5972                 :             }
    5973                 :         }
    5974                 :     }
    5975             550 :     poAPIPROXYDriver = NULL; 
    5976             550 : }
    5977                 : 
    5978                 : /************************************************************************/
    5979                 : /*                       GDALGetAPIPROXYDriver()                        */
    5980                 : /************************************************************************/
    5981                 : 
    5982           19965 : GDALDriver* GDALGetAPIPROXYDriver()
    5983                 : {
    5984           19965 :     CPLMutexHolderD(GDALGetphDMMutex());
    5985           19965 :     if( poAPIPROXYDriver == NULL )
    5986                 :     {
    5987                 : #ifdef DEBUG
    5988                 :         CPLAssert(INSTR_END + 1 == sizeof(apszInstr) / sizeof(apszInstr[0]));
    5989                 : #endif
    5990                 :         /* If asserted, change GDAL_CLIENT_SERVER_PROTOCOL_MAJOR / GDAL_CLIENT_SERVER_PROTOCOL_MINOR */
    5991                 :         CPLAssert(INSTR_END + 1 == 80);
    5992                 : 
    5993             556 :         const char* pszConnPool = CPLGetConfigOption("GDAL_API_PROXY_CONN_POOL", "YES");
    5994             556 :         if( atoi(pszConnPool) > 0 )
    5995                 :         {
    5996               0 :             bRecycleChild = TRUE;
    5997               0 :             nMaxRecycled = MIN(atoi(pszConnPool), MAX_RECYCLED);
    5998                 :         }
    5999             556 :         else if( CSLTestBoolean(pszConnPool) )
    6000                 :         {
    6001             556 :             bRecycleChild = TRUE;
    6002             556 :             nMaxRecycled = DEFAULT_RECYCLED;
    6003                 :         }
    6004             556 :         memset(aspRecycled, 0, sizeof(aspRecycled));
    6005                 : 
    6006             556 :         poAPIPROXYDriver = new GDALDriver();
    6007                 : 
    6008             556 :         poAPIPROXYDriver->SetDescription( "API_PROXY" );
    6009                 :         poAPIPROXYDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    6010             556 :                                    "API_PROXY" );
    6011                 : 
    6012             556 :         poAPIPROXYDriver->pfnOpen = GDALClientDataset::Open;
    6013             556 :         poAPIPROXYDriver->pfnIdentify = GDALClientDataset::Identify;
    6014             556 :         poAPIPROXYDriver->pfnCreateCopy = GDALClientDataset::CreateCopy;
    6015             556 :         poAPIPROXYDriver->pfnCreate = GDALClientDataset::Create;
    6016             556 :         poAPIPROXYDriver->pfnDelete = GDALClientDataset::Delete;
    6017             556 :         poAPIPROXYDriver->pfnUnloadDriver = GDALUnloadAPIPROXYDriver;
    6018                 :     }
    6019           19965 :     return poAPIPROXYDriver;
    6020                 : }

Generated by: LCOV version 1.7