~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Prafulla Tekawade
  • Date: 2010-07-13 16:07:35 UTC
  • mto: (1662.1.4 rollup)
  • mto: This revision was merged to the branch mainline in revision 1664.
  • Revision ID: prafulla_t@users.sourceforge.net-20100713160735-2fsdtrm3azayuyu1
This bug is simillar to mysql bug 36133
http://bugs.mysql.com/bug.php?id=36133

Taking changes from that fix.

  - The problem was that the range optimizer evaluated constant expressions, 
    and among them it would try to evaluate IN-subquery predicates slated for
    handling with materialization strategy. However, these predicates require
    that parent_join->setup_subquery_materialization() is invoked before one
    attempts to evaluate them.
  
  - Fixed by making the range optimizer not to evaluate expressions that have
    item->is_expensive() == TRUE (these are materialization subqueries and 
    stored function calls). This should also resolve the problem that EXPLAIN 
    may be too long. 
    This change cuts off some opportunities for range optimizer, but this is 
    the price we're willing to pay for separation of query optimization and
    execution. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
2
 
 *
3
 
 * PrimeBase Media Stream for MySQL
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
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
18
 
 *
19
 
 * Original author: Paul McCullagh (H&G2JCtL)
20
 
 * Continued development: Barry Leslie
21
 
 *
22
 
 * 2007-06-07
23
 
 *
24
 
 * CORE SYSTEM:
25
 
 * Basic file I/O.
26
 
 *
27
 
 */
28
 
 
29
 
#include "CSConfig.h"
30
 
 
31
 
#ifdef OS_WINDOWS
32
 
#include <sys/utime.h>
33
 
#define utimes(f, s) _utime(f, s)
34
 
#else
35
 
#include <unistd.h>
36
 
#include <dirent.h>
37
 
#include <sys/time.h>
38
 
#endif
39
 
#include <stdio.h>
40
 
 
41
 
#include <errno.h>
42
 
#include <string.h>
43
 
 
44
 
#include "CSGlobal.h"
45
 
#include "CSFile.h"
46
 
#include "CSStream.h"
47
 
#include "CSMd5.h"
48
 
 
49
 
#define IS_MODE(m, s) ((m & s) == s)
50
 
 
51
 
/*
52
 
 * ---------------------------------------------------------------
53
 
 * CORE SYSTEM FILES
54
 
 */
55
 
 
56
 
CSFile::~CSFile()
57
 
{
58
 
        close();
59
 
        if (myFilePath)
60
 
                myFilePath->release();
61
 
}
62
 
 
63
 
CSOutputStream *CSFile::getOutputStream()
64
 
{
65
 
        return CSFileOutputStream::newStream(RETAIN(this));
66
 
}
67
 
 
68
 
CSOutputStream *CSFile::getOutputStream(off64_t offset)
69
 
{
70
 
        return CSFileOutputStream::newStream(RETAIN(this), offset);
71
 
}
72
 
 
73
 
CSInputStream *CSFile::getInputStream()
74
 
{
75
 
        return CSFileInputStream::newStream(RETAIN(this));
76
 
}
77
 
 
78
 
CSInputStream *CSFile::getInputStream(off64_t offset)
79
 
{
80
 
        return CSFileInputStream::newStream(RETAIN(this), offset);
81
 
}
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
 
 
113
 
void CSFile::open(int mode)
114
 
{
115
 
        enter_();
116
 
        if (mode & CREATE) {
117
 
                bool retry = false;
118
 
                while ((retry = try_CreateAndOpen(self, mode, retry)) == true){}                
119
 
        }
120
 
        else
121
 
                openFile(mode);
122
 
        exit_();
123
 
}
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
 
 
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)
141
 
{
142
 
        size_t tfer;
143
 
        enter_();
144
 
        
145
 
        push_(dst_file);
146
 
        push_(src_file);
147
 
 
148
 
        while (size > 0) {
149
 
                if (size > (off64_t) buffer_size)
150
 
                        tfer = buffer_size;
151
 
                else
152
 
                        tfer = (size_t) size;
153
 
                if (!(tfer = src_file->read(buffer, src_offset, tfer, 0)))
154
 
                        break;
155
 
                dst_file->write(buffer, dst_offset, tfer);
156
 
                dst_offset += tfer;
157
 
                src_offset += tfer;
158
 
                size -= tfer;
159
 
        }
160
 
        
161
 
        release_(src_file);
162
 
        release_(dst_file);
163
 
        return_(size == 0);
164
 
}
165
 
 
166
 
void CSFile::streamOut(CSOutputStream *dst_stream, off64_t src_offset, off64_t size, char *buffer, size_t buffer_size)
167
 
{
168
 
        size_t tfer;
169
 
        enter_();
170
 
        
171
 
        push_(dst_stream);
172
 
 
173
 
        while (size > 0) {
174
 
                if (size > (off64_t) buffer_size)
175
 
                        tfer = buffer_size;
176
 
                else
177
 
                        tfer = (size_t) size;
178
 
      
179
 
                read(buffer, src_offset, tfer, tfer);
180
 
                dst_stream->write(buffer, tfer);
181
 
    
182
 
                src_offset += tfer;
183
 
                size -= tfer;
184
 
        }
185
 
        
186
 
        release_(dst_stream);
187
 
        exit_();
188
 
}
189
 
 
190
 
#define CS_MASK                         ((S_IRUSR | S_IWUSR) | (S_IRGRP | S_IWGRP) | (S_IROTH))
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
 
 
200
 
void CSFile::close()
201
 
{
202
 
        while (iLocked)
203
 
                unlock();
204
 
        sf_close();
205
 
}
206
 
 
207
 
off64_t CSFile::getEOF()
208
 
{
209
 
     return sf_getEOF();
210
 
}
211
 
 
212
 
void CSFile::setEOF(off64_t offset)
213
 
{
214
 
        sf_setEOF(offset);
215
 
}
216
 
 
217
 
size_t CSFile::read(void *data, off64_t offset, size_t size, size_t min_size)
218
 
{
219
 
        size_t read_size;
220
 
        
221
 
        enter_();
222
 
        read_size = sf_pread(data, size, offset);
223
 
        self->interrupted();
224
 
        if (read_size < min_size)
225
 
                CSException::throwEOFError(CS_CONTEXT, myFilePath->getCString());
226
 
        return_(read_size);
227
 
}
228
 
 
229
 
void CSFile::write(const void *data, off64_t offset, size_t size)
230
 
{
231
 
        enter_();
232
 
    sf_pwrite(data, size, offset);
233
 
        self->interrupted();
234
 
        exit_();
235
 
}
236
 
 
237
 
void CSFile::flush()
238
 
{
239
 
}
240
 
 
241
 
void CSFile::sync()
242
 
{
243
 
        sf_sync();
244
 
}
245
 
 
246
 
CSFile *CSFile::newFile(CSPath *path)
247
 
{
248
 
        CSFile *f;
249
 
 
250
 
        if (!(f = new CSFile())) {
251
 
                path->release();
252
 
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
253
 
        }
254
 
        f->myFilePath = path;
255
 
        return f;
256
 
}
257
 
 
258
 
CSFile *CSFile::newFile(const char *path_str)
259
 
{
260
 
        CSPath *path;
261
 
 
262
 
        path = CSPath::newPath(path_str);
263
 
        return newFile(path);
264
 
}
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
 
 
274
 
void CSFile::openFile(int mode)
275
 
{
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));
281
 
        
282
 
        iMode = mode;
283
 
        /* Does not make sense to truncate, and have READONLY! */
284
 
        if (IS_MODE(mode, TRUNCATE) && !IS_MODE(mode, READONLY))
285
 
                setEOF((off64_t) 0);
286
 
}
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
 
 
309
 
/*
310
 
 * ---------------------------------------------------------------
311
 
 * A READ BUFFERED FILE
312
 
 */
313
 
 
314
 
CSReadBufferedFile::CSReadBufferedFile():
315
 
myFile(NULL),
316
 
iFileBufferOffset(0),
317
 
iBufferDataLen(0)
318
 
{
319
 
}
320
 
 
321
 
CSReadBufferedFile::~CSReadBufferedFile()
322
 
{
323
 
        if (myFile) {
324
 
                close();
325
 
                myFile->release();
326
 
                myFile = NULL;
327
 
        }
328
 
}
329
 
 
330
 
void CSReadBufferedFile::close()
331
 
{
332
 
        flush();
333
 
        myFile->close();
334
 
        iFileBufferOffset = 0;
335
 
        iBufferDataLen = 0;
336
 
}
337
 
 
338
 
off64_t CSReadBufferedFile::getEOF()
339
 
{
340
 
        off64_t eof = myFile->getEOF();
341
 
 
342
 
        if (eof < iFileBufferOffset + iBufferDataLen)
343
 
                return iFileBufferOffset + iBufferDataLen;
344
 
        return eof;
345
 
}
346
 
 
347
 
void CSReadBufferedFile::setEOF(off64_t offset)
348
 
{
349
 
        myFile->setEOF(offset);
350
 
        if (offset < iFileBufferOffset) {
351
 
                iFileBufferOffset = 0;
352
 
                iBufferDataLen = 0;
353
 
        }
354
 
        else if (offset < iFileBufferOffset + iBufferDataLen)
355
 
                iBufferDataLen = (size_t)(offset - iFileBufferOffset);
356
 
}
357
 
 
358
 
size_t CSReadBufferedFile::read(void *data, off64_t offset, size_t size, size_t min_size)
359
 
{
360
 
        size_t result;
361
 
        size_t tfer = 0;
362
 
 
363
 
        if (iBufferDataLen > 0) {
364
 
                if (offset < iFileBufferOffset) {
365
 
                        //  case 1, 2, 6
366
 
                        if (offset + size > iFileBufferOffset + iBufferDataLen) {
367
 
                                // 6 (would have to do 2 reads and a memcpy (better is just one read)
368
 
                                flush();
369
 
                                goto readit;
370
 
                        }
371
 
                        if (offset + size > iFileBufferOffset) {
372
 
                                // 2
373
 
                                tfer = (size_t)(offset + size - iFileBufferOffset);
374
 
                                memcpy((char *) data + (iFileBufferOffset - offset), iFileBuffer, tfer);
375
 
                                size -= tfer;
376
 
                        }
377
 
                        // We assume we are reading back to front: 
378
 
                        if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
379
 
                                size_t mins;
380
 
 
381
 
                                if (offset + size >= SC_DEFAULT_FILE_BUFFER_SIZE) {
382
 
                                        iFileBufferOffset = offset + size - SC_DEFAULT_FILE_BUFFER_SIZE;
383
 
                                        mins = SC_DEFAULT_FILE_BUFFER_SIZE;
384
 
                                }
385
 
                                else {
386
 
                                        iFileBufferOffset = 0;
387
 
                                        mins = (size_t) offset + size;
388
 
                                }
389
 
                                result = myFile->read(iFileBuffer, iFileBufferOffset, SC_DEFAULT_FILE_BUFFER_SIZE, mins);
390
 
                                iBufferDataLen = result;
391
 
                                memcpy(data, iFileBuffer + (offset - iFileBufferOffset), size);
392
 
                        }
393
 
                        else
394
 
                                result = myFile->read(data, offset, size, size);
395
 
                        return size + tfer;
396
 
                }
397
 
                if (offset + size <= iFileBufferOffset + iBufferDataLen) {
398
 
                        // 3
399
 
                        memcpy(data, iFileBuffer + (offset - iFileBufferOffset), size);
400
 
                        return size;
401
 
                }
402
 
                if (offset < iFileBufferOffset + iBufferDataLen) {
403
 
                        // 4 We assume we are reading front to back
404
 
                        tfer = (size_t)(iFileBufferOffset + iBufferDataLen - offset);
405
 
                        memcpy(data, iFileBuffer + (offset - iFileBufferOffset), tfer);
406
 
                        data = (char *) data + tfer;
407
 
                        size -= tfer;
408
 
                        offset += tfer;
409
 
                        if (min_size >= tfer)
410
 
                                min_size -= tfer;
411
 
                        else
412
 
                                min_size = 0;
413
 
                }
414
 
                // else 5
415
 
        }
416
 
 
417
 
        readit:
418
 
        if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
419
 
                result = myFile->read(iFileBuffer, offset, SC_DEFAULT_FILE_BUFFER_SIZE, min_size);
420
 
                iFileBufferOffset = offset;
421
 
                iBufferDataLen = result;
422
 
                if (result > size)
423
 
                        result = size;
424
 
                memcpy(data, iFileBuffer, result);
425
 
        }
426
 
        else
427
 
                result = myFile->read(data, offset, size, min_size);
428
 
        return result + tfer;
429
 
}
430
 
 
431
 
void CSReadBufferedFile::write(const void *data, off64_t offset, size_t size)
432
 
{
433
 
        if (iBufferDataLen > 0) {
434
 
                size_t tfer;
435
 
 
436
 
                if (offset < iFileBufferOffset) {
437
 
                        //  case 1, 2, 6
438
 
                        if (offset + size > iFileBufferOffset + iBufferDataLen) {
439
 
                                // 6 (would have to do 2 reads and a memcpy (better is just one read)
440
 
                                memcpy((char *) data + (iFileBufferOffset - offset), iFileBuffer, iBufferDataLen);
441
 
                        }
442
 
                        else if (offset + size > iFileBufferOffset) {
443
 
                                // 2
444
 
                                tfer = (size_t)(offset + size - iFileBufferOffset);
445
 
                                memcpy(iFileBuffer, (char *) data + (iFileBufferOffset - offset), tfer);
446
 
                        }
447
 
                }
448
 
                else if (offset + size <= iFileBufferOffset + iBufferDataLen) {
449
 
                        // 3
450
 
                        memcpy(iFileBuffer + (offset - iFileBufferOffset), data, size);
451
 
                }
452
 
                else if (offset < iFileBufferOffset + iBufferDataLen) {
453
 
                        // 4 We assume we are reading front to back
454
 
                        tfer = (size_t)(iFileBufferOffset + iBufferDataLen - offset);
455
 
                        memcpy(iFileBuffer + (offset - iFileBufferOffset), data, tfer);
456
 
                }
457
 
                // else 5
458
 
        }
459
 
 
460
 
        myFile->write(data, offset, size);
461
 
}
462
 
 
463
 
void CSReadBufferedFile::flush()
464
 
{
465
 
        myFile->flush();
466
 
}
467
 
 
468
 
void CSReadBufferedFile::sync()
469
 
{
470
 
        flush();
471
 
        myFile->sync();
472
 
}
473
 
 
474
 
const char *CSReadBufferedFile::getEOL()
475
 
{
476
 
        return myFile->getEOL();
477
 
}
478
 
 
479
 
void CSReadBufferedFile::openFile(int mode)
480
 
{
481
 
        myFile->openFile(mode);
482
 
}
483
 
 
484
 
 
485
 
/*
486
 
 * ---------------------------------------------------------------
487
 
 * FILE BASED ON THE STANDARD C FILE
488
 
 */