36
36
#include "storage/shmem.h"
37
37
#include "utils/hsearch.h"
38
38
39
+ download_extension_file_hook_type download_extension_file_hook = NULL ;
39
40
40
41
/* signature for PostgreSQL-specific library init function */
41
42
typedef void (* PG_init_t ) (void );
@@ -79,11 +80,13 @@ static void *internal_load_library(const char *libname);
79
80
static void incompatible_module_error (const char * libname ,
80
81
const Pg_magic_struct * module_magic_data ) pg_attribute_noreturn ();
81
82
static bool file_exists (const char * name );
82
- static char * expand_dynamic_library_name (const char * name );
83
+ static char * expand_dynamic_library_name (const char * name , bool * is_found );
83
84
static void check_restricted_library_name (const char * name );
84
85
static char * substitute_libpath_macro (const char * name );
85
86
static char * find_in_dynamic_libpath (const char * basename );
86
87
88
+ static void neon_try_load (const char * name );
89
+
87
90
/* Magic structure that module needs to match to be accepted */
88
91
static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA ;
89
92
@@ -108,9 +111,20 @@ load_external_function(const char *filename, const char *funcname,
108
111
char * fullname ;
109
112
void * lib_handle ;
110
113
void * retval ;
114
+ bool is_found = true;
111
115
112
116
/* Expand the possibly-abbreviated filename to an exact path name */
113
- fullname = expand_dynamic_library_name (filename );
117
+ fullname = expand_dynamic_library_name (filename , & is_found );
118
+
119
+ // if file is not found, try to download it from compute_ctl
120
+ if (!is_found && download_extension_file_hook != NULL )
121
+ {
122
+ // try to download the file
123
+ elog (DEBUG3 , "load_external_function: try to download file: %s" , fullname );
124
+ neon_try_load (fullname );
125
+ // try to find file locally once again
126
+ fullname = expand_dynamic_library_name (filename , & is_found );
127
+ }
114
128
115
129
/* Load the shared library, unless we already did */
116
130
lib_handle = internal_load_library (fullname );
@@ -132,6 +146,47 @@ load_external_function(const char *filename, const char *funcname,
132
146
return retval ;
133
147
}
134
148
149
+ void
150
+ neon_try_load (const char * name )
151
+ {
152
+ bool have_slash ;
153
+ char * request_name ;
154
+
155
+ // add .so suffix if it is not present
156
+ if (strstr (name , DLSUFFIX ) == NULL )
157
+ {
158
+ request_name = psprintf ("%s%s" , name , DLSUFFIX );
159
+ elog (DEBUG3 , "neon_try_load: add DLSUFFIX: %s" , request_name );
160
+ }
161
+ else
162
+ {
163
+ request_name = pstrdup (name );
164
+ elog (DEBUG3 , "neon_try_load: DLSUFFIX already present: %s" , request_name );
165
+ }
166
+
167
+ have_slash = (first_dir_separator (request_name ) != NULL );
168
+
169
+ if (strncmp (request_name , "$libdir/" , strlen ("$libdir/" )) == 0 )
170
+ {
171
+ char * new_request_name = psprintf ("%s" , request_name + strlen ("$libdir/" ));
172
+ pfree (request_name );
173
+ request_name = new_request_name ;
174
+
175
+ elog (DEBUG3 , "neon_try_load: omit $libdir/: %s" , request_name );
176
+ }
177
+ else if (have_slash )
178
+ {
179
+ ereport (ERROR ,
180
+ (errcode (ERRCODE_INVALID_NAME ),
181
+ errmsg ("unexpected path in dynamic library name: %s" ,
182
+ name )));
183
+ }
184
+
185
+ elog (DEBUG3 , "neon_try_load: final request_name: %s" , request_name );
186
+
187
+ download_extension_file_hook (request_name , true);
188
+ }
189
+
135
190
/*
136
191
* This function loads a shlib file without looking up any particular
137
192
* function in it. If the same shlib has previously been loaded,
@@ -144,13 +199,24 @@ void
144
199
load_file (const char * filename , bool restricted )
145
200
{
146
201
char * fullname ;
202
+ bool is_found = true;
147
203
148
204
/* Apply security restriction if requested */
149
205
if (restricted )
150
206
check_restricted_library_name (filename );
151
207
152
208
/* Expand the possibly-abbreviated filename to an exact path name */
153
- fullname = expand_dynamic_library_name (filename );
209
+ fullname = expand_dynamic_library_name (filename , & is_found );
210
+
211
+ // if file is not found, try to download it from compute_ctl
212
+ if (!is_found && download_extension_file_hook != NULL )
213
+ {
214
+ // try to download the file
215
+ elog (DEBUG3 , "load_file: try to download file: %s" , fullname );
216
+ neon_try_load (fullname );
217
+ // try to find file locally once again
218
+ fullname = expand_dynamic_library_name (filename , & is_found );
219
+ }
154
220
155
221
/* Load the shared library */
156
222
(void ) internal_load_library (fullname );
@@ -168,7 +234,6 @@ lookup_external_function(void *filehandle, const char *funcname)
168
234
return dlsym (filehandle , funcname );
169
235
}
170
236
171
-
172
237
/*
173
238
* Load the specified dynamic-link library file, unless it already is
174
239
* loaded. Return the pg_dl* handle for the file.
@@ -209,6 +274,7 @@ internal_load_library(const char *libname)
209
274
errmsg ("could not access file \"%s\": %m" ,
210
275
libname )));
211
276
277
+
212
278
for (file_scanner = file_list ;
213
279
file_scanner != NULL &&
214
280
!SAME_INODE (stat_buf , * file_scanner );
@@ -428,7 +494,7 @@ file_exists(const char *name)
428
494
* The result will always be freshly palloc'd.
429
495
*/
430
496
static char *
431
- expand_dynamic_library_name (const char * name )
497
+ expand_dynamic_library_name (const char * name , bool * is_found )
432
498
{
433
499
bool have_slash ;
434
500
char * new ;
@@ -474,9 +540,11 @@ expand_dynamic_library_name(const char *name)
474
540
* If we can't find the file, just return the string as-is. The ensuing
475
541
* load attempt will fail and report a suitable message.
476
542
*/
543
+ * is_found = false;
477
544
return pstrdup (name );
478
545
}
479
546
547
+
480
548
/*
481
549
* Check a restricted library name. It must begin with "$libdir/plugins/"
482
550
* and there must not be any directory separators after that (this is
0 commit comments