~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Lee Bieber
  • Date: 2010-10-22 16:47:38 UTC
  • mfrom: (1841.1.7 drizzle_pbms)
  • Revision ID: kalebral@gmail.com-20101022164738-vv8w22b8towpb307
Merge Barry - fix bug 657830: PBMS build failure in GCC 4.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
#include "CSConfig.h"
30
30
 
31
 
#ifndef XT_WIN
 
31
#ifdef OS_WINDOWS
 
32
#include <sys/utime.h>
 
33
#define utimes(f, s) _utime(f, s)
 
34
#else
32
35
#include <unistd.h>
33
36
#include <dirent.h>
 
37
#include <sys/time.h>
34
38
#endif
35
39
#include <stdio.h>
36
 
#include <sys/stat.h>
37
 
#include <fcntl.h>
 
40
 
38
41
#include <errno.h>
39
42
#include <string.h>
40
43
 
 
44
#include "CSGlobal.h"
41
45
#include "CSFile.h"
42
46
#include "CSStream.h"
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
 
}
 
47
#include "CSMd5.h"
 
48
 
 
49
#define IS_MODE(m, s) ((m & s) == s)
55
50
 
56
51
/*
57
52
 * ---------------------------------------------------------------
85
80
        return CSFileInputStream::newStream(RETAIN(this), offset);
86
81
}
87
82
 
 
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
 
88
113
void CSFile::open(int mode)
89
114
{
90
 
        CSPath  *dir;
91
 
        bool    retry = false;
92
 
 
93
 
        CLOBBER_PROTECT(retry);
94
 
 
95
115
        enter_();
96
116
        if (mode & CREATE) {
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);
 
117
                bool retry = false;
 
118
                while ((retry = try_CreateAndOpen(self, mode, retry)) == true){}                
125
119
        }
126
120
        else
127
121
                openFile(mode);
128
122
        exit_();
129
123
}
130
124
 
 
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
 
131
140
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)
132
141
{
133
142
        size_t tfer;
 
143
        enter_();
 
144
        
 
145
        push_(dst_file);
 
146
        push_(src_file);
134
147
 
135
148
        while (size > 0) {
136
149
                if (size > (off64_t) buffer_size)
138
151
                else
139
152
                        tfer = (size_t) size;
140
153
                if (!(tfer = src_file->read(buffer, src_offset, tfer, 0)))
141
 
                        return false;
 
154
                        break;
142
155
                dst_file->write(buffer, dst_offset, tfer);
143
156
                dst_offset += tfer;
144
157
                src_offset += tfer;
145
158
                size -= tfer;
146
159
        }
147
 
        return true;
 
160
        
 
161
        release_(src_file);
 
162
        release_(dst_file);
 
163
        return_(size == 0);
148
164
}
149
165
 
150
166
void CSFile::streamOut(CSOutputStream *dst_stream, off64_t src_offset, off64_t size, char *buffer, size_t buffer_size)
151
167
{
152
168
        size_t tfer;
 
169
        enter_();
 
170
        
 
171
        push_(dst_stream);
153
172
 
154
173
        while (size > 0) {
155
174
                if (size > (off64_t) buffer_size)
163
182
                src_offset += tfer;
164
183
                size -= tfer;
165
184
        }
 
185
        
 
186
        release_(dst_stream);
 
187
        exit_();
166
188
}
167
189
 
168
190
#define CS_MASK                         ((S_IRUSR | S_IWUSR) | (S_IRGRP | S_IWGRP) | (S_IROTH))
169
191
 
 
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
 
170
200
void CSFile::close()
171
201
{
172
 
        if (iFH != -1) {
173
 
                unix_file_close(iFH);
174
 
                iFH = -1;
175
 
        }
 
202
        while (iLocked)
 
203
                unlock();
 
204
        sf_close();
176
205
}
177
206
 
178
207
off64_t CSFile::getEOF()
179
208
{
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;
 
209
     return sf_getEOF();
186
210
}
187
211
 
188
212
void CSFile::setEOF(off64_t offset)
189
213
{
190
 
        if (ftruncate(iFH, offset) == -1)
191
 
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
 
214
        sf_setEOF(offset);
192
215
}
193
216
 
194
217
size_t CSFile::read(void *data, off64_t offset, size_t size, size_t min_size)
195
218
{
196
 
        ssize_t read_size;
 
219
        size_t read_size;
197
220
        
198
221
        enter_();
199
 
        read_size = pread(iFH, data, size, offset);
 
222
        read_size = sf_pread(data, size, offset);
200
223
        self->interrupted();
201
 
        if (read_size ==  -1)
202
 
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
203
 
        if ((size_t) read_size < min_size)
 
224
        if (read_size < min_size)
204
225
                CSException::throwEOFError(CS_CONTEXT, myFilePath->getCString());
205
226
        return_(read_size);
206
227
}
207
228
 
208
229
void CSFile::write(const void *data, off64_t offset, size_t size)
209
230
{
210
 
        size_t write_size;
211
 
 
212
231
        enter_();
213
 
    write_size = pwrite(iFH, (void *) data, size, offset);
 
232
    sf_pwrite(data, size, offset);
214
233
        self->interrupted();
215
 
        if (write_size != size)
216
 
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
217
234
        exit_();
218
235
}
219
236
 
223
240
 
224
241
void CSFile::sync()
225
242
{
226
 
        fsync(iFH);
 
243
        sf_sync();
227
244
}
228
245
 
229
246
CSFile *CSFile::newFile(CSPath *path)
246
263
        return newFile(path);
247
264
}
248
265
 
 
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
 
249
274
void CSFile::openFile(int mode)
250
275
{
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;
 
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));
260
281
        
261
 
        if ((iFH = unix_file_open(myFilePath->getCString(), flags, CS_MASK)) ==  -1)
262
 
                CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
263
 
 
 
282
        iMode = mode;
264
283
        /* Does not make sense to truncate, and have READONLY! */
265
 
        if ((mode & TRUNCATE) && !(mode & READONLY))
 
284
        if (IS_MODE(mode, TRUNCATE) && !IS_MODE(mode, READONLY))
266
285
                setEOF((off64_t) 0);
267
286
}
268
287
 
 
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
 
269
309
/*
270
310
 * ---------------------------------------------------------------
271
311
 * A READ BUFFERED FILE
312
352
                iBufferDataLen = 0;
313
353
        }
314
354
        else if (offset < iFileBufferOffset + iBufferDataLen)
315
 
                iBufferDataLen = offset - iFileBufferOffset;
 
355
                iBufferDataLen = (size_t)(offset - iFileBufferOffset);
316
356
}
317
357
 
318
358
size_t CSReadBufferedFile::read(void *data, off64_t offset, size_t size, size_t min_size)
330
370
                        }
331
371
                        if (offset + size > iFileBufferOffset) {
332
372
                                // 2
333
 
                                tfer = offset + size - iFileBufferOffset;
 
373
                                tfer = (size_t)(offset + size - iFileBufferOffset);
334
374
                                memcpy((char *) data + (iFileBufferOffset - offset), iFileBuffer, tfer);
335
375
                                size -= tfer;
336
376
                        }
361
401
                }
362
402
                if (offset < iFileBufferOffset + iBufferDataLen) {
363
403
                        // 4 We assume we are reading front to back
364
 
                        tfer = iFileBufferOffset + iBufferDataLen - offset;
 
404
                        tfer = (size_t)(iFileBufferOffset + iBufferDataLen - offset);
365
405
                        memcpy(data, iFileBuffer + (offset - iFileBufferOffset), tfer);
366
406
                        data = (char *) data + tfer;
367
407
                        size -= tfer;
401
441
                        }
402
442
                        else if (offset + size > iFileBufferOffset) {
403
443
                                // 2
404
 
                                tfer = offset + size - iFileBufferOffset;
 
444
                                tfer = (size_t)(offset + size - iFileBufferOffset);
405
445
                                memcpy(iFileBuffer, (char *) data + (iFileBufferOffset - offset), tfer);
406
446
                        }
407
447
                }
411
451
                }
412
452
                else if (offset < iFileBufferOffset + iBufferDataLen) {
413
453
                        // 4 We assume we are reading front to back
414
 
                        tfer = iFileBufferOffset + iBufferDataLen - offset;
 
454
                        tfer = (size_t)(iFileBufferOffset + iBufferDataLen - offset);
415
455
                        memcpy(iFileBuffer + (offset - iFileBufferOffset), data, tfer);
416
456
                }
417
457
                // else 5
441
481
        myFile->openFile(mode);
442
482
}
443
483
 
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
 
}
498
484
 
499
485
/*
500
486
 * ---------------------------------------------------------------