bson_ext 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,229 +0,0 @@
1
- /* bson.h */
2
-
3
- /* Copyright 2009, 2010 10gen Inc.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
-
18
- #ifndef _BSON_H_
19
- #define _BSON_H_
20
-
21
- #include "platform_hacks.h"
22
- #include <time.h>
23
-
24
- MONGO_EXTERN_C_START
25
-
26
- typedef enum {
27
- bson_eoo=0 ,
28
- bson_double=1,
29
- bson_string=2,
30
- bson_object=3,
31
- bson_array=4,
32
- bson_bindata=5,
33
- bson_undefined=6,
34
- bson_oid=7,
35
- bson_bool=8,
36
- bson_date=9,
37
- bson_null=10,
38
- bson_regex=11,
39
- bson_dbref=12, /* deprecated */
40
- bson_code=13,
41
- bson_symbol=14,
42
- bson_codewscope=15,
43
- bson_int = 16,
44
- bson_timestamp = 17,
45
- bson_long = 18
46
- } bson_type;
47
-
48
- typedef int bson_bool_t;
49
-
50
- typedef struct {
51
- char * data;
52
- bson_bool_t owned;
53
- } bson;
54
-
55
- typedef struct {
56
- const char * cur;
57
- bson_bool_t first;
58
- } bson_iterator;
59
-
60
- typedef struct {
61
- char * buf;
62
- char * cur;
63
- int bufSize;
64
- bson_bool_t finished;
65
- int stack[32];
66
- int stackPos;
67
- } bson_buffer;
68
-
69
- #pragma pack(1)
70
- typedef union{
71
- char bytes[12];
72
- int ints[3];
73
- } bson_oid_t;
74
- #pragma pack()
75
-
76
- typedef int64_t bson_date_t; /* milliseconds since epoch UTC */
77
-
78
- typedef struct {
79
- int i; /* increment */
80
- int t; /* time in seconds */
81
- } bson_timestamp_t;
82
-
83
- /* ----------------------------
84
- READING
85
- ------------------------------ */
86
-
87
- bson * bson_empty(bson * obj); /* returns pointer to static empty bson object */
88
- void bson_copy(bson* out, const bson* in); /* puts data in new buffer. NOOP if out==NULL */
89
- bson * bson_from_buffer(bson * b, bson_buffer * buf);
90
- bson * bson_init( bson * b , char * data , bson_bool_t mine );
91
- int bson_size(const bson * b );
92
- void bson_destroy( bson * b );
93
-
94
- void bson_print( bson * b );
95
- void bson_print_raw( const char * bson , int depth );
96
-
97
- /* advances iterator to named field */
98
- /* returns bson_eoo (which is false) if field not found */
99
- bson_type bson_find(bson_iterator* it, const bson* obj, const char* name);
100
-
101
- void bson_iterator_init( bson_iterator * i , const char * bson );
102
-
103
- /* more returns true for eoo. best to loop with bson_iterator_next(&it) */
104
- bson_bool_t bson_iterator_more( const bson_iterator * i );
105
- bson_type bson_iterator_next( bson_iterator * i );
106
-
107
- bson_type bson_iterator_type( const bson_iterator * i );
108
- const char * bson_iterator_key( const bson_iterator * i );
109
- const char * bson_iterator_value( const bson_iterator * i );
110
-
111
- /* these convert to the right type (return 0 if non-numeric) */
112
- double bson_iterator_double( const bson_iterator * i );
113
- int bson_iterator_int( const bson_iterator * i );
114
- int64_t bson_iterator_long( const bson_iterator * i );
115
-
116
- /* return the bson timestamp as a whole or in parts */
117
- bson_timestamp_t bson_iterator_timestamp( const bson_iterator * i );
118
-
119
- /* false: boolean false, 0 in any type, or null */
120
- /* true: anything else (even empty strings and objects) */
121
- bson_bool_t bson_iterator_bool( const bson_iterator * i );
122
-
123
- /* these assume you are using the right type */
124
- double bson_iterator_double_raw( const bson_iterator * i );
125
- int bson_iterator_int_raw( const bson_iterator * i );
126
- int64_t bson_iterator_long_raw( const bson_iterator * i );
127
- bson_bool_t bson_iterator_bool_raw( const bson_iterator * i );
128
- bson_oid_t* bson_iterator_oid( const bson_iterator * i );
129
-
130
- /* these can also be used with bson_code and bson_symbol*/
131
- const char * bson_iterator_string( const bson_iterator * i );
132
- int bson_iterator_string_len( const bson_iterator * i );
133
-
134
- /* works with bson_code, bson_codewscope, and bson_string */
135
- /* returns NULL for everything else */
136
- const char * bson_iterator_code(const bson_iterator * i);
137
-
138
- /* calls bson_empty on scope if not a bson_codewscope */
139
- void bson_iterator_code_scope(const bson_iterator * i, bson * scope);
140
-
141
- /* both of these only work with bson_date */
142
- bson_date_t bson_iterator_date(const bson_iterator * i);
143
- time_t bson_iterator_time_t(const bson_iterator * i);
144
-
145
- int bson_iterator_bin_len( const bson_iterator * i );
146
- char bson_iterator_bin_type( const bson_iterator * i );
147
- const char * bson_iterator_bin_data( const bson_iterator * i );
148
-
149
- const char * bson_iterator_regex( const bson_iterator * i );
150
- const char * bson_iterator_regex_opts( const bson_iterator * i );
151
-
152
- /* these work with bson_object and bson_array */
153
- void bson_iterator_subobject(const bson_iterator * i, bson * sub);
154
- void bson_iterator_subiterator(const bson_iterator * i, bson_iterator * sub);
155
-
156
- /* str must be at least 24 hex chars + null byte */
157
- void bson_oid_from_string(bson_oid_t* oid, const char* str);
158
- void bson_oid_to_string(const bson_oid_t* oid, char* str);
159
- void bson_oid_gen(bson_oid_t* oid);
160
-
161
- time_t bson_oid_generated_time(bson_oid_t* oid); /* Gives the time the OID was created */
162
-
163
- /* ----------------------------
164
- BUILDING
165
- ------------------------------ */
166
-
167
- bson_buffer * bson_buffer_init( bson_buffer * b );
168
- bson_buffer * bson_ensure_space( bson_buffer * b , const int bytesNeeded );
169
-
170
- /**
171
- * @return the raw data. you either should free this OR call bson_destroy not both
172
- */
173
- char * bson_buffer_finish( bson_buffer * b );
174
- void bson_buffer_destroy( bson_buffer * b );
175
-
176
- bson_buffer * bson_append_oid( bson_buffer * b , const char * name , const bson_oid_t* oid );
177
- bson_buffer * bson_append_new_oid( bson_buffer * b , const char * name );
178
- bson_buffer * bson_append_int( bson_buffer * b , const char * name , const int i );
179
- bson_buffer * bson_append_long( bson_buffer * b , const char * name , const int64_t i );
180
- bson_buffer * bson_append_double( bson_buffer * b , const char * name , const double d );
181
- bson_buffer * bson_append_string( bson_buffer * b , const char * name , const char * str );
182
- bson_buffer * bson_append_string_n( bson_buffer * b, const char * name, const char * str , int len);
183
- bson_buffer * bson_append_symbol( bson_buffer * b , const char * name , const char * str );
184
- bson_buffer * bson_append_symbol_n( bson_buffer * b , const char * name , const char * str , int len );
185
- bson_buffer * bson_append_code( bson_buffer * b , const char * name , const char * str );
186
- bson_buffer * bson_append_code_n( bson_buffer * b , const char * name , const char * str , int len );
187
- bson_buffer * bson_append_code_w_scope( bson_buffer * b , const char * name , const char * code , const bson * scope);
188
- bson_buffer * bson_append_code_w_scope_n( bson_buffer * b , const char * name , const char * code , int size , const bson * scope);
189
- bson_buffer * bson_append_binary( bson_buffer * b, const char * name, char type, const char * str, int len );
190
- bson_buffer * bson_append_bool( bson_buffer * b , const char * name , const bson_bool_t v );
191
- bson_buffer * bson_append_null( bson_buffer * b , const char * name );
192
- bson_buffer * bson_append_undefined( bson_buffer * b , const char * name );
193
- bson_buffer * bson_append_regex( bson_buffer * b , const char * name , const char * pattern, const char * opts );
194
- bson_buffer * bson_append_bson( bson_buffer * b , const char * name , const bson* bson);
195
- bson_buffer * bson_append_element( bson_buffer * b, const char * name_or_null, const bson_iterator* elem);
196
- bson_buffer * bson_append_timestamp( bson_buffer * b, const char * name, bson_timestamp_t * ts );
197
-
198
- /* these both append a bson_date */
199
- bson_buffer * bson_append_date(bson_buffer * b, const char * name, bson_date_t millis);
200
- bson_buffer * bson_append_time_t(bson_buffer * b, const char * name, time_t secs);
201
-
202
- bson_buffer * bson_append_start_object( bson_buffer * b , const char * name );
203
- bson_buffer * bson_append_start_array( bson_buffer * b , const char * name );
204
- bson_buffer * bson_append_finish_object( bson_buffer * b );
205
-
206
- void bson_numstr(char* str, int i);
207
- void bson_incnumstr(char* str);
208
-
209
-
210
- /* ------------------------------
211
- ERROR HANDLING - also used in mongo code
212
- ------------------------------ */
213
-
214
- void * bson_malloc(int size); /* checks return value */
215
- void * bson_realloc(void * ptr, int size); /* checks return value */
216
-
217
- /* bson_err_handlers shouldn't return!!! */
218
- typedef void(*bson_err_handler)(const char* errmsg);
219
-
220
- /* returns old handler or NULL */
221
- /* default handler prints error then exits with failure*/
222
- bson_err_handler set_bson_err_handler(bson_err_handler func);
223
-
224
- /* does nothing is ok != 0 */
225
- void bson_fatal( int ok );
226
- void bson_fatal_msg( int ok, const char* msg );
227
-
228
- MONGO_EXTERN_C_END
229
- #endif
@@ -1,799 +0,0 @@
1
- /*--------------------------------------------------------------------*/
2
- /* gridfs.c */
3
- /* Author: Christopher Triolo */
4
- /*--------------------------------------------------------------------*/
5
-
6
- #include "gridfs.h"
7
- #include "mongo.h"
8
- #include "bson.h"
9
- #include <stdio.h>
10
- #include <stdlib.h>
11
- #include <string.h>
12
- #include <assert.h>
13
- #define TRUE 1
14
- #define FALSE 0
15
-
16
-
17
- /*--------------------------------------------------------------------*/
18
-
19
- static bson * chunk_new(bson_oid_t id, int chunkNumber,
20
- const char * data, int len)
21
-
22
- {
23
- bson * b;
24
- bson_buffer buf;
25
-
26
- b = (bson *)bson_malloc(sizeof(bson));
27
- if (b == NULL) return NULL;
28
-
29
- bson_buffer_init(&buf);
30
- bson_append_oid(&buf, "files_id", &id);
31
- bson_append_int(&buf, "n", chunkNumber);
32
- bson_append_binary(&buf, "data", 2, data, len);
33
- bson_from_buffer(b, &buf);
34
- return b;
35
- }
36
-
37
- /*--------------------------------------------------------------------*/
38
-
39
- static void chunk_free(bson * oChunk)
40
-
41
- {
42
- bson_destroy(oChunk);
43
- free(oChunk);
44
- }
45
-
46
- /*--------------------------------------------------------------------*/
47
-
48
- int gridfs_init(mongo_connection * client, const char * dbname,
49
- const char * prefix, gridfs* gfs)
50
- {
51
- int options;
52
- bson_buffer bb;
53
- bson b;
54
- bson out;
55
- bson_bool_t success;
56
-
57
- gfs->client = client;
58
-
59
- /* Allocate space to own the dbname */
60
- gfs->dbname = (const char *)bson_malloc(strlen(dbname)+1);
61
- if (gfs->dbname == NULL) {
62
- return FALSE;
63
- }
64
- strcpy((char*)gfs->dbname, dbname);
65
-
66
- /* Allocate space to own the prefix */
67
- if (prefix == NULL) prefix = "fs";
68
- gfs->prefix = (const char *)bson_malloc(strlen(prefix)+1);
69
- if (gfs->prefix == NULL) {
70
- free((char*)gfs->dbname);
71
- return FALSE;
72
- }
73
- strcpy((char *)gfs->prefix, prefix);
74
-
75
- /* Allocate space to own files_ns */
76
- gfs->files_ns =
77
- (const char *) bson_malloc (strlen(prefix)+strlen(dbname)+strlen(".files")+2);
78
- if (gfs->files_ns == NULL) {
79
- free((char*)gfs->dbname);
80
- free((char*)gfs->prefix);
81
- return FALSE;
82
- }
83
- strcpy((char*)gfs->files_ns, dbname);
84
- strcat((char*)gfs->files_ns, ".");
85
- strcat((char*)gfs->files_ns, prefix);
86
- strcat((char*)gfs->files_ns, ".files");
87
-
88
- /* Allocate space to own chunks_ns */
89
- gfs->chunks_ns = (const char *) bson_malloc(strlen(prefix) + strlen(dbname)
90
- + strlen(".chunks") + 2);
91
- if (gfs->chunks_ns == NULL) {
92
- free((char*)gfs->dbname);
93
- free((char*)gfs->prefix);
94
- free((char*)gfs->files_ns);
95
- return FALSE;
96
- }
97
- strcpy((char*)gfs->chunks_ns, dbname);
98
- strcat((char*)gfs->chunks_ns, ".");
99
- strcat((char*)gfs->chunks_ns, prefix);
100
- strcat((char*)gfs->chunks_ns, ".chunks");
101
-
102
- bson_buffer_init(&bb);
103
- bson_append_int(&bb, "filename", 1);
104
- bson_from_buffer(&b, &bb);
105
- options = 0;
106
- success = mongo_create_index(gfs->client, gfs->files_ns, &b, options, &out);
107
- bson_destroy(&b);
108
- if (!success) {
109
- free((char*)gfs->dbname);
110
- free((char*)gfs->prefix);
111
- free((char*)gfs->files_ns);
112
- free((char*)gfs->chunks_ns);
113
- return FALSE;
114
- }
115
-
116
- bson_buffer_init(&bb);
117
- bson_append_int(&bb, "files_id", 1);
118
- bson_append_int(&bb, "n", 1);
119
- bson_from_buffer(&b, &bb);
120
- options = MONGO_INDEX_UNIQUE;
121
- success = mongo_create_index(gfs->client, gfs->chunks_ns, &b, options, &out);
122
- bson_destroy(&b);
123
- if (!success) {
124
- free((char*)gfs->dbname);
125
- free((char*)gfs->prefix);
126
- free((char*)gfs->files_ns);
127
- free((char*)gfs->chunks_ns);
128
- return FALSE;
129
- }
130
-
131
- return TRUE;
132
- }
133
-
134
- /*--------------------------------------------------------------------*/
135
-
136
- void gridfs_destroy(gridfs* gfs)
137
-
138
- {
139
- if (gfs == NULL) return;
140
- if (gfs->dbname) free((char*)gfs->dbname);
141
- if (gfs->prefix) free((char*)gfs->prefix);
142
- if (gfs->files_ns) free((char*)gfs->files_ns);
143
- if (gfs->chunks_ns) free((char*)gfs->chunks_ns);
144
- }
145
-
146
- /*--------------------------------------------------------------------*/
147
-
148
- static bson gridfs_insert_file( gridfs* gfs, const char* name,
149
- const bson_oid_t id, gridfs_offset length,
150
- const char* contenttype)
151
- {
152
- bson command;
153
- bson res;
154
- bson ret;
155
- bson_buffer buf;
156
- bson_iterator it;
157
-
158
- /* Check run md5 */
159
- bson_buffer_init(&buf);
160
- bson_append_oid(&buf, "filemd5", &id);
161
- bson_append_string(&buf, "root", gfs->prefix);
162
- bson_from_buffer(&command, &buf);
163
- assert(mongo_run_command(gfs->client, gfs->dbname,
164
- &command, &res));
165
- bson_destroy(&command);
166
-
167
- /* Create and insert BSON for file metadata */
168
- bson_buffer_init(&buf);
169
- bson_append_oid(&buf, "_id", &id);
170
- if (name != NULL && *name != '\0') {
171
- bson_append_string(&buf, "filename", name);
172
- }
173
- bson_append_long(&buf, "length", length);
174
- bson_append_int(&buf, "chunkSize", DEFAULT_CHUNK_SIZE);
175
- bson_append_date(&buf, "uploadDate", (bson_date_t)1000*time(NULL));
176
- bson_find(&it, &res, "md5");
177
- bson_append_string(&buf, "md5", bson_iterator_string(&it));
178
- bson_destroy(&res);
179
- if (contenttype != NULL && *contenttype != '\0') {
180
- bson_append_string(&buf, "contentType", contenttype);
181
- }
182
- bson_from_buffer(&ret, &buf);
183
- mongo_insert(gfs->client, gfs->files_ns, &ret);
184
-
185
- return ret;
186
- }
187
-
188
- /*--------------------------------------------------------------------*/
189
-
190
- bson gridfs_store_buffer( gridfs* gfs, const char* data,
191
- gridfs_offset length, const char* remotename,
192
- const char * contenttype)
193
-
194
- {
195
- char const * const end = data + length;
196
- bson_oid_t id;
197
- int chunkNumber = 0;
198
- int chunkLen;
199
- bson * oChunk;
200
-
201
- /* Large files Assertion */
202
- assert(length <= 0xffffffff);
203
-
204
- /* Generate and append an oid*/
205
- bson_oid_gen(&id);
206
-
207
- /* Insert the file's data chunk by chunk */
208
- while (data < end) {
209
- chunkLen = DEFAULT_CHUNK_SIZE < (unsigned int)(end - data) ?
210
- DEFAULT_CHUNK_SIZE : (unsigned int)(end - data);
211
- oChunk = chunk_new( id, chunkNumber, data, chunkLen );
212
- mongo_insert(gfs->client, gfs->chunks_ns, oChunk);
213
- chunk_free(oChunk);
214
- chunkNumber++;
215
- data += chunkLen;
216
- }
217
-
218
- /* Inserts file's metadata */
219
- return gridfs_insert_file(gfs, remotename, id, length, contenttype);
220
- }
221
-
222
- /*--------------------------------------------------------------------*/
223
-
224
- void gridfile_writer_init( gridfile* gfile, gridfs* gfs,
225
- const char* remote_name, const char* content_type )
226
- {
227
- gfile->gfs = gfs;
228
-
229
- bson_oid_gen( &(gfile->id) );
230
- gfile->chunk_num = 0;
231
- gfile->length = 0;
232
- gfile->pending_len = 0;
233
- gfile->pending_data = NULL;
234
-
235
- gfile->remote_name = (const char *)bson_malloc( strlen( remote_name ) + 1 );
236
- strcpy( (char *)gfile->remote_name, remote_name );
237
-
238
- gfile->content_type = (const char *)bson_malloc( strlen( content_type ) );
239
- strcpy( (char *)gfile->content_type, content_type );
240
- }
241
-
242
- /*--------------------------------------------------------------------*/
243
-
244
- void gridfile_write_buffer( gridfile* gfile, const char* data, gridfs_offset length )
245
- {
246
-
247
- int bytes_left = 0;
248
- int data_partial_len = 0;
249
- int chunks_to_write = 0;
250
- char* buffer;
251
- bson* oChunk;
252
- gridfs_offset to_write = length + gfile->pending_len;
253
-
254
- if ( to_write < DEFAULT_CHUNK_SIZE ) { /* Less than one chunk to write */
255
- if( gfile->pending_data ) {
256
- gfile->pending_data = (char *)bson_realloc((void *)gfile->pending_data, gfile->pending_len + to_write);
257
- memcpy( gfile->pending_data + gfile->pending_len, data, length );
258
- } else if (to_write > 0) {
259
- gfile->pending_data = (char *)bson_malloc(to_write);
260
- memcpy( gfile->pending_data, data, length );
261
- }
262
- gfile->pending_len += length;
263
-
264
- } else { /* At least one chunk of data to write */
265
-
266
- /* If there's a pending chunk to be written, we need to combine
267
- * the buffer provided up to DEFAULT_CHUNK_SIZE.
268
- */
269
- if ( gfile->pending_len > 0 ) {
270
- chunks_to_write = to_write / DEFAULT_CHUNK_SIZE;
271
- bytes_left = to_write % DEFAULT_CHUNK_SIZE;
272
-
273
- data_partial_len = DEFAULT_CHUNK_SIZE - gfile->pending_len;
274
- buffer = (char *)bson_malloc( DEFAULT_CHUNK_SIZE );
275
- memcpy(buffer, gfile->pending_data, gfile->pending_len);
276
- memcpy(buffer + gfile->pending_len, data, data_partial_len);
277
-
278
- oChunk = chunk_new(gfile->id, gfile->chunk_num, buffer, DEFAULT_CHUNK_SIZE);
279
- mongo_insert(gfile->gfs->client, gfile->gfs->chunks_ns, oChunk);
280
- chunk_free(oChunk);
281
- gfile->chunk_num++;
282
- gfile->length += DEFAULT_CHUNK_SIZE;
283
- data += data_partial_len;
284
-
285
- chunks_to_write--;
286
-
287
- free(buffer);
288
- }
289
-
290
- while( chunks_to_write > 0 ) {
291
- oChunk = chunk_new(gfile->id, gfile->chunk_num, data, DEFAULT_CHUNK_SIZE);
292
- mongo_insert(gfile->gfs->client, gfile->gfs->chunks_ns, oChunk);
293
- chunk_free(oChunk);
294
- gfile->chunk_num++;
295
- chunks_to_write--;
296
- gfile->length += DEFAULT_CHUNK_SIZE;
297
- data += DEFAULT_CHUNK_SIZE;
298
- }
299
-
300
- free(gfile->pending_data);
301
-
302
- /* If there are any leftover bytes, store them as pending data. */
303
- if( bytes_left == 0 )
304
- gfile->pending_data = NULL;
305
- else {
306
- gfile->pending_data = (char *)bson_malloc( bytes_left );
307
- memcpy( gfile->pending_data, data, bytes_left );
308
- }
309
-
310
- gfile->pending_len = bytes_left;
311
- }
312
- }
313
-
314
- /*--------------------------------------------------------------------*/
315
-
316
- bson gridfile_writer_done( gridfile* gfile )
317
- {
318
-
319
- /* write any remaining pending chunk data.
320
- * pending data will always take up less than one chunk
321
- */
322
- bson* oChunk;
323
- if( gfile->pending_data )
324
- {
325
- oChunk = chunk_new(gfile->id, gfile->chunk_num, gfile->pending_data, gfile->pending_len);
326
- mongo_insert(gfile->gfs->client, gfile->gfs->chunks_ns, oChunk);
327
- chunk_free(oChunk);
328
- free(gfile->pending_data);
329
- gfile->length += gfile->pending_len;
330
- }
331
-
332
- /* insert into files collection */
333
- return gridfs_insert_file(gfile->gfs, gfile->remote_name, gfile->id,
334
- gfile->length, gfile->content_type);
335
- }
336
-
337
- /*--------------------------------------------------------------------*/
338
-
339
- bson gridfs_store_file(gridfs* gfs, const char* filename,
340
- const char* remotename, const char* contenttype)
341
- {
342
- char buffer[DEFAULT_CHUNK_SIZE];
343
- FILE * fd;
344
- bson_oid_t id;
345
- int chunkNumber = 0;
346
- gridfs_offset length = 0;
347
- gridfs_offset chunkLen = 0;
348
- bson* oChunk;
349
-
350
- /* Open the file and the correct stream */
351
- if (strcmp(filename, "-") == 0) fd = stdin;
352
- else fd = fopen(filename, "rb");
353
- assert(fd != NULL); /* No such file */
354
-
355
- /* Generate and append an oid*/
356
- bson_oid_gen(&id);
357
-
358
- /* Insert the file chunk by chunk */
359
- chunkLen = fread(buffer, 1, DEFAULT_CHUNK_SIZE, fd);
360
- do {
361
- oChunk = chunk_new( id, chunkNumber, buffer, chunkLen );
362
- mongo_insert(gfs->client, gfs->chunks_ns, oChunk);
363
- chunk_free(oChunk);
364
- length += chunkLen;
365
- chunkNumber++;
366
- chunkLen = fread(buffer, 1, DEFAULT_CHUNK_SIZE, fd);
367
- } while (chunkLen != 0);
368
-
369
- /* Close the file stream */
370
- if (fd != stdin) fclose(fd);
371
-
372
- /* Large files Assertion */
373
- /* assert(length <= 0xffffffff); */
374
-
375
- /* Optional Remote Name */
376
- if (remotename == NULL || *remotename == '\0') {
377
- remotename = filename; }
378
-
379
- /* Inserts file's metadata */
380
- return gridfs_insert_file(gfs, remotename, id, length, contenttype);
381
- }
382
-
383
- /*--------------------------------------------------------------------*/
384
-
385
- void gridfs_remove_filename(gridfs* gfs, const char* filename )
386
-
387
- {
388
- bson query;
389
- bson_buffer buf;
390
- mongo_cursor* files;
391
- bson file;
392
- bson_iterator it;
393
- bson_oid_t id;
394
- bson b;
395
-
396
- bson_buffer_init(&buf);
397
- bson_append_string(&buf, "filename", filename);
398
- bson_from_buffer(&query, &buf);
399
- files = mongo_find(gfs->client, gfs->files_ns, &query, NULL, 0, 0, 0);
400
- bson_destroy(&query);
401
-
402
- /* Remove each file and it's chunks from files named filename */
403
- while (mongo_cursor_next(files)) {
404
- file = files->current;
405
- bson_find(&it, &file, "_id");
406
- id = *bson_iterator_oid(&it);
407
-
408
- /* Remove the file with the specified id */
409
- bson_buffer_init(&buf);
410
- bson_append_oid(&buf, "_id", &id);
411
- bson_from_buffer(&b, &buf);
412
- mongo_remove( gfs->client, gfs->files_ns, &b);
413
- bson_destroy(&b);
414
-
415
- /* Remove all chunks from the file with the specified id */
416
- bson_buffer_init(&buf);
417
- bson_append_oid(&buf, "files_id", &id);
418
- bson_from_buffer(&b, &buf);
419
- mongo_remove( gfs->client, gfs->chunks_ns, &b);
420
- bson_destroy(&b);
421
- }
422
-
423
- }
424
-
425
- /*--------------------------------------------------------------------*/
426
-
427
- int gridfs_find_query(gridfs* gfs, bson* query,
428
- gridfile* gfile )
429
-
430
- {
431
- bson_buffer date_buffer;
432
- bson uploadDate;
433
- bson_buffer buf;
434
- bson finalQuery;
435
- bson out;
436
- int i;
437
-
438
- bson_buffer_init(&date_buffer);
439
- bson_append_int(&date_buffer, "uploadDate", -1);
440
- bson_from_buffer(&uploadDate, &date_buffer);
441
- bson_buffer_init(&buf);
442
- bson_append_bson(&buf, "query", query);
443
- bson_append_bson(&buf, "orderby", &uploadDate);
444
- bson_from_buffer(&finalQuery, &buf);
445
-
446
-
447
- i = (mongo_find_one(gfs->client, gfs->files_ns,
448
- &finalQuery, NULL, &out));
449
- bson_destroy(&uploadDate);
450
- bson_destroy(&finalQuery);
451
- if (!i)
452
- return FALSE;
453
- else {
454
- gridfile_init(gfs, &out, gfile);
455
- bson_destroy(&out);
456
- return TRUE;
457
- }
458
- }
459
-
460
- /*--------------------------------------------------------------------*/
461
-
462
- int gridfs_find_filename(gridfs* gfs, const char* filename,
463
- gridfile* gfile)
464
-
465
- {
466
- bson query;
467
- bson_buffer buf;
468
- int i;
469
-
470
- bson_buffer_init(&buf);
471
- bson_append_string(&buf, "filename", filename);
472
- bson_from_buffer(&query, &buf) ;
473
- i = gridfs_find_query(gfs, &query, gfile);
474
- bson_destroy(&query);
475
- return i;
476
- }
477
-
478
- /*--------------------------------------------------------------------*/
479
-
480
- int gridfile_init(gridfs* gfs, bson* meta, gridfile* gfile)
481
-
482
- {
483
- gfile->gfs = gfs;
484
- gfile->pos = 0;
485
- gfile->meta = (bson*)bson_malloc(sizeof(bson));
486
- if (gfile->meta == NULL) return FALSE;
487
- bson_copy(gfile->meta, meta);
488
- return TRUE;
489
- }
490
-
491
- /*--------------------------------------------------------------------*/
492
-
493
- void gridfile_destroy(gridfile* gfile)
494
-
495
- {
496
- bson_destroy(gfile->meta);
497
- free(gfile->meta);
498
- }
499
-
500
- /*--------------------------------------------------------------------*/
501
-
502
- bson_bool_t gridfile_exists(gridfile* gfile)
503
-
504
- {
505
- return (bson_bool_t)(gfile != NULL || gfile->meta == NULL);
506
- }
507
-
508
- /*--------------------------------------------------------------------*/
509
-
510
- const char* gridfile_get_filename(gridfile* gfile)
511
-
512
- {
513
- bson_iterator it;
514
-
515
- bson_find(&it, gfile->meta, "filename");
516
- return bson_iterator_string(&it);
517
- }
518
-
519
- /*--------------------------------------------------------------------*/
520
-
521
- int gridfile_get_chunksize(gridfile* gfile)
522
-
523
- {
524
- bson_iterator it;
525
-
526
- bson_find(&it, gfile->meta, "chunkSize");
527
- return bson_iterator_int(&it);
528
- }
529
-
530
- /*--------------------------------------------------------------------*/
531
-
532
- gridfs_offset gridfile_get_contentlength(gridfile* gfile)
533
-
534
- {
535
- bson_iterator it;
536
-
537
- bson_find(&it, gfile->meta, "length");
538
-
539
- if( bson_iterator_type( &it ) == bson_int )
540
- return (gridfs_offset)bson_iterator_int( &it );
541
- else
542
- return (gridfs_offset)bson_iterator_long( &it );
543
- }
544
-
545
- /*--------------------------------------------------------------------*/
546
-
547
- const char *gridfile_get_contenttype(gridfile* gfile)
548
-
549
- {
550
- bson_iterator it;
551
-
552
- if (bson_find(&it, gfile->meta, "contentType"))
553
- return bson_iterator_string( &it );
554
- else return NULL;
555
- }
556
-
557
- /*--------------------------------------------------------------------*/
558
-
559
- bson_date_t gridfile_get_uploaddate(gridfile* gfile)
560
-
561
- {
562
- bson_iterator it;
563
-
564
- bson_find(&it, gfile->meta, "uploadDate");
565
- return bson_iterator_date( &it );
566
- }
567
-
568
- /*--------------------------------------------------------------------*/
569
-
570
- const char* gridfile_get_md5(gridfile* gfile)
571
-
572
- {
573
- bson_iterator it;
574
-
575
- bson_find(&it, gfile->meta, "md5");
576
- return bson_iterator_string( &it );
577
- }
578
-
579
- /*--------------------------------------------------------------------*/
580
-
581
- const char* gridfile_get_field(gridfile* gfile, const char* name)
582
-
583
- {
584
- bson_iterator it;
585
-
586
- bson_find(&it, gfile->meta, name);
587
- return bson_iterator_value( &it );
588
- }
589
-
590
- /*--------------------------------------------------------------------*/
591
-
592
- bson_bool_t gridfile_get_boolean(gridfile* gfile, const char* name)
593
- {
594
- bson_iterator it;
595
-
596
- bson_find(&it, gfile->meta, name);
597
- return bson_iterator_bool( &it );
598
- }
599
-
600
- /*--------------------------------------------------------------------*/
601
- bson gridfile_get_metadata(gridfile* gfile)
602
-
603
- {
604
- bson sub;
605
- bson_iterator it;
606
-
607
- if (bson_find(&it, gfile->meta, "metadata")) {
608
- bson_iterator_subobject( &it, &sub );
609
- return sub;
610
- }
611
- else {
612
- bson_empty(&sub);
613
- return sub;
614
- }
615
- }
616
-
617
- /*--------------------------------------------------------------------*/
618
-
619
- int gridfile_get_numchunks(gridfile* gfile)
620
-
621
- {
622
- bson_iterator it;
623
- gridfs_offset length;
624
- gridfs_offset chunkSize;
625
- double numchunks;
626
-
627
- bson_find(&it, gfile->meta, "length");
628
-
629
- if( bson_iterator_type( &it ) == bson_int )
630
- length = (gridfs_offset)bson_iterator_int( &it );
631
- else
632
- length = (gridfs_offset)bson_iterator_long( &it );
633
-
634
- bson_find(&it, gfile->meta, "chunkSize");
635
- chunkSize = bson_iterator_int(&it);
636
- numchunks = ((double)length/(double)chunkSize);
637
- return (numchunks - (int)numchunks > 0)
638
- ? (int)(numchunks+1)
639
- : (int)(numchunks);
640
- }
641
-
642
- /*--------------------------------------------------------------------*/
643
-
644
- bson gridfile_get_chunk(gridfile* gfile, int n)
645
-
646
- {
647
- bson query;
648
- bson out;
649
- bson_buffer buf;
650
- bson_iterator it;
651
- bson_oid_t id;
652
-
653
- bson_buffer_init(&buf);
654
- bson_find(&it, gfile->meta, "_id");
655
- id = *bson_iterator_oid(&it);
656
- bson_append_oid(&buf, "files_id", &id);
657
- bson_append_int(&buf, "n", n);
658
- bson_from_buffer(&query, &buf);
659
-
660
- assert(mongo_find_one(gfile->gfs->client,
661
- gfile->gfs->chunks_ns,
662
- &query, NULL, &out));
663
- return out;
664
- }
665
-
666
- /*--------------------------------------------------------------------*/
667
-
668
- mongo_cursor* gridfile_get_chunks(gridfile* gfile, int start, int size)
669
-
670
- {
671
- bson_iterator it;
672
- bson_oid_t id;
673
- bson_buffer gte_buf;
674
- bson gte_bson;
675
- bson_buffer query_buf;
676
- bson query_bson;
677
- bson_buffer orderby_buf;
678
- bson orderby_bson;
679
- bson_buffer command_buf;
680
- bson command_bson;
681
-
682
- bson_find(&it, gfile->meta, "_id");
683
- id = *bson_iterator_oid(&it);
684
-
685
- bson_buffer_init(&query_buf);
686
- bson_append_oid(&query_buf, "files_id", &id);
687
- if (size == 1) {
688
- bson_append_int(&query_buf, "n", start);
689
- } else {
690
- bson_buffer_init(&gte_buf);
691
- bson_append_int(&gte_buf, "$gte", start);
692
- bson_from_buffer(&gte_bson, &gte_buf);
693
- bson_append_bson(&query_buf, "n", &gte_bson);
694
- }
695
- bson_from_buffer(&query_bson, &query_buf);
696
-
697
- bson_buffer_init(&orderby_buf);
698
- bson_append_int(&orderby_buf, "n", 1);
699
- bson_from_buffer(&orderby_bson, &orderby_buf);
700
-
701
- bson_buffer_init(&command_buf);
702
- bson_append_bson(&command_buf, "query", &query_bson);
703
- bson_append_bson(&command_buf, "orderby", &orderby_bson);
704
- bson_from_buffer(&command_bson, &command_buf);
705
-
706
- return mongo_find(gfile->gfs->client, gfile->gfs->chunks_ns,
707
- &command_bson, NULL, size, 0, 0);
708
- }
709
-
710
- /*--------------------------------------------------------------------*/
711
-
712
- gridfs_offset gridfile_write_file(gridfile* gfile, FILE *stream)
713
-
714
- {
715
- int i;
716
- size_t len;
717
- bson chunk;
718
- bson_iterator it;
719
- const char* data;
720
- const int num = gridfile_get_numchunks( gfile );
721
-
722
- for ( i=0; i<num; i++ ){
723
- chunk = gridfile_get_chunk( gfile, i );
724
- bson_find( &it, &chunk, "data" );
725
- len = bson_iterator_bin_len( &it );
726
- data = bson_iterator_bin_data( &it );
727
- fwrite( data , sizeof(char), len, stream );
728
- }
729
-
730
- return gridfile_get_contentlength(gfile);
731
- }
732
-
733
- /*--------------------------------------------------------------------*/
734
-
735
- gridfs_offset gridfile_read(gridfile* gfile, gridfs_offset size, char* buf)
736
-
737
- {
738
- mongo_cursor* chunks;
739
- bson chunk;
740
-
741
- int first_chunk;
742
- int last_chunk;
743
- int total_chunks;
744
- gridfs_offset chunksize;
745
- gridfs_offset contentlength;
746
- gridfs_offset bytes_left;
747
- int i;
748
- bson_iterator it;
749
- gridfs_offset chunk_len;
750
- const char * chunk_data;
751
-
752
- contentlength = gridfile_get_contentlength(gfile);
753
- chunksize = gridfile_get_chunksize(gfile);
754
- size = (contentlength - gfile->pos < size)
755
- ? contentlength - gfile->pos
756
- : size;
757
- bytes_left = size;
758
-
759
- first_chunk = (gfile->pos)/chunksize;
760
- last_chunk = (gfile->pos+size-1)/chunksize;
761
- total_chunks = last_chunk - first_chunk + 1;
762
- chunks = gridfile_get_chunks(gfile, first_chunk, total_chunks);
763
-
764
- for (i = 0; i < total_chunks; i++) {
765
- mongo_cursor_next(chunks);
766
- chunk = chunks->current;
767
- bson_find(&it, &chunk, "data");
768
- chunk_len = bson_iterator_bin_len( &it );
769
- chunk_data = bson_iterator_bin_data( &it );
770
- if (i == 0) {
771
- chunk_data += (gfile->pos)%chunksize;
772
- chunk_len -= (gfile->pos)%chunksize;
773
- }
774
- if (bytes_left > chunk_len) {
775
- memcpy(buf, chunk_data, chunk_len);
776
- bytes_left -= chunk_len;
777
- buf += chunk_len;
778
- } else {
779
- memcpy(buf, chunk_data, bytes_left);
780
- }
781
- }
782
-
783
- mongo_cursor_destroy(chunks);
784
- gfile->pos = gfile->pos + size;
785
-
786
- return size;
787
- }
788
-
789
- /*--------------------------------------------------------------------*/
790
-
791
- gridfs_offset gridfile_seek(gridfile* gfile, gridfs_offset offset)
792
-
793
- {
794
- gridfs_offset length;
795
-
796
- length = gridfile_get_contentlength(gfile);
797
- gfile->pos = length < offset ? length : offset;
798
- return gfile->pos;
799
- }