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