~pbxt-core/pbxt/rc4

« back to all changes in this revision

Viewing changes to src/pbms.h

  • Committer: Paul McCullagh
  • Date: 2009-07-30 15:43:08 UTC
  • mfrom: (663.3.2 rc2_PBMS)
  • Revision ID: paul.mccullagh@primebase.org-20090730154308-smf9l4vcpcqa0b1q
Merged changes for PBMS version 0.5.09

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * along with this program; if not, write to the Free Software
17
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
 *
19
 
 * Paul McCullagh
 
19
 * Original author: Paul McCullagh
 
20
 * Continued development: Barry Leslie
20
21
 * H&G2JCtL
21
22
 *
22
23
 * 2007-06-01
37
38
#include <dirent.h>
38
39
#include <signal.h>
39
40
#include <ctype.h>
 
41
#include <errno.h>
 
42
 
40
43
 
41
44
#ifdef USE_PRAGMA_INTERFACE
42
45
#pragma interface                       /* gcc class implementation */
43
46
#endif
44
47
 
 
48
/*                      2       10              1                       10                      20                      10                              10                      20                              20
 
49
 * Format: "~*"<db_id><'~' || '_'><tab_id>"-"<blob_id>"-"<auth_code>"-"<server_id>"-"<blob_ref_id>"-"<blob_size>
 
50
 */
 
51
//If URL_FMT changes do not forget to update couldBeURL() in this file.
 
52
 
 
53
#define URL_FMT "~*%lu%c%lu-%llu-%lx-%lu-%llu-%llu"
 
54
 
45
55
#define MS_SHARED_MEMORY_MAGIC                  0x7E9A120C
46
56
#define MS_ENGINE_VERSION                               1
47
 
#define MS_CALLBACK_VERSION                             1
48
 
#define MS_SHARED_MEMORY_VERSION                1
49
 
#define MS_ENGINE_LIST_SIZE                             80
50
 
#define MS_TEMP_FILE_PREFIX                             "pbms_temp_"
51
 
#define MS_TEMP_FILE_PREFIX                             "pbms_temp_"
52
 
 
53
 
#define MS_RESULT_MESSAGE_SIZE                  300
54
 
#define MS_RESULT_STACK_SIZE                    200
 
57
#define MS_CALLBACK_VERSION                             4
 
58
#define MS_SHARED_MEMORY_VERSION                2
 
59
#define MS_ENGINE_LIST_SIZE                             10
 
60
#define MS_TEMP_FILE_PREFIX                             "pbms_temp_"
55
61
 
56
62
#define MS_BLOB_HANDLE_SIZE                             300
57
63
 
68
74
#define MS_ERR_UNKNOWN_DB                               8
69
75
#define MS_ERR_REMOVING_REPO                    9
70
76
#define MS_ERR_DATABASE_DELETED                 10
 
77
#define MS_ERR_DUPLICATE                                11                                              /* Attempt to insert a duplicate key into a system table. */
 
78
#define MS_ERR_INVALID_RECORD                   12
 
79
#define MS_ERR_RECOVERY_IN_PROGRESS             13
 
80
#define MS_ERR_DUPLICATE_DB                             14
 
81
#define MS_ERR_DUPLICATE_DB_ID                  15
 
82
#define MS_ERR_INVALID_OPERATION                16
71
83
 
72
84
#define MS_LOCK_NONE                                    0
73
85
#define MS_LOCK_READONLY                                1
74
86
#define MS_LOCK_READ_WRITE                              2
75
87
 
76
 
#define MS_XACT_NONE                                    0
77
 
#define MS_XACT_BEGIN                                   1
78
 
#define MS_XACT_COMMIT                                  2
79
 
#define MS_XACT_ROLLBACK                                3
80
 
 
81
 
#define PBMS_ENGINE_REF_LEN                             8
82
 
#define PBMS_BLOB_URL_SIZE                              200
 
88
#define PBMS_BLOB_URL_SIZE                              120
83
89
 
84
90
#define PBMS_FIELD_COL_SIZE                             128
85
91
#define PBMS_FIELD_COND_SIZE                    300
86
92
 
 
93
#define MS_RESULT_MESSAGE_SIZE                  300
 
94
#define MS_RESULT_STACK_SIZE                    200
 
95
 
 
96
typedef struct PBMSResultRec {
 
97
        int                                             mr_code;                                                                /* Engine specific error code. */ 
 
98
        char                                    mr_message[MS_RESULT_MESSAGE_SIZE];             /* Error message, required if non-zero return code. */
 
99
        char                                    mr_stack[MS_RESULT_STACK_SIZE];                 /* Trace information about where the error occurred. */
 
100
} PBMSResultRec, *PBMSResultPtr;
 
101
 
 
102
 
87
103
 
88
104
typedef struct PBMSBlobID {
 
105
        u_int32_t                               bi_db_id;       
89
106
        u_int64_t                               bi_blob_size;   
90
107
        u_int64_t                               bi_blob_id;                             // or repo file offset if type = REPO
 
108
        u_int64_t                               bi_blob_ref_id;                 
91
109
        u_int32_t                               bi_tab_id;                              // or repo ID if type = REPO
92
110
        u_int32_t                               bi_auth_code;
93
111
        u_int32_t                               bi_blob_type;
94
112
} PBMSBlobIDRec, *PBMSBlobIDPtr;
95
113
 
96
 
typedef struct PBMSResultRec {
97
 
        int                                             mr_code;                                                                /* Engine specific error code. */ 
98
 
        char                                    mr_message[MS_RESULT_MESSAGE_SIZE];             /* Error message, required if non-zero return code. */
99
 
        char                                    mr_stack[MS_RESULT_STACK_SIZE];                 /* Trace information about where the error occurred. */
100
 
} PBMSResultRec, *PBMSResultPtr;
101
 
 
102
 
typedef struct PBMSEngineRefRec {
103
 
        unsigned char                   er_data[PBMS_ENGINE_REF_LEN];
104
 
} PBMSEngineRefRec, *PBMSEngineRefPtr;
105
 
 
106
114
typedef struct PBMSBlobURL {
107
115
        char                                    bu_data[PBMS_BLOB_URL_SIZE];
108
116
} PBMSBlobURLRec, *PBMSBlobURLPtr;
109
117
 
110
 
typedef struct PBMSFieldRef {
111
 
        char                                    fr_column[PBMS_FIELD_COL_SIZE];
112
 
        char                                    fr_cond[PBMS_FIELD_COND_SIZE];
113
 
} PBMSFieldRefRec, *PBMSFieldRefPtr;
114
 
/*
115
 
 * The engine must free its resources for the given thread.
116
 
 */
117
 
typedef void (*MSCloseConnFunc)(void *thd);
118
 
 
119
 
/* Before access BLOBs of a table, the streaming engine will open the table.
120
 
 * Open tables are managed as a pool by the streaming engine.
121
 
 * When a request is received, the streaming engine will ask all
122
 
 * registered engine to open the table. The engine must return a NULL
123
 
 * open_table pointer if it does not handle the table.
124
 
 * A callback allows an engine to request all open tables to be
125
 
 * closed by the streaming engine.
126
 
 */
127
 
typedef int (*MSOpenTableFunc)(void *thd, const char *table_url, void **open_table, PBMSResultPtr result);
128
 
typedef void (*MSCloseTableFunc)(void *thd, void *open_table);
129
 
 
130
 
/*
131
 
 * When the streaming engine wants to use an open table handle from the
132
 
 * pool, it calls the lock table function.
133
 
 */ 
134
 
typedef int (*MSLockTableFunc)(void *thd, int *xact, void *open_table, int lock_type, PBMSResultPtr result);
135
 
typedef int (*MSUnlockTableFunc)(void *thd, int xact, void *open_table, PBMSResultPtr result);
136
 
 
137
 
/* This function is used to locate and send a BLOB on the given stream.
138
 
 */
139
 
typedef int (*MSSendBLOBFunc)(void *thd, void *open_table, const char *blob_column, const char *blob_url, void *stream, PBMSResultPtr result);
140
 
 
141
 
/*
142
 
 * Lookup and engine reference, and return readable text.
143
 
 */
144
 
typedef int (*MSLookupRefFunc)(void *thd, void *open_table, unsigned short col_index, PBMSEngineRefPtr eng_ref, PBMSFieldRefPtr feild_ref, PBMSResultPtr result);
145
 
 
146
118
typedef struct PBMSEngineRec {
147
119
        int                                             ms_version;                                                     /* MS_ENGINE_VERSION */
148
120
        int                                             ms_index;                                                       /* The index into the engine list. */
149
121
        int                                             ms_removing;                                            /* TRUE (1) if the engine is being removed. */
150
 
        const char                              *ms_engine_name;
151
 
        void                                    *ms_engine_info;
152
 
        MSCloseConnFunc                 ms_close_conn;
153
 
        MSOpenTableFunc                 ms_open_table;
154
 
        MSCloseTableFunc                ms_close_table;
155
 
        MSLockTableFunc                 ms_lock_table;
156
 
        MSUnlockTableFunc               ms_unlock_table;
157
 
        MSSendBLOBFunc                  ms_send_blob;
158
 
        MSLookupRefFunc                 ms_lookup_ref;
 
122
        int                                             ms_internal;                                            /* TRUE (1) if the engine is supported directly in the mysq/drizzle handler code . */
 
123
        char                                    ms_engine_name[32];
159
124
} PBMSEngineRec, *PBMSEnginePtr;
160
125
 
161
126
/*
162
127
 * This function should never be called directly, it is called
163
128
 * by deregisterEngine() below.
164
129
 */
 
130
typedef void (*ECRegisterdFunc)(PBMSEnginePtr engine);
 
131
 
165
132
typedef void (*ECDeregisterdFunc)(PBMSEnginePtr engine);
166
133
 
167
 
typedef void (*ECTableCloseAllFunc)(const char *table_url);
168
 
 
169
 
typedef int (*ECSetContentLenFunc)(void *stream, off_t len, PBMSResultPtr result);
170
 
 
171
 
typedef int (*ECWriteHeadFunc)(void *stream, PBMSResultPtr result);
172
 
 
173
 
typedef int (*ECWriteStreamFunc)(void *stream, void *buffer, size_t len, PBMSResultPtr result);
174
 
 
175
 
/*
176
 
 * The engine should call this function from
177
 
 * its own close connection function!
178
 
 */
179
 
typedef int (*ECCloseConnFunc)(void *thd, PBMSResultPtr result);
180
 
 
181
 
/*
182
 
 * Call this function before retaining or releasing BLOBs in a row.
183
 
 */
184
 
typedef int (*ECOpenTableFunc)(void **open_table, char *table_path, PBMSResultPtr result);
185
 
 
186
 
/*
187
 
 * Call this function when the operation is complete.
188
 
 */
189
 
typedef void (*ECCloseTableFunc)(void *open_table);
 
134
/*
 
135
 * Call this function to store a BLOB in the repository the BLOB's
 
136
 * URL will be returned. The returned URL buffer is expected to be atleast 
 
137
 * PBMS_BLOB_URL_SIZE long.
 
138
 *
 
139
 * The BLOB URL must still be retained or it will automaticly be deleted after a timeout expires.
 
140
 */
 
141
typedef int (*ECCreateBlobsFunc)(bool built_in, const char *db_name, const char *tab_name, char *blob, size_t blob_len, char *blob_url, unsigned short col_index, PBMSResultPtr result);
190
142
 
191
143
/*
192
144
 * Call this function for each BLOB to be retained. When a BLOB is used, the 
193
 
 * URL may be changed. The returned URL is valid as long as the the
194
 
 * table is open.
 
145
 * URL may be changed. The returned URL buffer is expected to be atleast 
 
146
 * PBMS_BLOB_URL_SIZE long.
195
147
 *
196
148
 * The returned URL must be inserted into the row in place of the given
197
149
 * URL.
198
150
 */
199
 
typedef int (*ECUseBlobFunc)(void *open_table, char **ret_blob_url, char *blob_url, unsigned short col_index, PBMSResultPtr result);
200
 
 
201
 
/*
202
 
 * Reference Blobs that has been uploaded to the streaming engine.
203
 
 *
204
 
 * All BLOBs specified by the use blob function are retained by
205
 
 * this function.
206
 
 *
207
 
 * The engine reference is a (unaligned) 8 byte value which
208
 
 * identifies the row that the BLOBs are in.
209
 
 */
210
 
typedef int (*ECRetainBlobsFunc)(void *open_table, PBMSEngineRefPtr eng_ref, PBMSResultPtr result);
 
151
typedef int (*ECRetainBlobsFunc)(bool built_in, const char *db_name, const char *tab_name, char *ret_blob_url, char *blob_url, unsigned short col_index, PBMSResultPtr result);
211
152
 
212
153
/*
213
154
 * If a row containing a BLOB is deleted, then the BLOBs in the
216
157
 * Note: if a table is dropped, all the BLOBs referenced by the
217
158
 * table are automatically released.
218
159
 */
219
 
typedef int (*ECReleaseBlobFunc)(void *open_table, char *blob_url, unsigned short col_index, PBMSEngineRefPtr eng_ref, PBMSResultPtr result);
220
 
 
221
 
typedef int (*ECDropTable)(const char *table_path, PBMSResultPtr result);
222
 
 
223
 
typedef int (*ECRenameTable)(const char *from_table, const char *to_table, PBMSResultPtr result);
 
160
typedef int (*ECReleaseBlobFunc)(bool built_in, const char *db_name, const char *tab_name, char *blob_url, PBMSResultPtr result);
 
161
 
 
162
typedef int (*ECDropTable)(bool built_in, const char *db_name, const char *tab_name, PBMSResultPtr result);
 
163
 
 
164
typedef int (*ECRenameTable)(bool built_in, const char *db_name, const char *from_table, const char *to_table, PBMSResultPtr result);
 
165
 
 
166
typedef void (*ECCallCompleted)(bool built_in, bool ok);
224
167
 
225
168
typedef struct PBMSCallbacksRec {
226
169
        int                                             cb_version;                                                     /* MS_CALLBACK_VERSION */
 
170
        ECRegisterdFunc                 cb_register;
227
171
        ECDeregisterdFunc               cb_deregister;
228
 
        ECTableCloseAllFunc             cb_table_close_all;
229
 
        ECSetContentLenFunc             cb_set_cont_len;
230
 
        ECWriteHeadFunc                 cb_write_head;
231
 
        ECWriteStreamFunc               cb_write_stream;
232
 
        ECCloseConnFunc                 cb_close_conn;
233
 
        ECOpenTableFunc                 cb_open_table;
234
 
        ECCloseTableFunc                cb_close_table;
235
 
        ECUseBlobFunc                   cb_use_blob;
236
 
        ECRetainBlobsFunc               cb_retain_blobs;
 
172
        ECCreateBlobsFunc               cb_create_blob;
 
173
        ECRetainBlobsFunc               cb_retain_blob;
237
174
        ECReleaseBlobFunc               cb_release_blob;
238
175
        ECDropTable                             cb_drop_table;
239
176
        ECRenameTable                   cb_rename_table;
 
177
        ECCallCompleted                 cb_completed;
240
178
} PBMSCallbacksRec, *PBMSCallbacksPtr;
241
179
 
242
180
typedef struct PBMSSharedMemoryRec {
251
189
        PBMSEnginePtr                   sm_engine_list[MS_ENGINE_LIST_SIZE];
252
190
} PBMSSharedMemoryRec, *PBMSSharedMemoryPtr;
253
191
 
254
 
#ifndef PBMS_API
255
 
#ifndef PBMS_CLIENT_API
256
 
Please define he value of PBMS_API
257
 
#endif
258
 
#else
 
192
#ifdef PBMS_API
259
193
 
260
194
class PBMS_API
261
195
{
262
196
private:
263
197
        const char *temp_prefix[3];
 
198
        bool built_in;
264
199
 
265
200
public:
266
201
        PBMS_API(): sharedMemory(NULL) { 
267
202
                int i = 0;
268
203
                temp_prefix[i++] = MS_TEMP_FILE_PREFIX;
269
 
#ifdef MS_TEMP_FILE_PREFIX
270
 
                temp_prefix[i++] = MS_TEMP_FILE_PREFIX;
271
 
#endif
272
204
                temp_prefix[i++] = NULL;
273
205
                
274
206
        }
276
208
        ~PBMS_API() { }
277
209
 
278
210
        /*
 
211
         * This method is called by the PBMS engine during startup.
 
212
         */
 
213
        int PBMSStartup(PBMSCallbacksPtr callbacks, PBMSResultPtr result) {
 
214
                int err;
 
215
                
 
216
                deleteTempFiles();
 
217
                err = getSharedMemory(true, result);
 
218
                if (!err)
 
219
                        sharedMemory->sm_callbacks = callbacks;
 
220
                        
 
221
                return err;
 
222
        }
 
223
 
 
224
        /*
 
225
         * This method is called by the PBMS engine during startup.
 
226
         */
 
227
        void PBMSShutdown() {
 
228
                
 
229
                if (!sharedMemory)
 
230
                        return;
 
231
                        
 
232
                lock();
 
233
                sharedMemory->sm_callbacks = NULL;
 
234
 
 
235
                bool empty = true;
 
236
                for (int i=0; i<sharedMemory->sm_list_len && empty; i++) {
 
237
                        if (sharedMemory->sm_engine_list[i]) 
 
238
                                empty = false;
 
239
                }
 
240
 
 
241
                unlock();
 
242
                
 
243
                if (empty) 
 
244
                        removeSharedMemory();
 
245
        }
 
246
 
 
247
        /*
279
248
         * Register the engine with the Stream Engine.
280
249
         */
281
250
        int registerEngine(PBMSEnginePtr engine, PBMSResultPtr result) {
283
252
 
284
253
                deleteTempFiles();
285
254
 
 
255
                // The first engine to register creates the shared memory.
286
256
                if ((err = getSharedMemory(true, result)))
287
257
                        return err;
288
258
 
292
262
                                engine->ms_index = i;
293
263
                                if (i >= sharedMemory->sm_list_len)
294
264
                                        sharedMemory->sm_list_len = i+1;
 
265
                                if (sharedMemory->sm_callbacks)
 
266
                                        sharedMemory->sm_callbacks->cb_register(engine);
 
267
                                        
 
268
                                built_in = (engine->ms_internal == 1);
295
269
                                return MS_OK;
296
270
                        }
297
271
                }
322
296
                PBMSResultRec result;
323
297
                int err;
324
298
 
325
 
                if ((err = getSharedMemory(true, &result)))
 
299
                if ((err = getSharedMemory(false, &result)))
326
300
                        return;
327
301
 
328
302
                lock();
342
316
 
343
317
                unlock();
344
318
 
345
 
                if (empty) {
346
 
                        char    temp_file[100];
347
 
 
348
 
                        sharedMemory->sm_magic = 0;
349
 
                        free(sharedMemory);
350
 
                        sharedMemory = NULL;
351
 
                        const char **prefix = temp_prefix;
352
 
                        while (*prefix) {
353
 
                                getTempFileName(temp_file, *prefix, getpid());
354
 
                                unlink(temp_file);
355
 
                                prefix++;
356
 
                        }
357
 
                }
 
319
                if (empty) 
 
320
                        removeSharedMemory();
358
321
        }
359
322
 
360
 
        void closeAllTables(const char *table_url)
 
323
        void removeSharedMemory() 
361
324
        {
362
 
                PBMSResultRec   result;
363
 
                int                                     err;
364
 
 
365
 
                if ((err = getSharedMemory(true, &result)))
366
 
                        return;
367
 
 
 
325
                const char **prefix = temp_prefix;
 
326
                char    temp_file[100];
 
327
 
 
328
                // Do not remove the sharfed memory until after
 
329
                // the PBMS engine has shutdown.
368
330
                if (sharedMemory->sm_callbacks)
369
 
                        sharedMemory->sm_callbacks->cb_table_close_all(table_url);
370
 
        }
371
 
 
372
 
        int setContentLength(void *stream, off_t len, PBMSResultPtr result)
373
 
        {
374
 
                int err;
375
 
 
376
 
                if ((err = getSharedMemory(true, result)))
377
 
                        return err;
378
 
 
379
 
                return sharedMemory->sm_callbacks->cb_set_cont_len(stream, len, result);
380
 
        }
381
 
 
382
 
        int writeHead(void *stream, PBMSResultPtr result)
383
 
        {
384
 
                int err;
385
 
 
386
 
                if ((err = getSharedMemory(true, result)))
387
 
                        return err;
388
 
 
389
 
                return sharedMemory->sm_callbacks->cb_write_head(stream, result);
390
 
        }
391
 
 
392
 
        int writeStream(void *stream, void *buffer, size_t len, PBMSResultPtr result)
393
 
        {
394
 
                int err;
395
 
 
396
 
                if ((err = getSharedMemory(true, result)))
397
 
                        return err;
398
 
 
399
 
                return sharedMemory->sm_callbacks->cb_write_stream(stream, buffer, len, result);
400
 
        }
401
 
 
402
 
        int closeConn(void *thd, PBMSResultPtr result)
403
 
        {
404
 
                int err;
405
 
 
406
 
                if ((err = getSharedMemory(true, result)))
407
 
                        return err;
408
 
 
409
 
                if (!sharedMemory->sm_callbacks)
410
 
                        return MS_OK;
411
 
 
412
 
                return sharedMemory->sm_callbacks->cb_close_conn(thd, result);
413
 
        }
414
 
 
415
 
        int openTable(void **open_table, char *table_path, PBMSResultPtr result)
416
 
        {
417
 
                int err;
418
 
 
419
 
                if ((err = getSharedMemory(true, result)))
420
 
                        return err;
421
 
 
422
 
                if (!sharedMemory->sm_callbacks) {
423
 
                        *open_table = NULL;
424
 
                        return MS_OK;
 
331
                        return;
 
332
                        
 
333
                sharedMemory->sm_magic = 0;
 
334
                free(sharedMemory);
 
335
                sharedMemory = NULL;
 
336
                
 
337
                while (*prefix) {
 
338
                        getTempFileName(temp_file, *prefix, getpid());
 
339
                        unlink(temp_file);
 
340
                        prefix++;
425
341
                }
426
 
 
427
 
                return sharedMemory->sm_callbacks->cb_open_table(open_table, table_path, result);
428
 
        }
429
 
 
430
 
        int closeTable(void *open_table, PBMSResultPtr result)
431
 
        {
432
 
                int err;
433
 
 
434
 
                if ((err = getSharedMemory(true, result)))
435
 
                        return err;
436
 
 
437
 
                if (sharedMemory->sm_callbacks && open_table)
438
 
                        sharedMemory->sm_callbacks->cb_close_table(open_table);
439
 
                return MS_OK;
440
 
        }
441
 
 
 
342
        }
 
343
        
442
344
        int couldBeURL(char *blob_url)
443
 
        /* ~*test/~1-150-2b5e0a7-0[*<blob size>][.ext] */
444
 
        /* ~*test/_1-150-2b5e0a7-0[*<blob size>][.ext] */
445
345
        {
446
 
                char    *ptr;
447
 
                size_t  len;
448
 
                bool have_blob_size = false;
449
 
 
450
346
                if (blob_url) {
451
 
                        if ((len = strlen(blob_url))) {
452
 
                                /* Too short: */
453
 
                                if (len <= 10)
454
 
                                        return 0;
455
 
 
456
 
                                /* Required prefix: */
457
 
                                /* NOTE: ~> is deprecated v0.5.4+, now use ~* */
458
 
                                if (*blob_url != '~' || (*(blob_url + 1) != '>' && *(blob_url + 1) != '*'))
459
 
                                        return 0;
460
 
 
461
 
                                ptr = blob_url + len - 1;
462
 
 
463
 
                                /* Allow for an optional extension: */
464
 
                                if (!isdigit(*ptr)) {
465
 
                                        while (ptr > blob_url && *ptr != '/' && *ptr != '.')
466
 
                                                ptr--;
467
 
                                        if (ptr == blob_url || *ptr != '.')
468
 
                                                return 0;
469
 
                                        if (ptr == blob_url || !isdigit(*ptr))
470
 
                                                return 0;
471
 
                                }
472
 
        
473
 
                                // field 1: server id OR blob size
474
 
                                do_again:
475
 
                                while (ptr > blob_url && isdigit(*ptr))
476
 
                                        ptr--;
477
 
 
478
 
                                if (ptr != blob_url && *ptr == '*' && !have_blob_size) {
479
 
                                        ptr--;
480
 
                                        have_blob_size = true;
481
 
                                        goto do_again;
482
 
                                }
483
 
                                
484
 
                                if (ptr == blob_url || *ptr != '-')
485
 
                                        return 0;
486
 
                                        
487
 
                                        
488
 
                                // field 2: Authoration code
489
 
                                ptr--;
490
 
                                if (!isxdigit(*ptr))
491
 
                                        return 0;
492
 
 
493
 
                                while (ptr > blob_url && isxdigit(*ptr))
494
 
                                        ptr--;
495
 
 
496
 
                                if (ptr == blob_url || *ptr != '-')
497
 
                                        return 0;
498
 
                                        
499
 
                                // field 3:offset
500
 
                                ptr--;
501
 
                                if (!isxdigit(*ptr))
502
 
                                        return 0;
503
 
                                        
504
 
                                while (ptr > blob_url && isdigit(*ptr))
505
 
                                        ptr--;
506
 
 
507
 
                                if (ptr == blob_url || *ptr != '-')
508
 
                                        return 0;
509
 
                                        
510
 
                                        
511
 
                                // field 4:Table id
512
 
                                ptr--;
513
 
                                if (!isdigit(*ptr))
514
 
                                        return 0;
515
 
 
516
 
                                while (ptr > blob_url && isdigit(*ptr))
517
 
                                        ptr--;
518
 
 
519
 
                                /* NOTE: ^ and : are deprecated v0.5.4+, now use ! and ~ */
520
 
                                if (ptr == blob_url || (*ptr != '^' && *ptr != ':' && *ptr != '_' && *ptr != '~'))
521
 
                                        return 0;
522
 
                                ptr--;
523
 
 
524
 
                                if (ptr == blob_url || *ptr != '/')
525
 
                                        return 0;
526
 
                                ptr--;
527
 
                                if (ptr == blob_url)
528
 
                                        return 0;
529
 
                                return 1;
530
 
                        }
 
347
                        u_int32_t               db_id = 0;
 
348
                        u_int32_t               tab_id = 0;
 
349
                        u_int64_t               blob_id = 0;
 
350
                        u_int64_t               blob_ref_id = 0;
 
351
                        u_int64_t               blob_size = 0;
 
352
                        u_int32_t               auth_code = 0;
 
353
                        u_int32_t               server_id = 0;
 
354
                        char            type, junk[5];
 
355
                        int                     scanned;
 
356
 
 
357
                        junk[0] = 0;
 
358
                        scanned = sscanf(blob_url, URL_FMT"%4s", &db_id, &type, &tab_id, &blob_id, &auth_code, &server_id, &blob_ref_id, &blob_size, junk);
 
359
                        if (scanned != 8) // If junk is found at the end this will also result in an invalid URL. 
 
360
                                return 0;
 
361
                        
 
362
                        if (junk[0] || (type != '~' && type != '_'))
 
363
                                return 0;
 
364
                
 
365
                        return 1;
531
366
                }
 
367
                
532
368
                return 0;
533
369
        }
534
 
 
535
 
        int useBlob(void *open_table, char **ret_blob_url, char *blob_url, unsigned short col_index, PBMSResultPtr result)
 
370
        
 
371
        int  retainBlob(const char *db_name, const char *tab_name, char *ret_blob_url, char *blob_url, size_t blob_size, unsigned short col_index, PBMSResultPtr result)
536
372
        {
537
373
                int err;
538
374
 
539
 
                if ((err = getSharedMemory(true, result)))
 
375
                if ((err = getSharedMemory(false, result)))
540
376
                        return err;
541
377
 
542
378
                if (!couldBeURL(blob_url)) {
543
 
                        *ret_blob_url = NULL;
544
 
                        return MS_OK;
 
379
                
 
380
                        if (!sharedMemory->sm_callbacks)  {
 
381
                                *ret_blob_url = 0;
 
382
                                return MS_OK;
 
383
                        }
 
384
                        err = sharedMemory->sm_callbacks->cb_create_blob(built_in, db_name, tab_name, blob_url, blob_size, ret_blob_url, col_index, result);
 
385
                        if (err)
 
386
                                return err;
 
387
                                
 
388
                        blob_url = ret_blob_url;
545
389
                }
546
390
 
547
391
                if (!sharedMemory->sm_callbacks) {
551
395
                        return MS_ERR_INCORRECT_URL;
552
396
                }
553
397
 
554
 
                return sharedMemory->sm_callbacks->cb_use_blob(open_table, ret_blob_url, blob_url, col_index, result);
555
 
        }
556
 
 
557
 
        int retainBlobs(void *open_table, PBMSEngineRefPtr eng_ref, PBMSResultPtr result)
558
 
        {
559
 
                int err;
560
 
 
561
 
                if ((err = getSharedMemory(true, result)))
562
 
                        return err;
563
 
 
564
 
                if (!sharedMemory->sm_callbacks)
565
 
                        return MS_OK;
566
 
 
567
 
                return sharedMemory->sm_callbacks->cb_retain_blobs(open_table, eng_ref, result);
568
 
        }
569
 
 
570
 
        int releaseBlob(void *open_table, char *blob_url, unsigned short col_index, PBMSEngineRefPtr eng_ref, PBMSResultPtr result)
571
 
        {
572
 
                int err;
573
 
 
574
 
                if ((err = getSharedMemory(true, result)))
 
398
                return sharedMemory->sm_callbacks->cb_retain_blob(built_in, db_name, tab_name, ret_blob_url, blob_url, col_index, result);
 
399
        }
 
400
 
 
401
        int releaseBlob(const char *db_name, const char *tab_name, char *blob_url, PBMSResultPtr result)
 
402
        {
 
403
                int err;
 
404
 
 
405
                if ((err = getSharedMemory(false, result)))
575
406
                        return err;
576
407
 
577
408
                if (!sharedMemory->sm_callbacks)
580
411
                if (!couldBeURL(blob_url))
581
412
                        return MS_OK;
582
413
 
583
 
                return sharedMemory->sm_callbacks->cb_release_blob(open_table, blob_url, col_index, eng_ref, result);
584
 
        }
585
 
 
586
 
        int dropTable(const char *table_path, PBMSResultPtr result)
587
 
        {
588
 
                int err;
589
 
 
590
 
                if ((err = getSharedMemory(true, result)))
591
 
                        return err;
592
 
 
593
 
                if (!sharedMemory->sm_callbacks)
594
 
                        return MS_OK;
595
 
                        
596
 
                return sharedMemory->sm_callbacks->cb_drop_table(table_path, result);
597
 
        }
598
 
 
599
 
        int renameTable(const char *from_table, const char *to_table, PBMSResultPtr result)
600
 
        {
601
 
                int err;
602
 
 
603
 
                if ((err = getSharedMemory(true, result)))
604
 
                        return err;
605
 
 
606
 
                if (!sharedMemory->sm_callbacks)
607
 
                        return MS_OK;
608
 
                        
609
 
                return sharedMemory->sm_callbacks->cb_rename_table(from_table, to_table, result);
610
 
        }
611
 
 
 
414
                return sharedMemory->sm_callbacks->cb_release_blob(built_in, db_name, tab_name, blob_url, result);
 
415
        }
 
416
 
 
417
        int dropTable(const char *db_name, const char *tab_name, PBMSResultPtr result)
 
418
        {
 
419
                int err;
 
420
 
 
421
                if ((err = getSharedMemory(false, result)))
 
422
                        return err;
 
423
 
 
424
                if (!sharedMemory->sm_callbacks)
 
425
                        return MS_OK;
 
426
                        
 
427
                return sharedMemory->sm_callbacks->cb_drop_table(built_in, db_name, tab_name, result);
 
428
        }
 
429
 
 
430
        int renameTable(const char *db_name, const char *from_table, const char *to_table, PBMSResultPtr result)
 
431
        {
 
432
                int err;
 
433
 
 
434
                if ((err = getSharedMemory(false, result)))
 
435
                        return err;
 
436
 
 
437
                if (!sharedMemory->sm_callbacks)
 
438
                        return MS_OK;
 
439
                        
 
440
                return sharedMemory->sm_callbacks->cb_rename_table(built_in, db_name, from_table, to_table, result);
 
441
        }
 
442
 
 
443
        void completed(int ok)
 
444
        {
 
445
                PBMSResultRec result;
 
446
 
 
447
                if (getSharedMemory(false, &result))
 
448
                        return;
 
449
 
 
450
                if (!sharedMemory->sm_callbacks)
 
451
                        return;
 
452
                        
 
453
                sharedMemory->sm_callbacks->cb_completed(built_in, ok);
 
454
        }
 
455
        
612
456
        volatile PBMSSharedMemoryPtr sharedMemory;
613
457
 
614
458
private:
618
462
                int             r;
619
463
                char    temp_file[100];
620
464
                const char      **prefix = temp_prefix;
621
 
                void            *tmp_p = NULL;
622
465
 
623
466
                if (sharedMemory)
624
467
                        return MS_OK;
644
487
                        }
645
488
 
646
489
                        buffer[tfer] = 0;
647
 
                        sscanf(buffer, "%p", &tmp_p);
648
 
                        sharedMemory = (PBMSSharedMemoryPtr) tmp_p;
 
490
                        sscanf(buffer, "%p", &sharedMemory);
649
491
                        if (!sharedMemory || sharedMemory->sm_magic != MS_SHARED_MEMORY_MAGIC) {
650
492
                                if (!create)
651
493
                                        return MS_OK;
661
503
                                        return setOSResult(errno, "fseek", temp_file, result);
662
504
                                }
663
505
 
664
 
                                sprintf(buffer, "%p", (void *) sharedMemory);
 
506
                                sprintf(buffer, "%p", sharedMemory);
665
507
                                tfer = write(tmp_f, buffer, strlen(buffer));
666
 
                                if (tfer != (ssize_t) strlen(buffer)) {
 
508
                                if (tfer != strlen(buffer)) {
667
509
                                        close(tmp_f);
668
510
                                        return setOSResult(errno, "write", temp_file, result);
669
511
                                }
838
680
extern void PBMSGetError(void *v_bs_thread, PBMSResultPtr result);
839
681
 
840
682
/* 
841
 
* PBMSCreateBlob():Creates a new blob in the database of the given size. cont_type can be NULL.
 
683
* PBMSCreateBlob():Creates a new blob in the database of the given size.
842
684
*/
843
 
extern bool PBMSCreateBlob(PBMSBlobIDPtr blob_id, char *database_name, char *cont_type, u_int64_t size);
 
685
extern bool PBMSCreateBlob(PBMSBlobIDPtr blob_id, char *database_name, u_int64_t size);
844
686
 
845
687
/* 
846
688
* PBMSWriteBlob():Write the data to the blob in one or more chunks. The total size of all the chuncks of 
847
689
* data written to the blob must match the size specified when the blob was created.
848
690
*/
849
 
extern bool PBMSWriteBlob(PBMSBlobIDPtr blob_id, char *database_name, char *data, size_t size, size_t offset);
 
691
extern bool PBMSWriteBlob(PBMSBlobIDPtr blob_id, char *data, size_t size, size_t offset);
850
692
 
851
693
/* 
852
694
* PBMSReadBlob():Read the blob data out of the blob in one or more chunks.
853
695
*/
854
 
extern bool PBMSReadBlob(PBMSBlobIDPtr blob_id, char *database_name, char *buffer, size_t *size, size_t offset);
 
696
extern bool PBMSReadBlob(PBMSBlobIDPtr blob_id, char *buffer, size_t *size, size_t offset);
855
697
 
856
698
/*
857
699
* PBMSIDToURL():Convert a blob id to a blob URL. The 'url' buffer must be atleast  PBMS_BLOB_URL_SIZE bytes in size.
858
700
*/
859
 
extern bool PBMSIDToURL(PBMSBlobIDPtr blob_id, char *database_name, char *url);
 
701
extern bool PBMSIDToURL(PBMSBlobIDPtr blob_id, char *url);
860
702
 
861
703
/*
862
704
* PBMSIDToURL():Convert a blob URL to a blob ID.