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