~mathiaz/ubuntu/lucid/mysql-dfsg-5.1/zap-bug-552053

« back to all changes in this revision

Viewing changes to storage/ibmdb2i/db2i_ioBuffers.cc

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2009-06-25 12:55:45 UTC
  • mfrom: (1.1.2 upstream) (0.1.3 experimental)
  • Revision ID: james.westby@ubuntu.com-20090625125545-m8ogs96zzsri74xe
Tags: 5.1.34-1ubuntu1
* Merge from debian experimental (and 5.0 from main), remaining changes:
  - debian/mysql-server-5.1.config:
    + ask for MySQL root password at priority high instead of medium so
      that the password prompt is seen on a default install. (LP: #319843)
    + don't ask for root password when upgrading from a 5.0 install.
  - debian/control:
    + Make libmysqlclient16-dev a transitional package depending on
      libmysqlclient-dev.
    + Make libmysqlclient-dev conflict with libmysqlclient15-dev.
    + Don't build mysql-server, mysql-client, mysql-common and
      libmysqlclient15-dev binary packages since they're still provided
      by mysql-dfsg-5.0.
    + Make mysql-{client,server}-5.1 packages conflict and
      replace mysql-{client,server}-5.0, but not provide
      mysql-{client,server}.
    + Depend on a specific version of mysql-common rather than the src
      version of mysql-dfsg-5.1 since mysql-common is currently part of
      mysql-dfsg-5.0.
    + Lower mailx from a Recommends to a Suggests to avoid pulling in
      a full MTA on all installs of mysql-server. (LP: #259477)
  - debian/rules:
    + added -fno-strict-aliasing to CFLAGS to get around mysql testsuite
      build failures.
    + install mysql-test and sql-bench to /usr/share/mysql/ rather than
      /usr/.
  - debian/additions/debian-start.inc.sh: support ANSI mode (LP: #310211)
  - Add AppArmor profile:
    - debian/apparmor-profile: apparmor profile.
    - debian/rules, debian/mysql-server-5.0.files: install apparmor profile.
    - debian/mysql-server-5.0.dirs: add etc/apparmor.d/force-complain
    - debian/mysql-server-5.0.postrm: remove symlink in force-complain/ on
      purge.
    - debian/mysql-server-5.1.README.Debian: add apparmor documentation.
    - debian/additions/my.cnf: Add warning about apparmor. (LP: #201799)
    - debian/mysql-server-5.1.postinst: reload apparmor profiles.
  - debian/additions/my.cnf: remove language option. Error message files are
    located in a different directory in MySQL 5.0. Setting the language
    option to use /usr/share/mysql/english breaks 5.0. Both 5.0 and 5.1
    use a default value that works. (LP: #316974)
  - debian/mysql-server-5.1.mysql.init:
    + Clearly indicate that we do not support running multiple instances
      of mysqld by duplicating the init script.
      (closes: #314785, #324834, #435165, #444216)
    + Properly parameterize all existing references to the mysql config
      file (/etc/mysql/my.cnf).
  - debian/mysql-server-5.0.postinst: Clear out the second password
    when setting up mysql. (LP: #344816)
  - mysql-server-core-5.1 package for files needed by Akonadi:
    + debian/control: create mysql-server-core-5.1 package.
    + debian/mysql-server-core-5.1.files, debian/mysql-server-5.1.files:
      move core mysqld files to mysql-server-core-5.1 package.
  - Don't package sql-bench and mysql-test file.
* Dropped changes:
  - debian/patches/92_ssl_test_cert.dpatch: certificate expiration in
    test suite (LP: #323755). Included upstream.
* Dropped from 5.0:
  - apparmor profile:
    - debian/control: Recommends apparmor >= 2.1+1075-0ubuntu6. All version
      of apparmor-profile (>hardy) are higher than this version.
    - debian/mysql-server-5.0.preinst: create symlink for force-complain/
      on pre-feisty upgrades, upgrades where apparmor-profiles profile is
      unchanged (ie non-enforcing) and upgrades where the profile
      doesn't exist. Support for pre-hardy upgrades is no longer needed.
* debian/mysql-server-5.1.postinst: fix debian-sys-maint user creation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Licensed Materials - Property of IBM
 
3
DB2 Storage Engine Enablement
 
4
Copyright IBM Corporation 2007,2008
 
5
All rights reserved
 
6
 
 
7
Redistribution and use in source and binary forms, with or without modification,
 
8
are permitted provided that the following conditions are met: 
 
9
 (a) Redistributions of source code must retain this list of conditions, the
 
10
     copyright notice in section {d} below, and the disclaimer following this
 
11
     list of conditions. 
 
12
 (b) Redistributions in binary form must reproduce this list of conditions, the
 
13
     copyright notice in section (d) below, and the disclaimer following this
 
14
     list of conditions, in the documentation and/or other materials provided
 
15
     with the distribution. 
 
16
 (c) The name of IBM may not be used to endorse or promote products derived from
 
17
     this software without specific prior written permission. 
 
18
 (d) The text of the required copyright notice is: 
 
19
       Licensed Materials - Property of IBM
 
20
       DB2 Storage Engine Enablement 
 
21
       Copyright IBM Corporation 2007,2008 
 
22
       All rights reserved
 
23
 
 
24
THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
 
25
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
26
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 
27
SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 
29
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
30
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
31
CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 
32
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 
33
OF SUCH DAMAGE.
 
34
*/
 
35
 
 
36
 
 
37
#include "db2i_ioBuffers.h"
 
38
 
 
39
/**
 
40
  Request another block of rows
 
41
 
 
42
  Request the next set of rows from DB2. This must only be called after 
 
43
  newReadRequest().
 
44
  
 
45
  @param orientation The direction to use when reading through the table.
 
46
*/
 
47
void IOAsyncReadBuffer::loadNewRows(char orientation)
 
48
{
 
49
  rewind();
 
50
  maxRows() = rowsToBlock;
 
51
 
 
52
  DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("Requesting %d rows, async = %d", rowsToBlock, readIsAsync));
 
53
 
 
54
  rc = getBridge()->expectErrors(QMY_ERR_END_OF_BLOCK, QMY_ERR_LOB_SPACE_TOO_SMALL)
 
55
                  ->read(file,
 
56
                         ptr(),
 
57
                         accessIntent,
 
58
                         commitLevel,
 
59
                         orientation,
 
60
                         readIsAsync,
 
61
                         rrnList,
 
62
                         0, 
 
63
                         0,
 
64
                         0);
 
65
 
 
66
  DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("recordsRead: %d, rc: %d", (uint32)rowCount(), rc));
 
67
 
 
68
  
 
69
  *releaseRowNeeded = true;
 
70
  
 
71
  if (rc == QMY_ERR_END_OF_BLOCK)
 
72
  {
 
73
    // This is really just an informational error, so we ignore it.
 
74
    rc = 0;
 
75
    DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("End of block signalled"));
 
76
  }
 
77
  else if (rc == QMY_ERR_END_OF_FILE)
 
78
  {
 
79
    // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked.
 
80
    rc = HA_ERR_END_OF_FILE;
 
81
    *releaseRowNeeded = false;
 
82
  }
 
83
  else if (rc == QMY_ERR_KEY_NOT_FOUND)
 
84
  {
 
85
    rc = HA_ERR_KEY_NOT_FOUND;
 
86
    *releaseRowNeeded = false;
 
87
  }
 
88
  
 
89
  if (rc) closePipe();
 
90
}
 
91
 
 
92
 
 
93
/**
 
94
  Empty the message pipe to prepare for another read.
 
95
*/
 
96
void IOAsyncReadBuffer::drainPipe()
 
97
{
 
98
  DBUG_ASSERT(pipeState == PendingFullBufferMsg);      
 
99
  PipeRpy_t msg[32];
 
100
  int bytes;
 
101
  PipeRpy_t* lastMsg;
 
102
  while ((bytes = read(msgPipe, msg, sizeof(msg))) > 0)
 
103
  {
 
104
    DBUG_PRINT("db2i_ioBuffers::drainPipe",("Pipe returned %d bytes", bytes));
 
105
    lastMsg = &msg[bytes / (sizeof(msg[0]))-1];
 
106
    if (lastMsg->CumRowCnt == maxRows() ||
 
107
        lastMsg->RtnCod != 0)
 
108
    {
 
109
      pipeState = ConsumedFullBufferMsg;
 
110
      break;
 
111
    }
 
112
 
 
113
  } 
 
114
  DBUG_PRINT("db2i_ioBuffers::drainPipe",("rc = %d, rows = %d, max = %d", lastMsg->RtnCod, lastMsg->CumRowCnt, (uint32)maxRows()));
 
115
}
 
116
 
 
117
 
 
118
/**
 
119
  Poll the message pipe for async read messages
 
120
 
 
121
  Only valid in async 
 
122
  
 
123
  @param orientation The direction to use when reading through the table.
 
124
*/
 
125
void IOAsyncReadBuffer::pollNextRow(char orientation)
 
126
{
 
127
  DBUG_ASSERT(readIsAsync);
 
128
  
 
129
  // Handle the case in which the buffer is full.
 
130
  if (rowCount() == maxRows())
 
131
  {
 
132
    // If we haven't read to the end, exit here.
 
133
    if (readCursor < rowCount())
 
134
      return;
 
135
    
 
136
    if (pipeState == PendingFullBufferMsg)
 
137
      drainPipe();
 
138
    if (pipeState == ConsumedFullBufferMsg)
 
139
      loadNewRows(orientation);
 
140
  }
 
141
 
 
142
  if (!rc)
 
143
  {
 
144
    PipeRpy_t* lastMsg = NULL;
 
145
    while (true)
 
146
    {    
 
147
      PipeRpy_t msg[32];
 
148
      int bytes = read(msgPipe, msg, sizeof(msg));
 
149
      DBUG_PRINT("db2i_ioBuffers::pollNextRow",("Pipe returned %d bytes", bytes));
 
150
 
 
151
      if (unlikely(bytes < 0))
 
152
      {
 
153
        DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("Error"));
 
154
        rc = errno;
 
155
        break;
 
156
      }
 
157
      else if (bytes == 0)
 
158
        break;
 
159
 
 
160
      DBUG_ASSERT(bytes % sizeof(msg[0]) == 0);
 
161
      lastMsg = &msg[bytes / (sizeof(msg[0]))-1];
 
162
 
 
163
      if (lastMsg->RtnCod || (lastMsg->CumRowCnt == usedRows()))
 
164
      {
 
165
        rc = lastMsg->RtnCod;
 
166
        break;
 
167
      }
 
168
    } 
 
169
 
 
170
    *releaseRowNeeded = true;
 
171
 
 
172
    if (rc == QMY_ERR_END_OF_BLOCK)
 
173
      rc = 0;
 
174
    else if (rc == QMY_ERR_END_OF_FILE)
 
175
    {
 
176
      // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked.
 
177
      rc = HA_ERR_END_OF_FILE;
 
178
      *releaseRowNeeded = false;
 
179
    }
 
180
    else if (rc == QMY_ERR_KEY_NOT_FOUND)
 
181
    {
 
182
      rc = HA_ERR_KEY_NOT_FOUND;
 
183
      *releaseRowNeeded = false;
 
184
    }
 
185
 
 
186
    if (lastMsg)
 
187
      DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("Good data: rc=%d; rows=%d; usedRows=%d", lastMsg->RtnCod, lastMsg->CumRowCnt, (uint32)usedRows()));
 
188
    if (lastMsg && likely(!rc))
 
189
    {
 
190
      if (lastMsg->CumRowCnt < maxRows())
 
191
        pipeState = PendingFullBufferMsg;
 
192
      else
 
193
        pipeState = ConsumedFullBufferMsg;
 
194
 
 
195
      DBUG_ASSERT(lastMsg->CumRowCnt <= usedRows());
 
196
 
 
197
    }
 
198
    DBUG_ASSERT(rowCount() <= getRowCapacity());
 
199
  }
 
200
  DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("filledRows: %d, rc: %d", rowCount(), rc));
 
201
  if (rc) closePipe();
 
202
}
 
203
 
 
204
 
 
205
/**
 
206
  Prepare for the destruction of the row buffer storage.  
 
207
*/
 
208
void IOAsyncReadBuffer::prepForFree()
 
209
{
 
210
  interruptRead();
 
211
  rewind();
 
212
  IORowBuffer::prepForFree();
 
213
}
 
214
 
 
215
 
 
216
/**
 
217
  Initialize the newly allocated storage.
 
218
 
 
219
  @param sizeChanged  Indicates whether the storage capacity is being changed.
 
220
*/
 
221
void IOAsyncReadBuffer::initAfterAllocate(bool sizeChanged)
 
222
{
 
223
  rewind();
 
224
 
 
225
  if (sizeChanged || ((void*)rrnList == NULL))
 
226
    rrnList.realloc(getRowCapacity() * sizeof(uint32));
 
227
}
 
228
 
 
229
 
 
230
/**
 
231
  Send an initial read request
 
232
 
 
233
  @param infile  The file (table/index) being read from
 
234
  @param orientation  The orientation to use for this read request
 
235
  @param rowsToBuffer  The number of rows to request each time
 
236
  @param useAsync  Whether reads should be performed asynchronously.
 
237
  @param key  The key to use (if any)
 
238
  @param keyLength  The length of key (if any)
 
239
  @param keyParts  The number of columns in the key (if any)
 
240
 
 
241
*/
 
242
void IOAsyncReadBuffer::newReadRequest(FILE_HANDLE infile,
 
243
                                       char orientation,
 
244
                                       uint32 rowsToBuffer,
 
245
                                       bool useAsync,
 
246
                                       ILEMemHandle key,
 
247
                                       int keyLength,
 
248
                                       int keyParts)
 
249
{
 
250
  DBUG_ENTER("db2i_ioBuffers::newReadRequest");
 
251
  DBUG_ASSERT(rowsToBuffer <= getRowCapacity());
 
252
#ifndef DBUG_OFF
 
253
  if (readCursor < rowCount())
 
254
    DBUG_PRINT("PERF:",("Wasting %d buffered rows!\n", rowCount() - readCursor));
 
255
#endif
 
256
 
 
257
  int fildes[2];
 
258
  int ileDescriptor = QMY_REUSE;
 
259
 
 
260
  interruptRead();
 
261
 
 
262
  if (likely(useAsync))
 
263
  {
 
264
    if (rowsToBuffer == 1)
 
265
    {
 
266
      // Async provides little or no benefit for single row reads, so we turn it off
 
267
      DBUG_PRINT("db2i_ioBuffers::newReadRequest", ("Disabling async"));
 
268
      useAsync = false;
 
269
    }
 
270
    else
 
271
    {          
 
272
      rc = pipe(fildes);
 
273
      if (rc) DBUG_VOID_RETURN;
 
274
 
 
275
      // Translate the pipe write descriptor into the equivalent ILE descriptor
 
276
      rc = fstatx(fildes[1], (struct stat*)&ileDescriptor, sizeof(ileDescriptor), STX_XPFFD_PASE);
 
277
      if (rc)
 
278
      {
 
279
        close(fildes[0]);
 
280
        close(fildes[1]);
 
281
        DBUG_VOID_RETURN;
 
282
      }
 
283
      pipeState = Untouched;
 
284
      msgPipe = fildes[0];
 
285
      
 
286
      DBUG_PRINT("db2i_ioBuffers::newReadRequest", ("Opened pipe %d", fildes[0]));
 
287
    }
 
288
  }
 
289
 
 
290
  file = infile;
 
291
  readIsAsync = useAsync;
 
292
  rowsToBlock = rowsToBuffer;
 
293
 
 
294
  rewind();
 
295
  maxRows() = 1;
 
296
  rc = getBridge()->expectErrors(QMY_ERR_END_OF_BLOCK, QMY_ERR_LOB_SPACE_TOO_SMALL)
 
297
                  ->read(file,
 
298
                        ptr(),
 
299
                        accessIntent,
 
300
                        commitLevel,
 
301
                        orientation,
 
302
                        useAsync,
 
303
                        rrnList,
 
304
                        key, 
 
305
                        keyLength,
 
306
                        keyParts,
 
307
                        ileDescriptor);
 
308
 
 
309
  // Having shared the pipe with ILE, we relinquish our claim on the write end
 
310
  // of the pipe.
 
311
  if (useAsync)
 
312
    close(fildes[1]);
 
313
 
 
314
  // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked.
 
315
  if (rc == QMY_ERR_END_OF_FILE)
 
316
  {
 
317
    rc = HA_ERR_END_OF_FILE;
 
318
    *releaseRowNeeded = false;
 
319
  }
 
320
  else if (rc == QMY_ERR_KEY_NOT_FOUND)
 
321
  {
 
322
    if (rowCount())
 
323
      rc = HA_ERR_END_OF_FILE;
 
324
    else
 
325
      rc = HA_ERR_KEY_NOT_FOUND;
 
326
    *releaseRowNeeded = false;
 
327
  }
 
328
  else
 
329
    *releaseRowNeeded = true;
 
330
 
 
331
  DBUG_VOID_RETURN;
 
332
}