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