NdbScanOperation.hpp 8.29 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef NdbScanOperation_H
#define NdbScanOperation_H

#include <NdbOperation.hpp>

pekka@mysql.com's avatar
pekka@mysql.com committed
22
class NdbBlob;
23
class NdbResultSet;
mronstrom@mysql.com[mikron]'s avatar
mronstrom@mysql.com[mikron] committed
24
class PollGuard;
pekka@mysql.com's avatar
pekka@mysql.com committed
25

26 27 28 29
/**
 * @class NdbScanOperation
 * @brief Class of scan operations for use in transactions.  
 */
joreland@mysql.com's avatar
joreland@mysql.com committed
30
class NdbScanOperation : public NdbOperation {
31
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
32
  friend class Ndb;
33
  friend class NdbTransaction;
34 35
  friend class NdbResultSet;
  friend class NdbOperation;
joreland@mysql.com's avatar
joreland@mysql.com committed
36
  friend class NdbBlob;
37 38
#endif

39
public:
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
  /**
   * Scan flags.  OR-ed together and passed as second argument to
   * readTuples.
   */
  enum ScanFlag {
    SF_TupScan = (1 << 16),     // scan TUP - only LM_CommittedRead
    SF_OrderBy = (1 << 24),     // index scan in order
    SF_Descending = (2 << 24),  // index scan in descending order
    SF_ReadRangeNo = (4 << 24)  // enable @ref get_range_no
  };

  /**
   * readTuples
   * 
   * @param lock_mode Lock mode
   * @param scan_flags see @ref ScanFlag
   * @param parallel No of fragments to scan in parallel (0=max)
   */ 
  virtual
  int readTuples(LockMode lock_mode = LM_Read, 
                 Uint32 scan_flags = 0, Uint32 parallel = 0);

#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
63
  /**
64
   * readTuples
65
   * 
66
   * @param lock_mode Lock mode
joreland@mysql.com's avatar
joreland@mysql.com committed
67
   * @param batch No of rows to fetch from each fragment at a time
68
   * @param parallel No of fragments to scan in parallell
joreland@mysql.com's avatar
joreland@mysql.com committed
69
   * @note specifying 0 for batch and parallall means max performance
70
   */ 
71
#ifdef ndb_readtuples_impossible_overload
72
  int readTuples(LockMode lock_mode = LM_Read, 
73
		 Uint32 batch = 0, Uint32 parallel = 0);
74
#endif
75
  
76
  inline int readTuples(int parallell){
joreland@mysql.com's avatar
joreland@mysql.com committed
77 78 79
    return readTuples(LM_Read, 0, parallell);
  }
  
80
  inline int readTuplesExclusive(int parallell = 0){
joreland@mysql.com's avatar
joreland@mysql.com committed
81 82
    return readTuples(LM_Exclusive, 0, parallell);
  }
83
#endif
joreland@mysql.com's avatar
joreland@mysql.com committed
84
  
85
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
pekka@mysql.com's avatar
pekka@mysql.com committed
86 87
  NdbBlob* getBlobHandle(const char* anAttrName);
  NdbBlob* getBlobHandle(Uint32 anAttrId);
88
#endif
pekka@mysql.com's avatar
pekka@mysql.com committed
89

90 91 92
  /**
   * Get the next tuple in a scan transaction. 
   * 
93
   * After each call to nextResult
94 95 96 97
   * the buffers and NdbRecAttr objects defined in 
   * NdbOperation::getValue are updated with values 
   * from the scanned tuple. 
   *
98 99
   * @param fetchAllowed  If set to false, then fetching is disabled
   * @param forceSend If true send will occur immediately (see @ref secAdapt)
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
   *
   * The NDB API will contact the NDB Kernel for more tuples 
   * when necessary to do so unless you set the fetchAllowed 
   * to false. 
   * This will force NDB to process any records it
   * already has in it's caches. When there are no more cached 
   * records it will return 2. You must then call nextResult
   * with fetchAllowed = true in order to contact NDB for more 
   * records.
   *
   * fetchAllowed = false is useful when you want to update or 
   * delete all the records fetched in one transaction(This will save a
   *  lot of round trip time and make updates or deletes of scanned 
   * records a lot faster). 
   * While nextResult(false)
   * returns 0 take over the record to another transaction. When 
   * nextResult(false) returns 2 you must execute and commit the other 
   * transaction. This will cause the locks to be transferred to the 
   * other transaction, updates or deletes will be made and then the 
   * locks will be released.
   * After that, call nextResult(true) which will fetch new records and
   * cache them in the NdbApi. 
   * 
   * @note  If you don't take over the records to another transaction the 
   *        locks on those records will be released the next time NDB Kernel
   *        is contacted for more records.
   *
   * @note  Please contact for examples of efficient scan
   *        updates and deletes.
   * 
   * @note  See ndb/examples/ndbapi_scan_example for usage.
   *
   * @return 
   * -  -1: if unsuccessful,<br>
   * -   0: if another tuple was received, and<br> 
   * -   1: if there are no more tuples to scan.
   * -   2: if there are no more cached records in NdbApi
   */
  int nextResult(bool fetchAllowed = true, bool forceSend = false);

  /**
141
   * Close scan
142
   */
143
  void close(bool forceSend = false, bool releaseOp = false);
joreland@mysql.com's avatar
joreland@mysql.com committed
144

145
  /**
146
   * Update current tuple
147 148 149 150
   *
   * @return an NdbOperation or NULL.
   */
  NdbOperation* updateCurrentTuple();
151 152 153 154 155 156 157
  /**
   * Update current tuple
   *
   * @param updateTrans Transaction that should perform the update
   *
   * @return an NdbOperation or NULL.
   */
158
  NdbOperation*	updateCurrentTuple(NdbTransaction* updateTrans);
159 160

  /**
161 162
   * Delete current tuple
   * @return 0 on success or -1 on failure
163 164
   */
  int deleteCurrentTuple();
165 166 167 168 169 170 171
  /**
   * Delete current tuple
   *
   * @param takeOverTransaction Transaction that should perform the delete
   *
   * @return 0 on success or -1 on failure
   */
172
  int deleteCurrentTuple(NdbTransaction* takeOverTransaction);
173
  
174 175 176 177 178 179
  /**
   * Restart scan with exactly the same
   *   getValues and search conditions
   */
  int restart(bool forceSend = false);
  
180
protected:
181
  NdbScanOperation(Ndb* aNdb);
182
  virtual ~NdbScanOperation();
183

184
  int nextResultImpl(bool fetchAllowed = true, bool forceSend = false);
185 186
  virtual void release();
  
mronstrom@mysql.com[mikron]'s avatar
mronstrom@mysql.com[mikron] committed
187 188
  int close_impl(class TransporterFacade*, bool forceSend,
                 PollGuard *poll_guard);
189 190 191 192 193

  // Overloaded methods from NdbCursorOperation
  int executeCursor(int ProcessorId);

  // Overloaded private methods from NdbOperation
194
  int init(const NdbTableImpl* tab, NdbTransaction*);
195 196 197 198 199 200
  int prepareSend(Uint32  TC_ConnectPtr, Uint64  TransactionId);
  int doSend(int ProcessorId);

  virtual void setErrorCode(int aErrorCode);
  virtual void setErrorCodeAbort(int aErrorCode);

201
  NdbTransaction *m_transConnection;
202

joreland@mysql.com's avatar
joreland@mysql.com committed
203 204 205
  // Scan related variables
  Uint32 theParallelism;
  Uint32 m_keyInfo;
206

joreland@mysql.com's avatar
joreland@mysql.com committed
207 208 209 210
  int getFirstATTRINFOScan();
  int doSendScan(int ProcessorId);
  int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId);
  
joreland@mysql.com's avatar
joreland@mysql.com committed
211
  int fix_receivers(Uint32 parallel);
212
  void reset_receivers(Uint32 parallel, Uint32 ordered);
joreland@mysql.com's avatar
joreland@mysql.com committed
213
  Uint32* m_array; // containing all arrays below
joreland@mysql.com's avatar
joreland@mysql.com committed
214 215
  Uint32 m_allocated_receivers;
  NdbReceiver** m_receivers;      // All receivers
216

joreland@mysql.com's avatar
joreland@mysql.com committed
217
  Uint32* m_prepared_receivers;   // These are to be sent
218 219 220 221

  /**
   * owned by API/user thread
   */
joreland@mysql.com's avatar
joreland@mysql.com committed
222 223 224 225
  Uint32 m_current_api_receiver;
  Uint32 m_api_receivers_count;
  NdbReceiver** m_api_receivers;  // These are currently used by api
  
226 227 228
  /**
   * owned by receiver thread
   */
joreland@mysql.com's avatar
joreland@mysql.com committed
229 230 231
  Uint32 m_conf_receivers_count;  // NOTE needs mutex to access
  NdbReceiver** m_conf_receivers; // receive thread puts them here
  
232 233 234
  /**
   * owned by receiver thread
   */
joreland@mysql.com's avatar
joreland@mysql.com committed
235 236 237
  Uint32 m_sent_receivers_count;  // NOTE needs mutex to access
  NdbReceiver** m_sent_receivers; // receive thread puts them here
  
mronstrom@mysql.com[mikron]'s avatar
mronstrom@mysql.com[mikron] committed
238
  int send_next_scan(Uint32 cnt, bool close);
joreland@mysql.com's avatar
joreland@mysql.com committed
239 240
  void receiver_delivered(NdbReceiver*);
  void receiver_completed(NdbReceiver*);
241
  void execCLOSE_SCAN_REP();
242

joreland@mysql.com's avatar
joreland@mysql.com committed
243
  int getKeyFromKEYINFO20(Uint32* data, unsigned size);
244
  NdbOperation*	takeOverScanOp(OperationType opType, NdbTransaction*);
joreland@mysql.com's avatar
joreland@mysql.com committed
245
  
246 247
  bool m_ordered;
  bool m_descending;
248
  Uint32 m_read_range_no;
249
  NdbRecAttr *m_curr_row; // Pointer to last returned row
250
  bool m_executed; // Marker if operation should be released at close
251 252 253
};

inline
254 255 256 257 258 259 260
NdbOperation* 
NdbScanOperation::updateCurrentTuple(){
  return updateCurrentTuple(m_transConnection);
}

inline
NdbOperation* 
261
NdbScanOperation::updateCurrentTuple(NdbTransaction* takeOverTrans){
262 263 264 265 266 267 268 269 270 271 272 273
  return takeOverScanOp(NdbOperation::UpdateRequest, 
			takeOverTrans);
}

inline
int
NdbScanOperation::deleteCurrentTuple(){
  return deleteCurrentTuple(m_transConnection);
}

inline
int
274
NdbScanOperation::deleteCurrentTuple(NdbTransaction * takeOverTrans){
275 276 277 278 279
  void * res = takeOverScanOp(NdbOperation::DeleteRequest, 
			      takeOverTrans);
  if(res == 0)
    return -1;
  return 0;
280 281 282
}

#endif