~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ibmdb2i/db2i_ileBridge.h

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

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
#ifndef DB2I_ILEBRIDGE_H
 
38
#define DB2I_ILEBRIDGE_H
 
39
 
 
40
#include "db2i_global.h"
 
41
#include "mysql_priv.h"
 
42
#include "as400_types.h"
 
43
#include "as400_protos.h"
 
44
#include "qmyse.h"
 
45
#include "db2i_errors.h"
 
46
 
 
47
typedef uint64_t FILE_HANDLE;
 
48
typedef my_thread_id CONNECTION_HANDLE;
 
49
const char SAVEPOINT_NAME[] = {0xD4,0xE2,0xD7,0xC9,0xD5,0xE3,0xC5,0xD9,0xD5,0x0};
 
50
const uint32 TACIT_ERRORS_SIZE=2;
 
51
 
 
52
enum db2i_InfoRequestSpec
 
53
{
 
54
  objLength = 1,
 
55
  rowCount = 2,
 
56
  deletedRowCount = 4,
 
57
  rowsPerKey = 8,
 
58
  meanRowLen = 16,
 
59
  lastModTime = 32,
 
60
  createTime = 64,
 
61
  ioCount = 128
 
62
}; 
 
63
  
 
64
extern  handlerton *ibmdb2i_hton;
 
65
struct IBMDB2I_SHARE;
 
66
 
 
67
const uint32 db2i_ileBridge_MAX_INPARM_SIZE = 512;
 
68
const uint32 db2i_ileBridge_MAX_OUTPARM_SIZE = 512;
 
69
 
 
70
extern pthread_key(IleParms*, THR_ILEPARMS);
 
71
struct IleParms
 
72
{
 
73
  char inParms[db2i_ileBridge_MAX_INPARM_SIZE];
 
74
  char outParms[db2i_ileBridge_MAX_OUTPARM_SIZE];
 
75
};
 
76
 
 
77
/**
 
78
  @class db2i_ileBridge
 
79
 
 
80
  Implements a connection-based interface to the QMY_* APIs
 
81
  
 
82
  @details  Each client connection that touches an IBMDB2I table has a "bridge"
 
83
  associated with it. This bridge is constructed on first use and provides a
 
84
  more C-like interface to the APIs. As well, it is reponsible for tracking 
 
85
  connection scoped information such as statement transaction state and error
 
86
  message text. The bridge is destroyed when the connection ends.
 
87
*/
 
88
class db2i_ileBridge
 
89
{
 
90
  enum ileFuncs
 
91
  {
 
92
    funcRegisterParameterSpaces,
 
93
    funcRegisterSpace,
 
94
    funcUnregisterSpace,
 
95
    funcProcessRequest,
 
96
    funcListEnd
 
97
  };
 
98
 
 
99
  static db2i_ileBridge* globalBridge;    
 
100
public:
 
101
    
 
102
  
 
103
  static int setup();
 
104
  static void takedown();
 
105
 
 
106
  /**
 
107
    Obtain a pointer to the bridge for the current connection.
 
108
    
 
109
    If a MySQL client connection is on the stack, we get the associated brideg.
 
110
    Otherwise, we use the globalBridge. 
 
111
  */
 
112
  static db2i_ileBridge* getBridgeForThread()
 
113
  {
 
114
    THD* thd = current_thd;
 
115
    if (likely(thd))  
 
116
      return getBridgeForThread(thd);
 
117
 
 
118
    return globalBridge;  
 
119
  }
 
120
 
 
121
  /**
 
122
    Obtain a pointer to the bridge for the specified connection.
 
123
 
 
124
    If a bridge exists already, we return it immediately. Otherwise, prepare
 
125
    a new bridge for the connection.    
 
126
  */
 
127
  static db2i_ileBridge* getBridgeForThread(const THD* thd)
 
128
  {
 
129
    void* thdData = *thd_ha_data(thd, ibmdb2i_hton);
 
130
    if (likely(thdData != NULL))
 
131
      return (db2i_ileBridge*)(thdData);
 
132
 
 
133
    db2i_ileBridge* newBridge = createNewBridge(thd->thread_id);
 
134
    *thd_ha_data(thd, ibmdb2i_hton) = (void*)newBridge;
 
135
    return newBridge;
 
136
  }
 
137
 
 
138
  static void destroyBridgeForThread(const THD* thd);
 
139
  static void registerPtr(const void* ptr, ILEMemHandle* receiver);
 
140
  static void unregisterPtr(ILEMemHandle handle);
 
141
  int32 allocateFileDefn(ILEMemHandle definitionSpace,
 
142
                         ILEMemHandle handleSpace,
 
143
                         uint16 fileCount,
 
144
                         const char* schemaName,
 
145
                         uint16 schemaNameLength,
 
146
                         ILEMemHandle formatSpace,
 
147
                         uint32 formatSpaceLen);
 
148
  int32 allocateFileInstance(FILE_HANDLE defnHandle,
 
149
                             ILEMemHandle inuseSpace,
 
150
                             FILE_HANDLE* instance);
 
151
  int32 deallocateFile(FILE_HANDLE fileHandle,
 
152
                       bool postDropTable=FALSE);
 
153
  int32 read(FILE_HANDLE rfileHandle, 
 
154
             ILEMemHandle buf, 
 
155
             char accessIntent,
 
156
             char commitLevel,
 
157
             char orientation, 
 
158
             bool asyncRead = FALSE,
 
159
             ILEMemHandle rrn = 0,
 
160
             ILEMemHandle key = 0,
 
161
             uint32 keylen = 0,
 
162
             uint16 keyParts = 0,
 
163
             int pipeFD = -1);
 
164
  int32 readByRRN(FILE_HANDLE rfileHandle, 
 
165
                  ILEMemHandle buf,
 
166
                  uint32 inRRN,
 
167
                  char accessIntent,
 
168
                  char commitLevel);
 
169
  int32 writeRows(FILE_HANDLE rfileHandle, 
 
170
                  ILEMemHandle buf, 
 
171
                  char commitLevel,
 
172
                  int64* outIdVal,
 
173
                  bool* outIdGen,
 
174
                  uint32* dupKeyRRN,
 
175
                  char** dupKeyName,
 
176
                  uint32* dupKeyNameLen,
 
177
                  uint32* outIdIncrement);
 
178
  uint32 execSQL(const char* statement,
 
179
                 uint32 statementCount,
 
180
                 uint8  commitLevel,
 
181
                 bool autoCreateSchema = FALSE,
 
182
                 bool dropSchema = FALSE,
 
183
                 bool noCommit = FALSE,
 
184
                 FILE_HANDLE fileHandle = 0);
 
185
  int32 prepOpen(const char* statement,
 
186
                 FILE_HANDLE* rfileHandle,
 
187
                 uint32* recLength);
 
188
  int32 deleteRow(FILE_HANDLE rfileHandle,
 
189
                  uint32 rrn);
 
190
  int32 updateRow(FILE_HANDLE rfileHandle, 
 
191
                  uint32 rrn,
 
192
                  ILEMemHandle buf,
 
193
                  uint32* dupKeyRRN,
 
194
                  char** dupKeyName,
 
195
                  uint32* dupKeyNameLen);
 
196
  int32 commitmentControl(uint8 function);
 
197
  int32 savepoint(uint8 function,
 
198
                  const char* savepointName);
 
199
  int32 recordsInRange(FILE_HANDLE rfileHandle,
 
200
                       ILEMemHandle inSpc,
 
201
                       uint32 inKeyCnt,
 
202
                       uint32 inLiteralCnt,
 
203
                       uint32 inBoundsOff,
 
204
                       uint32 inLitDefOff,
 
205
                       uint32 inLiteralsOff,
 
206
                       uint32 inCutoff,
 
207
                       uint32 inSpcLen, 
 
208
                       uint16 inEndByte,
 
209
                       uint64* outRecCnt,
 
210
                       uint16* outRtnCode);
 
211
  int32 rrlslck(FILE_HANDLE rfileHandle,
 
212
                char accessIntent);
 
213
  int32 lockObj(FILE_HANDLE rfileHandle, 
 
214
                uint64 inTimeoutVal, 
 
215
                char inAction, 
 
216
                char inLockType,
 
217
                char inTimeout);
 
218
  int32 constraints(FILE_HANDLE rfileHandle,
 
219
                    ILEMemHandle inSpc, 
 
220
                    uint32 inSpcLen,
 
221
                    uint32* outLen,
 
222
                    uint32* outCnt);
 
223
  int32 optimizeTable(FILE_HANDLE rfileHandle);
 
224
  static int32 initILE(const char* aspName,
 
225
                       uint16* traceCtlPtr); 
 
226
  int32 initFileForIO(FILE_HANDLE rfileHandle,
 
227
                      char accessIntent,
 
228
                      char commitLevel,
 
229
                      uint16* inRecSize,
 
230
                      uint16* inRecNullOffset,
 
231
                      uint16* outRecSize,
 
232
                      uint16* outRecNullOffset);
 
233
  int32 readInterrupt(FILE_HANDLE fileHandle);  
 
234
  static int32 exitILE(); 
 
235
  
 
236
  int32 objectOverride(FILE_HANDLE rfileHandle,
 
237
                       ILEMemHandle buf,
 
238
                       uint32 recordWidth = 0);
 
239
  
 
240
  int32 retrieveTableInfo(FILE_HANDLE rfileHandle,
 
241
                          uint16 dataRequested,
 
242
                          ha_statistics& stats,
 
243
                          ILEMemHandle inSpc = NULL);
 
244
 
 
245
  int32 retrieveIndexInfo(FILE_HANDLE rfileHandle,
 
246
                          uint64* outPageCnt); 
 
247
  
 
248
  int32 closeConnection(CONNECTION_HANDLE conn);
 
249
  int32 quiesceFileInstance(FILE_HANDLE rfileHandle);
 
250
    
 
251
  /**
 
252
    Mark the beginning of a "statement transaction"
 
253
    
 
254
    @detail MySQL "statement transactions" (see sql/handler.cc) are implemented
 
255
            as DB2 savepoints having a predefined name.
 
256
    
 
257
    @return 0 if successful; error otherwise
 
258
  */
 
259
  uint32 beginStmtTx()
 
260
  {
 
261
    DBUG_ENTER("db2i_ileBridge::beginStmtTx");
 
262
    if (stmtTxActive)
 
263
      DBUG_RETURN(0);
 
264
    
 
265
    stmtTxActive = true;
 
266
    
 
267
    DBUG_RETURN(savepoint(QMY_SET_SAVEPOINT, SAVEPOINT_NAME));
 
268
  }
 
269
 
 
270
  /**
 
271
    Commit a "statement transaction"
 
272
    
 
273
    @return 0 if successful; error otherwise
 
274
  */
 
275
  uint32 commitStmtTx()
 
276
  {
 
277
    DBUG_ENTER("db2i_ileBridge::commitStmtTx");
 
278
    DBUG_ASSERT(stmtTxActive);
 
279
    stmtTxActive = false;
 
280
    DBUG_RETURN(savepoint(QMY_RELEASE_SAVEPOINT, SAVEPOINT_NAME));
 
281
  }
 
282
  
 
283
  /**
 
284
    Roll back a "statement transaction"
 
285
    
 
286
    @return 0 if successful; error otherwise
 
287
  */
 
288
  uint32 rollbackStmtTx()
 
289
  {
 
290
    DBUG_ENTER("db2i_ileBridge::rollbackStmtTx");
 
291
    DBUG_ASSERT(stmtTxActive);
 
292
    stmtTxActive = false;
 
293
    DBUG_RETURN(savepoint(QMY_ROLLBACK_SAVEPOINT, SAVEPOINT_NAME)); 
 
294
  }
 
295
  
 
296
        
 
297
  /**
 
298
    Provide storage for generating error messages.
 
299
    
 
300
    This storage must persist until the error message is retrieved from the 
 
301
    handler instance. It is for this reason that we associate it with the bridge.
 
302
    
 
303
    @return Pointer to heap storage of MYSQL_ERRMSG_SIZE bytes
 
304
  */
 
305
  char* getErrorStorage()
 
306
  {
 
307
    if (!connErrText)
 
308
    {
 
309
      connErrText = (char*)my_malloc(MYSQL_ERRMSG_SIZE, MYF(MY_WME));
 
310
      if (connErrText) connErrText[0] = 0;
 
311
    }
 
312
    
 
313
    return connErrText;
 
314
  }
 
315
  
 
316
  /**
 
317
    Free storage for generating error messages.
 
318
  */
 
319
  void freeErrorStorage()
 
320
  {
 
321
    if (likely(connErrText))
 
322
    {
 
323
      my_free(connErrText, MYF(0)); 
 
324
      connErrText = NULL;
 
325
    }
 
326
  }
 
327
  
 
328
 
 
329
  /**
 
330
    Store a file handle for later retrieval.
 
331
    
 
332
    If deallocateFile encounters a lock when trying to perform its operation,
 
333
    the file remains allocated but must be deallocated later. This function
 
334
    provides a way for the connection to "remember" that this deallocation is
 
335
    still needed.
 
336
    
 
337
    @param newname  The name of the file to be added
 
338
    @param newhandle  The handle associated with newname
 
339
    
 
340
  */
 
341
  void preserveHandle(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share)
 
342
  {
 
343
    pendingLockedHandles.add(newname, newhandle, share);
 
344
  }
 
345
  
 
346
  /**
 
347
    Retrieve a file handle stored by preserveHandle().
 
348
 
 
349
    @param name  The name of the file to be retrieved.
 
350
    
 
351
    @return The handle associated with name    
 
352
  */
 
353
  FILE_HANDLE findAndRemovePreservedHandle(const char* name, IBMDB2I_SHARE** share)
 
354
  {
 
355
    FILE_HANDLE hdl = pendingLockedHandles.findAndRemove(name, share);
 
356
    return hdl;
 
357
  }
 
358
  
 
359
  /**
 
360
    Indicate which error messages should be suppressed on the next API call
 
361
    
 
362
    These functions are useful for ensuring that the provided error numbers
 
363
    are returned if a failure occurs but do not cause a spurious error message
 
364
    to be returned.
 
365
    
 
366
    @return A pointer to this instance
 
367
  */
 
368
  db2i_ileBridge* expectErrors(int32 er1)
 
369
  {
 
370
    tacitErrors[0]=er1;
 
371
    return this;
 
372
  }
 
373
  
 
374
  db2i_ileBridge* expectErrors(int32 er1, int32 er2)
 
375
  {
 
376
    tacitErrors[0]=er1;
 
377
    tacitErrors[1]=er2;
 
378
    return this;
 
379
  }
 
380
 
 
381
  /**
 
382
    Obtain the IBM i system message that accompanied the last API failure.
 
383
    
 
384
    @return A pointer to the 7 character message ID.
 
385
  */
 
386
  static const char* getErrorMsgID()
 
387
  {
 
388
    return ((Qmy_Error_output_t*)parms()->outParms)->MsgId;
 
389
  }
 
390
  
 
391
  /**
 
392
    Convert an API error code into the equivalent MySQL error code (if any)
 
393
    
 
394
    @param rc  The QMYSE API error code
 
395
    
 
396
    @return  If an equivalent exists, the MySQL error code; else rc
 
397
  */
 
398
  static int32 translateErrorCode(int32 rc)
 
399
  {
 
400
    if (likely(rc == 0))
 
401
      return 0;
 
402
    
 
403
    switch (rc)
 
404
    {
 
405
      case QMY_ERR_KEY_NOT_FOUND:
 
406
        return HA_ERR_KEY_NOT_FOUND;
 
407
      case QMY_ERR_DUP_KEY:
 
408
        return HA_ERR_FOUND_DUPP_KEY;
 
409
      case QMY_ERR_END_OF_FILE:
 
410
        return HA_ERR_END_OF_FILE;
 
411
      case QMY_ERR_LOCK_TIMEOUT:
 
412
        return HA_ERR_LOCK_WAIT_TIMEOUT;
 
413
      case QMY_ERR_CST_VIOLATION:
 
414
        return HA_ERR_NO_REFERENCED_ROW;
 
415
      case QMY_ERR_TABLE_NOT_FOUND:
 
416
        return HA_ERR_NO_SUCH_TABLE;
 
417
      case QMY_ERR_NON_UNIQUE_KEY:
 
418
        return ER_DUP_ENTRY;
 
419
      case QMY_ERR_MSGID:
 
420
        {
 
421
          if (memcmp(getErrorMsgID(), DB2I_CPF503A, 7) == 0)
 
422
            return HA_ERR_ROW_IS_REFERENCED;
 
423
          if (memcmp(getErrorMsgID(), DB2I_SQL0538, 7) == 0)
 
424
            return HA_ERR_CANNOT_ADD_FOREIGN;
 
425
        }
 
426
    }
 
427
    return rc;
 
428
  }
 
429
  
 
430
private:
 
431
    
 
432
  static db2i_ileBridge* createNewBridge(CONNECTION_HANDLE connID);
 
433
  static void destroyBridge(db2i_ileBridge* bridge);
 
434
  static int registerParmSpace(char* in, char* out);
 
435
  static int32 doIt();
 
436
  int32 doItWithLog();
 
437
  
 
438
  static _ILEpointer *functionSymbols;          ///< Array of ILE function pointers
 
439
  CONNECTION_HANDLE cachedConnectionID;         ///< The associated connection
 
440
  bool stmtTxActive;                            ///< Inside statement transaction
 
441
  char *connErrText;                            ///< Storage for error message
 
442
  int32 tacitErrors[TACIT_ERRORS_SIZE];         ///< List of errors to be suppressed
 
443
 
 
444
  static IleParms* initParmsForThread();
 
445
 
 
446
  /**
 
447
    Get space for passing parameters to the QMY_* APIs
 
448
    
 
449
    @details  A fixed-length parameter passing space is associated with each
 
450
    pthread. This space is allocated and registered by initParmsForThread() 
 
451
    the first time a pthread works with a bridge. The space is cached away
 
452
    and remains available until the pthread ends. It became necessary to 
 
453
    disassociate the parameter space from the bridge in order to support
 
454
    future enhancements to MySQL that sever the one-to-one relationship between
 
455
    pthreads and user connections. The QMY_* APIs scope a registered parameter
 
456
    space to the thread that executes the register operation.
 
457
  */
 
458
  static IleParms* parms()
 
459
  {
 
460
    IleParms* p = my_pthread_getspecific_ptr(IleParms*, THR_ILEPARMS);
 
461
    if (likely(p))
 
462
      return p;
 
463
 
 
464
    return initParmsForThread();    
 
465
  }
 
466
  
 
467
  class PreservedHandleList
 
468
  {
 
469
    friend db2i_ileBridge* db2i_ileBridge::createNewBridge(CONNECTION_HANDLE);
 
470
    public: 
 
471
      void add(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share);
 
472
      FILE_HANDLE findAndRemove(const char* fileName, IBMDB2I_SHARE** share);
 
473
      
 
474
    private:     
 
475
      struct NameHandlePair
 
476
      {
 
477
        char name[FN_REFLEN];
 
478
        FILE_HANDLE handle;
 
479
        IBMDB2I_SHARE* share;
 
480
        NameHandlePair* next;
 
481
      }* head;
 
482
  } pendingLockedHandles;
 
483
 
 
484
  
 
485
#ifndef DBUG_OFF
 
486
  bool cachedStateIsCoherent()
 
487
  {
 
488
      return (current_thd->thread_id == cachedConnectionID);
 
489
  }
 
490
  
 
491
  friend void db2i_ileBridge::unregisterPtr(ILEMemHandle);
 
492
  friend void db2i_ileBridge::registerPtr(const void*, ILEMemHandle*);
 
493
  static uint32 registeredPtrs;
 
494
#endif    
 
495
};
 
496
 
 
497
 
 
498
 
 
499
#endif