~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/cslib/CSFile.cc

  • Committer: lbieber
  • Date: 2010-09-11 16:33:45 UTC
  • mfrom: (1757.1.2 build)
  • Revision ID: lbieber@orisndriz03-20100911163345-na1t8m18at9thsjl
Merge Vijay - added utf 8 tamil test case suite and test case for creating a database in tamil
Merge Brian - Small set of refactoring (includes one case of memset on a table object).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
 
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
2
2
 *
3
3
 * PrimeBase Media Stream for MySQL
4
4
 *
14
14
 *
15
15
 * You should have received a copy of the GNU General Public License
16
16
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
 *
19
19
 * Original author: Paul McCullagh (H&G2JCtL)
20
20
 * Continued development: Barry Leslie
28
28
 
29
29
#include "CSConfig.h"
30
30
 
31
 
#ifdef OS_WINDOWS
32
 
#include <sys/utime.h>
33
 
#define utimes(f, s) _utime(f, s)
34
 
#else
 
31
#ifndef XT_WIN
35
32
#include <unistd.h>
36
33
#include <dirent.h>
37
 
#include <sys/time.h>
38
34
#endif
39
35
#include <stdio.h>
40
 
 
 
36
#include <sys/stat.h>
 
37
#include <fcntl.h>
41
38
#include <errno.h>
42
39
#include <string.h>
43
40
 
44
 
#include "CSGlobal.h"
45
41
#include "CSFile.h"
46
42
#include "CSStream.h"
47
 
#include "CSMd5.h"
48
 
 
49
 
#define IS_MODE(m, s) ((m & s) == s)
 
43
#include "CSGlobal.h"
 
44
 
 
45
 
 
46
static int unix_file_open(const char *path, int flags, mode_t mode)
 
47
{
 
48
        return open(path, flags, mode);
 
49
}
 
50
 
 
51
int unix_file_close(int fh)
 
52
{
 
53
        return close(fh);
 
54
}
50
55
 
51
56
/*
52
57
 * ---------------------------------------------------------------
80
85
        return CSFileInputStream::newStream(RETAIN(this), offset);
81
86
}
82
87
 
83
 
bool CSFile::try_CreateAndOpen(CSThread *self, int mode, bool retry)
84
 
{
85
 
        volatile bool rtc = true;
86
 
        
87
 
        try_(a) {
88
 
                openFile(mode);
89
 
                rtc = false; // success, do not try again.
90
 
        }
91
 
        catch_(a) {
92
 
                if (retry || !isDirNotFound(&self->myException))
93
 
                        throw_();
94
 
 
95
 
                /* Make sure the parent directory exists: */
96
 
                CSPath  *dir = CSPath::newPath(RETAIN(myFilePath), "..");
97
 
                push_(dir);
98
 
                try_(b) {
99
 
                        dir->makePath();
100
 
                }
101
 
                catch_(b) { /* Two threads may try to create the directory at the same time. */
102
 
                        if (!isDirExists(&self->myException))
103
 
                                throw_();
104
 
                }
105
 
                cont_(b);
106
 
 
107
 
                release_(dir);
108
 
        }
109
 
        cont_(a);
110
 
        return rtc; // try again.
111
 
}
112
 
 
113
88
void CSFile::open(int mode)
114
89
{
 
90
        CSPath  *dir;
 
91
        bool    retry = false;
 
92
 
 
93
        CLOBBER_PROTECT(retry);
 
94
 
115
95
        enter_();
116
96
        if (mode & CREATE) {
117
 
                bool retry = false;
118
 
                while ((retry = try_CreateAndOpen(self, mode, retry)) == true){}                
 
97
                /* Create and open the file: */
 
98
                do {
 
99
                        try_(a) {
 
100
                                openFile(mode);
 
101
                                retry = false;
 
102
                        }
 
103
                        catch_(a) {
 
104
                                if (retry || !isDirNotFound(&self->myException))
 
105
                                        throw_();
 
106
 
 
107
                                /* Make sure the parent directory exists: */
 
108
                                dir = CSPath::newPath(RETAIN(myFilePath), "..");
 
109
                                push_(dir);
 
110
                                try_(b) {
 
111
                                        dir->makePath();
 
112
                                }
 
113
                                catch_(b) { /* Two threads may try to create the directory at the same time. */
 
114
                                        if (!isDirExists(&self->myException))
 
115
                                                throw_();
 
116
                                }
 
117
                                cont_(b);
 
118
 
 
119
                                release_(dir);
 
120
                                retry = true;
 
121
                        }
 
122
                        cont_(a);
 
123
                }
 
124
                while (retry);
119
125
        }
120
126
        else
121
127
                openFile(mode);
122
128
        exit_();
123
129
}
124
130
 
125
 
void CSFile::lock()
126
 
{
127
 
        if (!iLocked) {
128
 
                sf_lock(IS_MODE(iMode, READONLY));
129
 
        }
130
 
        iLocked++;
131
 
}
132
 
 
133
 
void CSFile::unlock()
134
 
{
135
 
        iLocked--;
136
 
        if (!iLocked) 
137
 
                sf_unlock();
138
 
}
139
 
 
140
131
bool CSFile::transfer(CSFile *dst_file, off64_t dst_offset, CSFile *src_file, off64_t src_offset, off64_t size, char *buffer, size_t buffer_size)
141
132
{
142
133
        size_t tfer;
143
 
        enter_();
144
 
        
145
 
        push_(dst_file);
146
 
        push_(src_file);
147
134
 
148
135
        while (size > 0) {
149
136
                if (size > (off64_t) buffer_size)
151
138
                else
152
139
                        tfer = (size_t) size;
153
140
                if (!(tfer = src_file->read(buffer, src_offset, tfer, 0)))
154
 
                        break;
 
141
                        return false;
155
142
                dst_file->write(buffer, dst_offset, tfer);
156
143
                dst_offset += tfer;
157
144
                src_offset += tfer;
158
145
                size -= tfer;
159
146
        }
160
 
        
161
 
        release_(src_file);
162
 
        release_(dst_file);
163
 
        return_(size == 0);
 
147
        return true;
164
148
}
165
149
 
166
150
void CSFile::streamOut(CSOutputStream *dst_stream, off64_t src_offset, off64_t size, char *buffer, size_t buffer_size)
167
151
{
168
152
        size_t tfer;
169
 
        enter_();
170
 
        
171
 
        push_(dst_stream);
172
153
 
173
154
        while (size > 0) {
174
155
                if (size > (off64_t) buffer_size)
182
163
                src_offset += tfer;
183
164
                size -= tfer;
184
165
        }
185
 
        
186
 
        release_(dst_stream);
187
 
        exit_();
188
166
}
189
167
 
190
168
#define CS_MASK                         ((S_IRUSR | S_IWUSR) | (S_IRGRP | S_IWGRP) | (S_IROTH))
191
169
 
192
 
void CSFile::touch()
193
 
{
194
 
        // don't use futimes() here. On some platforms it will fail if the 
195
 
        // file was opened readonly.
196
 
        if (utimes(myFilePath->getCString(), NULL) == -1)
197
 
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
198
 
}
199
 
 
200
170
void CSFile::close()
201
171
{
202
 
        while (iLocked)
203
 
                unlock();
204
 
        sf_close();
 
172
        if (iFH != -1) {
 
173
                unix_file_close(iFH);
 
174
                iFH = -1;
 
175
        }
205
176
}
206
177
 
207
178
off64_t CSFile::getEOF()
208
179
{
209
 
     return sf_getEOF();
 
180
        off64_t eof;
 
181
 
 
182
        if ((eof = lseek(iFH, 0, SEEK_END)) == (off64_t) -1)
 
183
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
 
184
 
 
185
     return eof;
210
186
}
211
187
 
212
188
void CSFile::setEOF(off64_t offset)
213
189
{
214
 
        sf_setEOF(offset);
 
190
        if (ftruncate(iFH, offset) == -1)
 
191
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
215
192
}
216
193
 
217
194
size_t CSFile::read(void *data, off64_t offset, size_t size, size_t min_size)
218
195
{
219
 
        size_t read_size;
 
196
        ssize_t read_size;
220
197
        
221
198
        enter_();
222
 
        read_size = sf_pread(data, size, offset);
 
199
        read_size = pread(iFH, data, size, offset);
223
200
        self->interrupted();
224
 
        if (read_size < min_size)
 
201
        if (read_size ==  -1)
 
202
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
 
203
        if ((size_t) read_size < min_size)
225
204
                CSException::throwEOFError(CS_CONTEXT, myFilePath->getCString());
226
205
        return_(read_size);
227
206
}
228
207
 
229
208
void CSFile::write(const void *data, off64_t offset, size_t size)
230
209
{
 
210
        size_t write_size;
 
211
 
231
212
        enter_();
232
 
    sf_pwrite(data, size, offset);
 
213
    write_size = pwrite(iFH, (void *) data, size, offset);
233
214
        self->interrupted();
 
215
        if (write_size != size)
 
216
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
234
217
        exit_();
235
218
}
236
219
 
240
223
 
241
224
void CSFile::sync()
242
225
{
243
 
        sf_sync();
 
226
        fsync(iFH);
244
227
}
245
228
 
246
229
CSFile *CSFile::newFile(CSPath *path)
263
246
        return newFile(path);
264
247
}
265
248
 
266
 
CSFile *CSFile::newFile(const char *dir_str, const char *path_str)
267
 
{
268
 
        CSPath *path;
269
 
 
270
 
        path = CSPath::newPath(dir_str, path_str);
271
 
        return newFile(path);
272
 
}
273
 
 
274
249
void CSFile::openFile(int mode)
275
250
{
276
 
        if (fs_isOpen() && (iMode != mode))
277
 
                close();
278
 
                
279
 
        if (!fs_isOpen())
280
 
                sf_open(myFilePath->getCString(), IS_MODE(mode, READONLY), IS_MODE(mode, CREATE));
 
251
        int flags = 0;
 
252
 
 
253
        if (mode & READONLY)
 
254
                flags = O_RDONLY;
 
255
        else
 
256
                flags = O_RDWR;
 
257
 
 
258
        if (mode & CREATE)
 
259
                flags |= O_CREAT;
281
260
        
282
 
        iMode = mode;
 
261
        if ((iFH = unix_file_open(myFilePath->getCString(), flags, CS_MASK)) ==  -1)
 
262
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
 
263
 
283
264
        /* Does not make sense to truncate, and have READONLY! */
284
 
        if (IS_MODE(mode, TRUNCATE) && !IS_MODE(mode, READONLY))
 
265
        if ((mode & TRUNCATE) && !(mode & READONLY))
285
266
                setEOF((off64_t) 0);
286
267
}
287
268
 
288
 
void CSFile::md5Digest(Md5Digest *digest)
289
 
{
290
 
        u_char buffer[1024];
291
 
        off64_t offset = 0, size;
292
 
        size_t len;
293
 
        CSMd5 md5;
294
 
        enter_();
295
 
        
296
 
        size = getEOF();
297
 
        while (size) {
298
 
                len = (size_t)((size < 1024)? size:1024);
299
 
                len = read(buffer, offset, len, len);
300
 
                offset +=len;
301
 
                size -= len;
302
 
                md5.md5_append(buffer, len);
303
 
        }
304
 
        md5.md5_get_digest(digest);
305
 
        exit_();
306
 
        
307
 
}
308
 
 
309
269
/*
310
270
 * ---------------------------------------------------------------
311
271
 * A READ BUFFERED FILE
352
312
                iBufferDataLen = 0;
353
313
        }
354
314
        else if (offset < iFileBufferOffset + iBufferDataLen)
355
 
                iBufferDataLen = (size_t)(offset - iFileBufferOffset);
 
315
                iBufferDataLen = offset - iFileBufferOffset;
356
316
}
357
317
 
358
318
size_t CSReadBufferedFile::read(void *data, off64_t offset, size_t size, size_t min_size)
370
330
                        }
371
331
                        if (offset + size > iFileBufferOffset) {
372
332
                                // 2
373
 
                                tfer = (size_t)(offset + size - iFileBufferOffset);
 
333
                                tfer = offset + size - iFileBufferOffset;
374
334
                                memcpy((char *) data + (iFileBufferOffset - offset), iFileBuffer, tfer);
375
335
                                size -= tfer;
376
336
                        }
401
361
                }
402
362
                if (offset < iFileBufferOffset + iBufferDataLen) {
403
363
                        // 4 We assume we are reading front to back
404
 
                        tfer = (size_t)(iFileBufferOffset + iBufferDataLen - offset);
 
364
                        tfer = iFileBufferOffset + iBufferDataLen - offset;
405
365
                        memcpy(data, iFileBuffer + (offset - iFileBufferOffset), tfer);
406
366
                        data = (char *) data + tfer;
407
367
                        size -= tfer;
441
401
                        }
442
402
                        else if (offset + size > iFileBufferOffset) {
443
403
                                // 2
444
 
                                tfer = (size_t)(offset + size - iFileBufferOffset);
 
404
                                tfer = offset + size - iFileBufferOffset;
445
405
                                memcpy(iFileBuffer, (char *) data + (iFileBufferOffset - offset), tfer);
446
406
                        }
447
407
                }
451
411
                }
452
412
                else if (offset < iFileBufferOffset + iBufferDataLen) {
453
413
                        // 4 We assume we are reading front to back
454
 
                        tfer = (size_t)(iFileBufferOffset + iBufferDataLen - offset);
 
414
                        tfer = iFileBufferOffset + iBufferDataLen - offset;
455
415
                        memcpy(iFileBuffer + (offset - iFileBufferOffset), data, tfer);
456
416
                }
457
417
                // else 5
481
441
        myFile->openFile(mode);
482
442
}
483
443
 
 
444
CSFile *CSReadBufferedFile::newFile(CSFile *file)
 
445
{
 
446
        CSReadBufferedFile *f;
 
447
 
 
448
        if (!(f = new CSReadBufferedFile())) {
 
449
                file->release();
 
450
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
 
451
        }
 
452
        f->myFile = file;
 
453
        f->myFilePath = file->myFilePath;
 
454
        f->myFilePath->retain();
 
455
        return (CSFile *) f;
 
456
}
 
457
 
 
458
/*
 
459
 * ---------------------------------------------------------------
 
460
 * A BUFFERED FILE
 
461
 */
 
462
 
 
463
void CSBufferedFile::write(const void *data, off64_t offset, size_t size)
 
464
{
 
465
        if (iBufferDataLen > 0) {
 
466
                if (offset < iFileBufferOffset && offset <= iFileBufferOffset + iBufferDataLen) {
 
467
                        size_t tfer;
 
468
 
 
469
                        tfer = iFileBufferOffset + SC_DEFAULT_FILE_BUFFER_SIZE - offset;
 
470
                        if (tfer >= size) {
 
471
                                memcpy(iFileBuffer + (offset - iFileBufferOffset), data, size);
 
472
                        }
 
473
                        size -= tfer;
 
474
                        data = (char *) data + tfer;
 
475
                }
 
476
                flush();
 
477
        }
 
478
 
 
479
        if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
 
480
                iFileBufferOffset = offset;
 
481
                iBufferDataLen = size;
 
482
                memcpy(iFileBuffer, data, size);
 
483
                iBufferDirty = true;
 
484
        }
 
485
        else
 
486
                myFile->write(data, offset, size);
 
487
}
 
488
 
 
489
void CSBufferedFile::flush()
 
490
{
 
491
        if (iBufferDirty && iBufferDataLen) {
 
492
                myFile->write(iFileBuffer, iFileBufferOffset, iBufferDataLen);
 
493
                iBufferDirty = false;
 
494
                
 
495
        }
 
496
        myFile->flush();
 
497
}
484
498
 
485
499
/*
486
500
 * ---------------------------------------------------------------