~ubuntu-branches/ubuntu/lucid/mysql-dfsg-5.1/lucid-security

« back to all changes in this revision

Viewing changes to storage/ibmdb2i/db2i_ileBridge.h

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 22:33:55 UTC
  • mto: (1.2.1) (37.1.1 lucid-security)
  • mto: This revision was merged to the branch mainline in revision 36.
  • Revision ID: package-import@ubuntu.com-20120222223355-ku1tb4r70osci6v2
Tags: upstream-5.1.61
ImportĀ upstreamĀ versionĀ 5.1.61

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