PostGIS  3.4.0dev-r@@SVN_REVISION@@
rtpostgis.c
Go to the documentation of this file.
1 /*
2  *
3  * WKTRaster - Raster Types for PostGIS
4  * http://trac.osgeo.org/postgis/wiki/WKTRaster
5  *
6  * Copyright (C) 2011-2013 Regents of the University of California
7  * <bkpark@ucdavis.edu>
8  * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9  * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10  * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11  * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12  * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software Foundation,
26  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27  *
28  */
29 
30 /***************************************************************
31  * Some rules for returning NOTICE or ERROR...
32  *
33  * Send an ERROR like:
34  *
35  * elog(ERROR, "RASTER_out: Could not deserialize raster");
36  *
37  * only when:
38  *
39  * -something wrong happen with memory,
40  * -a function got an invalid argument ('3BUI' as pixel type) so that no row can
41  * be processed
42  *
43  * *** IMPORTANT: elog(ERROR, ...) does NOT return to calling function ***
44  *
45  * Send a NOTICE like:
46  *
47  * elog(NOTICE, "Invalid band index (must use 1-based). Returning NULL");
48  *
49  * when arguments (e.g. x, y, band) are NULL or out of range so that some or
50  * most rows can be processed anyway
51  *
52  * in this case,
53  * for SET functions or function normally returning a modified raster, return
54  * the original raster
55  * for GET functions, return NULL
56  * try to deduce a valid parameter value if it makes sence (e.g. out of range
57  * index for addBand)
58  *
59  * Do not put the name of the faulty function for NOTICEs, only with ERRORs.
60  *
61  ****************************************************************/
62 
63 /******************************************************************************
64  * Some notes on memory management...
65  *
66  * Every time a SQL function is called, PostgreSQL creates a new memory context.
67  * So, all the memory allocated with palloc/repalloc in that context is
68  * automatically free'd at the end of the function. If you want some data to
69  * live between function calls, you have 2 options:
70  *
71  * - Use fcinfo->flinfo->fn_mcxt contex to store the data (by pointing the
72  * data you want to keep with fcinfo->flinfo->fn_extra)
73  * - Use SRF funcapi, and storing the data at multi_call_memory_ctx (by pointing
74  * the data you want to keep with funcctx->user_fctx. funcctx is created by
75  * funcctx = SPI_FIRSTCALL_INIT()). Recommended way in functions returning rows,
76  * like RASTER_dumpAsPolygons (see section 34.9.9 at
77  * http://www.postgresql.org/docs/8.4/static/xfunc-c.html).
78  *
79  * But raster code follows the same philosophy than the rest of PostGIS: keep
80  * memory as clean as possible. So, we free all allocated memory.
81  *
82  * TODO: In case of functions returning NULL, we should free the memory too.
83  *****************************************************************************/
84 
85 /******************************************************************************
86  * Notes for use of PG_DETOAST_DATUM(), PG_DETOAST_DATUM_SLICE()
87  * and PG_DETOAST_DATUM_COPY()
88  *
89  * When ONLY getting raster (not band) metadata, use PG_DETOAST_DATUM_SLICE()
90  * as it is generally quicker to get only the chunk of memory that contains
91  * the raster metadata.
92  *
93  * Example: PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0,
94  * sizeof(struct rt_raster_serialized_t))
95  *
96  * When ONLY setting raster or band(s) metadata OR reading band data, use
97  * PG_DETOAST_DATUM() as rt_raster_deserialize() allocates local memory
98  * for the raster and band(s) metadata.
99  *
100  * Example: PG_DETOAST_DATUM(PG_GETARG_DATUM(0))
101  *
102  * When SETTING band pixel values, use PG_DETOAST_DATUM_COPY(). This is
103  * because band data (not metadata) is just a pointer to the correct
104  * memory location in the detoasted datum. What is returned from
105  * PG_DETOAST_DATUM() may or may not be a copy of the input datum.
106  *
107  * From the comments in postgresql/src/include/fmgr.h...
108  *
109  * pg_detoast_datum() gives you either the input datum (if not toasted)
110  * or a detoasted copy allocated with palloc().
111  *
112  * From the mouth of Tom Lane...
113  * http://archives.postgresql.org/pgsql-hackers/2002-01/msg01289.php
114  *
115  * PG_DETOAST_DATUM_COPY guarantees to give you a copy, even if the
116  * original wasn't toasted. This allows you to scribble on the input,
117  * in case that happens to be a useful way of forming your result.
118  * Without a forced copy, a routine for a pass-by-ref datatype must
119  * NEVER, EVER scribble on its input ... because very possibly it'd
120  * be scribbling on a valid tuple in a disk buffer, or a valid entry
121  * in the syscache.
122  *
123  * The key detail above is that the raster datatype is a varlena, a
124  * passed by reference datatype.
125  *
126  * Example: PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0))
127  *
128  * If in doubt, use PG_DETOAST_DATUM_COPY() as that guarantees that the input
129  * datum is copied for use.
130  *****************************************************************************/
131 
132 /* PostgreSQL */
133 #include "postgres.h" /* for palloc */
134 #include "fmgr.h" /* for PG_MODULE_MAGIC */
135 #include "libpq/pqsignal.h"
136 #include "utils/guc.h"
137 #include "utils/builtins.h"
138 #include "utils/memutils.h"
139 #include "utils/elog.h"
140 
141 /* PostGIS */
142 #include "postgis_config.h"
143 #include "liblwgeom.h"
144 #include "lwgeom_pg.h"
145 #include "stringlist.h"
146 #include "optionlist.h"
147 
148 /* PostGIS Raster */
149 #include "rtpostgis.h"
150 #include "rtpg_internal.h"
151 
152 
153 #ifndef __GNUC__
154 # define __attribute__ (x)
155 #endif
156 
157 /*
158  * This is required for builds against pgsql
159  */
161 
162 /* Module load callback */
163 void _PG_init(void);
164 
165 /* Module unload callback */
166 void _PG_fini(void);
167 
168 #define RT_MSG_MAXLEN 256
169 
170 
171 /* ---------------------------------------------------------------- */
172 /* Memory allocation / error reporting hooks */
173 /* ---------------------------------------------------------------- */
174 
175 static void *
176 rt_pg_alloc(size_t size)
177 {
178  void * result;
179 
180  POSTGIS_RT_DEBUGF(5, "rt_pgalloc(%ld) called", (long int) size);
181 
182  result = palloc(size);
183 
184  return result;
185 }
186 
187 static void *
188 rt_pg_realloc(void *mem, size_t size)
189 {
190  void * result;
191 
192  POSTGIS_RT_DEBUGF(5, "rt_pg_realloc(%ld) called", (long int) size);
193 
194  if (mem)
195  result = repalloc(mem, size);
196 
197  else
198  result = palloc(size);
199 
200  return result;
201 }
202 
203 static void
204 rt_pg_free(void *ptr)
205 {
206  POSTGIS_RT_DEBUG(5, "rt_pfree called");
207  pfree(ptr);
208 }
209 
210 static void rt_pg_error(const char *fmt, va_list ap)
211  __attribute__(( format(printf,1,0) ));
212 
213 static void
214 rt_pg_error(const char *fmt, va_list ap)
215 {
216  char errmsg[RT_MSG_MAXLEN+1];
217 
218  vsnprintf (errmsg, RT_MSG_MAXLEN, fmt, ap);
219 
220  errmsg[RT_MSG_MAXLEN]='\0';
221  ereport(ERROR, (errmsg_internal("%s", errmsg)));
222 }
223 
224 static void rt_pg_notice(const char *fmt, va_list ap)
225  __attribute__(( format(printf,1,0) ));
226 
227 static void
228 rt_pg_notice(const char *fmt, va_list ap)
229 {
230  char msg[RT_MSG_MAXLEN+1];
231 
232  vsnprintf (msg, RT_MSG_MAXLEN, fmt, ap);
233 
234  msg[RT_MSG_MAXLEN]='\0';
235  ereport(NOTICE, (errmsg_internal("%s", msg)));
236 }
237 
238 static void rt_pg_debug(const char *fmt, va_list ap)
239  __attribute__(( format(printf,1,0) ));
240 
241 static void
242 rt_pg_debug(const char *fmt, va_list ap)
243 {
244  char msg[RT_MSG_MAXLEN+1];
245 
246  vsnprintf (msg, RT_MSG_MAXLEN, fmt, ap);
247 
248  msg[RT_MSG_MAXLEN]='\0';
249  ereport(DEBUG1, (errmsg_internal("%s", msg)));
250 }
251 
252 static char *
253 rt_pg_options(const char* varname)
254 {
255  char optname[128];
256  char *optvalue;
257  snprintf(optname, 128, "postgis.%s", varname);
258  /* GetConfigOptionByName(name, found_name, missing_ok) */
259  optvalue = GetConfigOptionByName(optname, NULL, true);
260  if (optvalue && strlen(optvalue) == 0)
261  return NULL;
262  else
263  return optvalue;
264 }
265 
266 /* ---------------------------------------------------------------- */
267 /* GDAL allowed config options for VSI filesystems */
268 /* ---------------------------------------------------------------- */
269 
271 
272 
273 #if POSTGIS_GDAL_VERSION < 23
274 
275 /*
276 * For older versions of GDAL we have extracted the list of options
277 * that were available at the 2.2 release and use that
278 * as our set of allowed VSI network file options.
279 */
280 static void
282 {
283  const char * gdaloption;
284  const char * const gdaloptions[] = {
285  "aws_access_key_id",
286  "aws_https",
287  "aws_max_keys",
288  "aws_s3_endpoint",
289  "aws_region",
290  "aws_request_payer",
291  "aws_secret_access_key",
292  "aws_session_token",
293  "aws_timestamp",
294  "aws_virtual_hosting",
295  "cpl_gs_timestamp",
296  "cpl_gs_endpoint",
297  "gs_secret_access_key",
298  "gs_access_key_id",
299  "goa2_client_id",
300  "goa2_client_secret",
301  "cpl_curl_enable_vsimem",
302  "cpl_curl_gzip",
303  "cpl_curl_verbose",
304  "gdal_http_auth",
305  "gdal_http_connecttimeout",
306  "gdal_http_cookie",
307  "gdal_http_header_file",
308  "gdal_http_low_speed_time",
309  "gdal_http_low_speed_limit",
310  "gdal_http_max_retry",
311  "gdal_http_netrc",
312  "gdal_http_proxy",
313  "gdal_http_proxyuserpwd",
314  "gdal_http_retry_delay",
315  "gdal_http_userpwd",
316  "gdal_http_timeout",
317  "gdal_http_unsafessl",
318  "gdal_http_useragent",
319  "gdal_disable_readdir_on_open",
320  "gdal_proxy_auth",
321  "curl_ca_bundle",
322  "ssl_cert_file",
323  "vsi_cache_size",
324  "cpl_vsil_curl_use_head",
325  "cpl_vsil_curl_use_s3_redirect",
326  "cpl_vsil_curl_max_ranges",
327  "cpl_vsil_curl_use_cache",
328  "cpl_vsil_curl_allowed_filename",
329  "cpl_vsil_curl_allowed_extensions",
330  "cpl_vsil_curl_slow_get_size",
331  "vsi_cache",
332  "vsis3_chunk_size",
333  NULL
334  };
335  const char * const * gdaloptionsptr = gdaloptions;
336 
338  while((gdaloption = *gdaloptionsptr++))
339  {
341  }
343 }
344 
345 #else /* POSTGIS_GDAL_VERSION < 23 */
346 
347 /*
348 * For newer versions of GDAL the VSIGetFileSystemOptions() call returns
349 * all the allowed options for each VSI network file type, and we just have
350 * to keep the list of VSI types statically in rt_pg_vsi_load_all_options().
351 */
352 static void
353 rt_pg_vsi_load_options(const char* vsiname, stringlist_t *s)
354 {
355  CPLXMLNode *root, *optNode;
356  const char *xml = VSIGetFileSystemOptions(vsiname);
357  if (!xml) return;
358 
359  root = CPLParseXMLString(xml);
360  if (!root) {
361  elog(ERROR, "%s: Unable to read options for VSI %s", __func__, vsiname);
362  return;
363  }
364  optNode = CPLSearchXMLNode(root, "Option");
365  if (!optNode) {
366  CPLDestroyXMLNode(root);
367  elog(ERROR, "%s: Unable to find <Option> in VSI XML %s", __func__, vsiname);
368  return;
369  }
370  while(optNode)
371  {
372  const char *option = CPLGetXMLValue(optNode, "name", NULL);
373  if (option) {
374  char *optionstr = pstrdup(option);
375  char *ptr = optionstr;
376  /* The options parser used in rt_util_gdal_open()
377  lowercases keys, so we'll lower case our list
378  of options before storing them in the stringlist. */
379  while (*ptr) {
380  *ptr = tolower(*ptr);
381  ptr++;
382  }
383  elog(DEBUG4, "GDAL %s option: %s", vsiname, optionstr);
384  stringlist_add_string_nosort(s, optionstr);
385  }
386  optNode = optNode->psNext;
387  }
388  CPLDestroyXMLNode(root);
389 }
390 
391 static void
393 {
394  const char * vsiname;
395  const char * const vsilist[] = {
396  "/vsicurl/",
397  "/vsis3/",
398  "/vsigs/",
399  "/vsiaz/",
400  "/vsioss/",
401  "/vsihdfs/",
402  "/vsiwebhdfs/",
403  "/vsiswift/",
404  "/vsiadls/",
405  NULL
406  };
407  const char * const * vsilistptr = vsilist;
408 
410  while((vsiname = *vsilistptr++))
411  {
412  rt_pg_vsi_load_options(vsiname, vsi_option_stringlist);
413  }
415 }
416 
417 #endif /* POSTGIS_GDAL_VERSION < 23 */
418 
419 
420 static bool
421 rt_pg_vsi_check_options(char **newval, void **extra, GucSource source)
422 {
423  size_t olist_sz, i;
424  char *olist[OPTION_LIST_SIZE];
425  const char *found = NULL;
426  char *newoptions;
427 
428  memset(olist, 0, sizeof(olist));
429  if (!newval || !*newval)
430  return false;
431  newoptions = pstrdup(*newval);
432 
433  /* Cache the legal options if they aren't already loaded */
436 
437  elog(DEBUG5, "%s: processing VSI options: %s", __func__, newoptions);
438  option_list_parse(newoptions, olist);
439  olist_sz = option_list_length(olist);
440  if (olist_sz % 2 != 0)
441  return false;
442 
443  for (i = 0; i < olist_sz; i += 2)
444  {
445  found = stringlist_find(vsi_option_stringlist, olist[i]);
446  if (!found)
447  {
448  elog(WARNING, "'%s' is not a legal VSI network file option", olist[i]);
449  pfree(newoptions);
450  return false;
451  }
452  }
453  return true;
454 }
455 
456 
457 /* ---------------------------------------------------------------- */
458 /* PostGIS raster GUCs */
459 /* ---------------------------------------------------------------- */
460 
461 static char *gdal_datapath = NULL;
462 static char *gdal_vsi_options = NULL;
463 static char *gdal_enabled_drivers = NULL;
464 static bool enable_outdb_rasters = false;
465 
466 /* ---------------------------------------------------------------- */
467 /* Useful variables */
468 /* ---------------------------------------------------------------- */
469 
473 
474 /* postgis.gdal_datapath */
475 static void
476 rtpg_assignHookGDALDataPath(const char *newpath, void *extra) {
477  POSTGIS_RT_DEBUGF(4, "newpath = %s", newpath);
478  POSTGIS_RT_DEBUGF(4, "gdaldatapath = %s", gdal_datapath);
479 
480  /* clear finder cache */
481  CPLFinderClean();
482 
483  /* clear cached OSR */
484  OSRCleanup();
485 
486  /* set GDAL_DATA */
487  CPLSetConfigOption("GDAL_DATA", newpath);
488  POSTGIS_RT_DEBUGF(4, "GDAL_DATA = %s", CPLGetConfigOption("GDAL_DATA", ""));
489 }
490 
491 /* postgis.gdal_enabled_drivers */
492 static void
493 rtpg_assignHookGDALEnabledDrivers(const char *enabled_drivers, void *extra) {
494  int enable_all = 0;
495  int disable_all = 0;
496  int vsicurl = 0;
497 
498  char **enabled_drivers_array = NULL;
499  uint32_t enabled_drivers_count = 0;
500  bool *enabled_drivers_found = NULL;
501  char *gdal_skip = NULL;
502 
503  uint32_t i;
504  uint32_t j;
505 
506  POSTGIS_RT_DEBUGF(4, "GDAL_SKIP = %s", CPLGetConfigOption("GDAL_SKIP", ""));
507  POSTGIS_RT_DEBUGF(4, "enabled_drivers = %s", enabled_drivers);
508 
509  /* if NULL, nothing to do */
510  if (enabled_drivers == NULL)
511  return;
512 
513  elog(DEBUG4, "Enabling GDAL drivers: %s", enabled_drivers);
514 
515  /* destroy the driver manager */
516  /* this is the only way to ensure GDAL_SKIP is recognized */
517  GDALDestroyDriverManager();
518  CPLSetConfigOption("GDAL_SKIP", NULL);
519 
520  /* force wrapper function to call GDALAllRegister() */
522 
523  enabled_drivers_array = rtpg_strsplit(enabled_drivers, " ", &enabled_drivers_count);
524  enabled_drivers_found = palloc(sizeof(bool) * enabled_drivers_count);
525  memset(enabled_drivers_found, FALSE, sizeof(bool) * enabled_drivers_count);
526 
527  /* scan for keywords DISABLE_ALL and ENABLE_ALL */
528  disable_all = 0;
529  enable_all = 0;
530  if (strstr(enabled_drivers, GDAL_DISABLE_ALL) != NULL) {
531  for (i = 0; i < enabled_drivers_count; i++) {
532  if (strstr(enabled_drivers_array[i], GDAL_DISABLE_ALL) != NULL) {
533  enabled_drivers_found[i] = TRUE;
534  disable_all = 1;
535  }
536  }
537  }
538  else if (strstr(enabled_drivers, GDAL_ENABLE_ALL) != NULL) {
539  for (i = 0; i < enabled_drivers_count; i++) {
540  if (strstr(enabled_drivers_array[i], GDAL_ENABLE_ALL) != NULL) {
541  enabled_drivers_found[i] = TRUE;
542  enable_all = 1;
543  }
544  }
545  }
546  else if (strstr(enabled_drivers, GDAL_VSICURL) != NULL) {
547  for (i = 0; i < enabled_drivers_count; i++) {
548  if (strstr(enabled_drivers_array[i], GDAL_VSICURL) != NULL) {
549  enabled_drivers_found[i] = TRUE;
550  vsicurl = 1;
551  }
552  }
553  }
554 
555  if (!enable_all) {
556  int found = 0;
557  uint32_t drv_count = 0;
558  rt_gdaldriver drv_set = rt_raster_gdal_drivers(&drv_count, 0);
559 
560  POSTGIS_RT_DEBUGF(4, "driver count = %d", drv_count);
561 
562  /* all other drivers than those in new drivers are added to GDAL_SKIP */
563  for (i = 0; i < drv_count; i++) {
564  found = 0;
565 
566  if (!disable_all) {
567  /* gdal driver found in enabled_drivers, continue to thorough search */
568  if (strstr(enabled_drivers, drv_set[i].short_name) != NULL) {
569  /* thorough search of enabled_drivers */
570  for (j = 0; j < enabled_drivers_count; j++) {
571  /* driver found */
572  if (strcmp(enabled_drivers_array[j], drv_set[i].short_name) == 0) {
573  enabled_drivers_found[j] = TRUE;
574  found = 1;
575  }
576  }
577  }
578  }
579 
580  /* driver found, continue */
581  if (found)
582  continue;
583 
584  /* driver not found, add to gdal_skip */
585  if (gdal_skip == NULL) {
586  gdal_skip = palloc(sizeof(char) * (strlen(drv_set[i].short_name) + 1));
587  gdal_skip[0] = '\0';
588  }
589  else {
590  gdal_skip = repalloc(
591  gdal_skip,
592  sizeof(char) * (
593  strlen(gdal_skip) + 1 + strlen(drv_set[i].short_name) + 1
594  )
595  );
596  strcat(gdal_skip, " ");
597  }
598  strcat(gdal_skip, drv_set[i].short_name);
599  }
600 
601  for (i = 0; i < drv_count; i++) {
602  pfree(drv_set[i].short_name);
603  pfree(drv_set[i].long_name);
604  pfree(drv_set[i].create_options);
605  }
606  if (drv_count) pfree(drv_set);
607 
608  }
609 
610  for (i = 0; i < enabled_drivers_count; i++) {
611  if (enabled_drivers_found[i])
612  continue;
613 
614  if (disable_all)
615  elog(WARNING, "%s set. Ignoring GDAL driver: %s", GDAL_DISABLE_ALL, enabled_drivers_array[i]);
616  else if (enable_all)
617  elog(WARNING, "%s set. Ignoring GDAL driver: %s", GDAL_ENABLE_ALL, enabled_drivers_array[i]);
618  else
619  elog(WARNING, "Unknown GDAL driver: %s", enabled_drivers_array[i]);
620  }
621 
622  if (vsicurl)
623  elog(WARNING, "%s set.", GDAL_VSICURL);
624 
625  /* destroy the driver manager */
626  /* this is the only way to ensure GDAL_SKIP is recognized */
627  GDALDestroyDriverManager();
628 
629  /* set GDAL_SKIP */
630  POSTGIS_RT_DEBUGF(4, "gdal_skip = %s", gdal_skip);
631  CPLSetConfigOption("GDAL_SKIP", gdal_skip);
632  if (gdal_skip != NULL) pfree(gdal_skip);
633 
634  /* force wrapper function to call GDALAllRegister() */
636 
637  pfree(enabled_drivers_array);
638  pfree(enabled_drivers_found);
639  POSTGIS_RT_DEBUGF(4, "GDAL_SKIP = %s", CPLGetConfigOption("GDAL_SKIP", ""));
640 }
641 
642 /* postgis.enable_outdb_rasters */
643 static void
644 rtpg_assignHookEnableOutDBRasters(bool enable, void *extra) {
645  /* do nothing for now */
646 }
647 
648 
649 
650 /*
651 * Machinery for intercepting the system SIGINT
652 * handler so we can cancel long-running GDAL operations
653 * via the progress handlers.
654 */
655 static pqsigfunc coreIntHandler = 0;
656 
657 #ifdef WIN32
658 static void interruptCallback() {
659  if (UNBLOCKED_SIGNAL_QUEUE())
660  pgwin32_dispatch_queued_signals();
661 }
662 #endif
663 
664 
665 /*
666 * This is the interrupt capture for this module.
667 * Before handing off the signal to the core, it
668 * sets the interrupt flag for currently running
669 * functions.
670 */
671 static void
673 {
674  /*
675  * NOTE: printf here would be dangerous, see
676  * https://trac.osgeo.org/postgis/ticket/3644
677  */
678  // printf("postgis_raster interrupt requested\n"); fflush(stdout);
679 
680  /* Request interruption of liblwgeom as well */
682 
683  /* Pass control into the usual core handler */
684  if (coreIntHandler) {
685  (*coreIntHandler)(sig);
686  }
687 }
688 
689 
690 
691 /* Module load callback */
692 void
693 _PG_init(void) {
694 
695  bool boot_postgis_enable_outdb_rasters = false;
696  MemoryContext old_context;
697 
698  /* Set up interrupt capture */
699  coreIntHandler = pqsignal(SIGINT, handleInterrupt);
700 
701 #ifdef WIN32
702  GEOS_interruptRegisterCallback(interruptCallback);
703  lwgeom_register_interrupt_callback(interruptCallback);
704 #endif
705 
706 
707  /*
708  * Change to context for memory allocation calls like palloc() in the
709  * extension initialization routine
710  */
711  old_context = MemoryContextSwitchTo(TopMemoryContext);
712 
713  /*
714  use POSTGIS_GDAL_ENABLED_DRIVERS to set the bootValue
715  of GUC postgis.gdal_enabled_drivers
716  */
717  env_postgis_gdal_enabled_drivers = getenv("POSTGIS_GDAL_ENABLED_DRIVERS");
718  if (env_postgis_gdal_enabled_drivers == NULL) {
719  size_t sz = sizeof(char) * (strlen(GDAL_DISABLE_ALL) + 1);
722  }
723  else {
726  );
727  }
729  4,
730  "boot_postgis_gdal_enabled_drivers = %s",
732  );
733 
734  /*
735  use POSTGIS_ENABLE_OUTDB_RASTERS to set the bootValue
736  of GUC postgis.enable_outdb_rasters
737  */
738  env_postgis_enable_outdb_rasters = getenv("POSTGIS_ENABLE_OUTDB_RASTERS");
739  if (env_postgis_enable_outdb_rasters != NULL) {
741 
742  /* out of memory */
743  if (env == NULL) {
744  elog(ERROR, "_PG_init: Cannot process environmental variable: POSTGIS_ENABLE_OUTDB_RASTERS");
745  return;
746  }
747 
748  if (strcmp(env, "1") == 0)
749  boot_postgis_enable_outdb_rasters = true;
750 
752  pfree(env);
753  }
755  4,
756  "boot_postgis_enable_outdb_rasters = %s",
757  boot_postgis_enable_outdb_rasters ? "TRUE" : "FALSE"
758  );
759 
760  /* Install liblwgeom handlers */
761  pg_install_lwgeom_handlers();
762 
763  /* Install rtcore handlers */
766  rt_pg_options);
767 
768  /* Define custom GUC variables. */
769  if ( postgis_guc_find_option("postgis.gdal_datapath") )
770  {
771  /* In this narrow case the previously installed GUC is tied to the callback in */
772  /* the previously loaded library. Probably this is happening during an */
773  /* upgrade, so the old library is where the callback ties to. */
774  elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_datapath");
775  }
776  else
777  {
778  DefineCustomStringVariable(
779  "postgis.gdal_datapath", /* name */
780  "Path to GDAL data files.", /* short_desc */
781  "Physical path to directory containing GDAL data files (sets the GDAL_DATA config option).", /* long_desc */
782  &gdal_datapath, /* valueAddr */
783  NULL, /* bootValue */
784  PGC_SUSET, /* GucContext context */
785  0, /* int flags */
786  NULL, /* GucStringCheckHook check_hook */
787  rtpg_assignHookGDALDataPath, /* GucStringAssignHook assign_hook */
788  NULL /* GucShowHook show_hook */
789  );
790  }
791 
792  if ( postgis_guc_find_option("postgis.gdal_enabled_drivers") )
793  {
794  /* In this narrow case the previously installed GUC is tied to the callback in */
795  /* the previously loaded library. Probably this is happening during an */
796  /* upgrade, so the old library is where the callback ties to. */
797  elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_enabled_drivers");
798  }
799  else
800  {
801  DefineCustomStringVariable(
802  "postgis.gdal_enabled_drivers", /* name */
803  "Enabled GDAL drivers.", /* short_desc */
804  "List of enabled GDAL drivers by short name. To enable/disable all drivers, use 'ENABLE_ALL' or 'DISABLE_ALL' (sets the GDAL_SKIP config option).", /* long_desc */
805  &gdal_enabled_drivers, /* valueAddr */
806  boot_postgis_gdal_enabled_drivers, /* bootValue */
807  PGC_SUSET, /* GucContext context */
808  0, /* int flags */
809  NULL, /* GucStringCheckHook check_hook */
810  rtpg_assignHookGDALEnabledDrivers, /* GucStringAssignHook assign_hook */
811  NULL /* GucShowHook show_hook */
812  );
813  }
814 
815  if ( postgis_guc_find_option("postgis.enable_outdb_rasters") )
816  {
817  /* In this narrow case the previously installed GUC is tied to the callback in */
818  /* the previously loaded library. Probably this is happening during an */
819  /* upgrade, so the old library is where the callback ties to. */
820  elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.enable_outdb_rasters");
821  }
822  else
823  {
824  DefineCustomBoolVariable(
825  "postgis.enable_outdb_rasters", /* name */
826  "Enable Out-DB raster bands", /* short_desc */
827  "If true, rasters can access data located outside the database", /* long_desc */
828  &enable_outdb_rasters, /* valueAddr */
829  boot_postgis_enable_outdb_rasters, /* bootValue */
830  PGC_SUSET, /* GucContext context */
831  0, /* int flags */
832  NULL, /* GucBoolCheckHook check_hook */
833  rtpg_assignHookEnableOutDBRasters, /* GucBoolAssignHook assign_hook */
834  NULL /* GucShowHook show_hook */
835  );
836  }
837 
838  if ( postgis_guc_find_option("postgis.gdal_vsi_options") )
839  {
840  elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_vsi_options");
841  }
842  else
843  {
844  DefineCustomStringVariable(
845  "postgis.gdal_vsi_options", /* name */
846  "VSI config options", /* short_desc */
847  "Set the config options to be used when opening /vsi/ network files", /* long_desc */
848  &gdal_vsi_options, /* valueAddr */
849  "", /* bootValue */
850  PGC_USERSET, /* GucContext context */
851  0, /* int flags */
852  rt_pg_vsi_check_options, /* GucStringCheckHook check_hook */
853  NULL, /* GucStringAssignHook assign_hook */
854  NULL /* GucShowHook show_hook */
855  );
856  }
857 
858  /* Revert back to old context */
859  MemoryContextSwitchTo(old_context);
860 }
861 
862 /* Module unload callback */
863 void
864 _PG_fini(void) {
865 
866  MemoryContext old_context = MemoryContextSwitchTo(TopMemoryContext);
867 
868  elog(NOTICE, "Goodbye from PostGIS Raster %s", POSTGIS_VERSION);
869 
870  /* Return SIGINT handling to core */
871  pqsignal(SIGINT, coreIntHandler);
872 
873  /* Clean up */
877 
881 
882  /* Revert back to old context */
883  MemoryContextSwitchTo(old_context);
884 }
885 
886 
887 
char * s
Definition: cu_in_wkt.c:23
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:262
#define TRUE
Definition: dbfopen.c:73
#define FALSE
Definition: dbfopen.c:72
void lwgeom_request_interrupt(void)
Request interruption of any running code.
Definition: lwgeom_api.c:663
lwinterrupt_callback * lwgeom_register_interrupt_callback(lwinterrupt_callback *)
Definition: lwgeom_api.c:673
This library is the generic geometry handling section of PostGIS.
int rt_util_gdal_register_all(int force_register_all)
Definition: rt_util.c:342
rt_gdaldriver rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t cancc)
Returns a set of available GDAL drivers.
Definition: rt_raster.c:1838
#define GDAL_ENABLE_ALL
Definition: librtcore.h:2192
#define GDAL_DISABLE_ALL
Definition: librtcore.h:2193
#define GDAL_VSICURL
Definition: librtcore.h:2194
void rt_set_handlers_options(rt_allocator allocator, rt_reallocator reallocator, rt_deallocator deallocator, rt_message_handler error_handler, rt_message_handler info_handler, rt_message_handler warning_handler, rt_options options_handler)
Definition: rt_context.c:169
def fmt
Definition: pixval.py:93
size_t option_list_length(char **olist)
Returns the total number of keys and values in the list.
Definition: optionlist.c:73
void option_list_parse(char *input, char **olist)
option_list is a null-terminated list of strings, where every odd string is a key and every even stri...
Definition: optionlist.c:86
#define OPTION_LIST_SIZE
Definition: optionlist.h:31
char * rtpg_trim(const char *input)
char ** rtpg_strsplit(const char *str, const char *delimiter, uint32_t *n)
static char * rt_pg_options(const char *varname)
Definition: rtpostgis.c:253
static void handleInterrupt(int sig)
Definition: rtpostgis.c:672
static char * env_postgis_enable_outdb_rasters
Definition: rtpostgis.c:472
static void * rt_pg_alloc(size_t size)
Definition: rtpostgis.c:176
void _PG_init(void)
Definition: rtpostgis.c:693
static char * gdal_vsi_options
Definition: rtpostgis.c:462
PG_MODULE_MAGIC
Definition: rtpostgis.c:160
static void rtpg_assignHookGDALDataPath(const char *newpath, void *extra)
Definition: rtpostgis.c:476
static void rt_pg_error(const char *fmt, va_list ap) __attribute__((format(printf
Definition: rtpostgis.c:214
void _PG_fini(void)
Definition: rtpostgis.c:864
static bool enable_outdb_rasters
Definition: rtpostgis.c:464
static void rt_pg_notice(const char *fmt, va_list ap) __attribute__((format(printf
Definition: rtpostgis.c:228
static bool rt_pg_vsi_check_options(char **newval, void **extra, GucSource source)
Definition: rtpostgis.c:421
static pqsigfunc coreIntHandler
Definition: rtpostgis.c:655
stringlist_t * vsi_option_stringlist
Definition: rtpostgis.c:270
static void rt_pg_vsi_load_all_options(void)
Definition: rtpostgis.c:281
static char * env_postgis_gdal_enabled_drivers
Definition: rtpostgis.c:470
static char * boot_postgis_gdal_enabled_drivers
Definition: rtpostgis.c:471
#define RT_MSG_MAXLEN
Definition: rtpostgis.c:168
static void rtpg_assignHookGDALEnabledDrivers(const char *enabled_drivers, void *extra)
Definition: rtpostgis.c:493
static void * rt_pg_realloc(void *mem, size_t size)
Definition: rtpostgis.c:188
static void rt_pg_free(void *ptr)
Definition: rtpostgis.c:204
static char * gdal_enabled_drivers
Definition: rtpostgis.c:463
static void rtpg_assignHookEnableOutDBRasters(bool enable, void *extra)
Definition: rtpostgis.c:644
#define __attribute__
Definition: rtpostgis.c:154
static void rt_pg_debug(const char *fmt, va_list ap) __attribute__((format(printf
Definition: rtpostgis.c:242
static char * gdal_datapath
Definition: rtpostgis.c:461
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:65
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rtpostgis.h:69
const char * stringlist_find(stringlist_t *s, const char *key)
Definition: stringlist.c:129
void stringlist_add_string_nosort(stringlist_t *s, const char *string)
Definition: stringlist.c:117
void stringlist_sort(stringlist_t *s)
Definition: stringlist.c:123
stringlist_t * stringlist_create(void)
Definition: stringlist.c:71