MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DbImpl.java
1 /*
2  * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17 
18 package com.mysql.clusterj.tie;
19 
20 import java.nio.ByteBuffer;
21 import java.nio.CharBuffer;
22 import java.util.List;
23 
24 import com.mysql.ndbjtie.ndbapi.Ndb;
25 import com.mysql.ndbjtie.ndbapi.Ndb.Key_part_ptr;
26 import com.mysql.ndbjtie.ndbapi.Ndb.Key_part_ptrArray;
27 
28 import com.mysql.ndbjtie.ndbapi.NdbErrorConst;
29 import com.mysql.ndbjtie.ndbapi.NdbTransaction;
30 import com.mysql.ndbjtie.ndbapi.NdbDictionary.Dictionary;
31 import com.mysql.ndbjtie.ndbapi.NdbDictionary.TableConst;
32 
33 import com.mysql.clusterj.ClusterJDatastoreException;
34 import com.mysql.clusterj.ClusterJFatalInternalException;
35 import com.mysql.clusterj.core.store.ClusterConnection;
36 import com.mysql.clusterj.core.store.ClusterTransaction;
37 
38 import com.mysql.clusterj.core.util.I18NHelper;
39 import com.mysql.clusterj.core.util.Logger;
40 import com.mysql.clusterj.core.util.LoggerFactoryService;
41 
45 class DbImpl implements com.mysql.clusterj.core.store.Db {
46 
48  static final I18NHelper local = I18NHelper.getInstance(DbImpl.class);
49 
51  static final Logger logger = LoggerFactoryService.getFactory()
52  .getInstance(com.mysql.clusterj.core.store.ClusterConnection.class);
53 
55  private Ndb ndb;
56 
57  // TODO change the allocation to a constant in ndbjtie
58  private int errorBufferSize = 300;
59 
61  private ByteBuffer errorBuffer = ByteBuffer.allocateDirect(errorBufferSize);
62 
63  // TODO change the allocation to a constant in ndbjtie
65  private int coordinatedTransactionIdBufferSize = 26;
66 
68  private ByteBuffer coordinatedTransactionIdBuffer =
69  ByteBuffer.allocateDirect(coordinatedTransactionIdBufferSize);
70 
71  // TODO change the allocation to something reasonable
73  private ByteBuffer partitionKeyScratchBuffer = ByteBuffer.allocateDirect(10000);
74 
76  private BufferManager bufferManager = new BufferManager();
77 
79  private Dictionary ndbDictionary;
80 
82  private DictionaryImpl dictionary;
83 
85  private ClusterConnection clusterConnection;
86 
87  public DbImpl(ClusterConnection clusterConnection, Ndb ndb, int maxTransactions) {
88  this.clusterConnection = clusterConnection;
89  this.ndb = ndb;
90  int returnCode = ndb.init(maxTransactions);
91  handleError(returnCode, ndb);
92  ndbDictionary = ndb.getDictionary();
93  handleError(ndbDictionary, ndb);
94  this.dictionary = new DictionaryImpl(ndbDictionary);
95  }
96 
97  public void close() {
98  Ndb.delete(ndb);
99  clusterConnection.close(this);
100  }
101 
102  public com.mysql.clusterj.core.store.Dictionary getDictionary() {
103  return dictionary;
104  }
105 
106  public ClusterTransaction startTransaction(String joinTransactionId) {
107  return new ClusterTransactionImpl(this, ndbDictionary, joinTransactionId);
108  }
109 
110  protected void handleError(int returnCode, Ndb ndb) {
111  if (returnCode == 0) {
112  return;
113  } else {
114  NdbErrorConst ndbError = ndb.getNdbError();
115  String detail = getNdbErrorDetail(ndbError);
116  Utility.throwError(returnCode, ndbError, detail);
117  }
118  }
119 
120  protected void handleError(Object object, Ndb ndb) {
121  if (object != null) {
122  return;
123  } else {
124  NdbErrorConst ndbError = ndb.getNdbError();
125  String detail = getNdbErrorDetail(ndbError);
126  Utility.throwError(null, ndbError, detail);
127  }
128  }
129 
130  public boolean isRetriable(ClusterJDatastoreException ex) {
131  return Utility.isRetriable(ex);
132  }
133 
134  public String getNdbErrorDetail(NdbErrorConst ndbError) {
135  return ndb.getNdbErrorDetail(ndbError, errorBuffer, errorBuffer.capacity());
136  }
137 
145  public NdbTransaction enlist(String tableName, List<KeyPart> keyParts) {
146  if (keyParts == null || keyParts.size() <= 0) {
147  throw new ClusterJFatalInternalException(
148  local.message("ERR_Key_Parts_Must_Not_Be_Null_Or_Zero_Length",
149  tableName));
150  }
151  int keyPartsSize = keyParts.size();
152  NdbTransaction ndbTransaction = null;
153  TableConst table = ndbDictionary.getTable(tableName);
154  handleError(table, ndb);
155  Key_part_ptrArray key_part_ptrArray = null;
156  if (keyPartsSize == 1) {
157  // extract the ByteBuffer and length from the keyPart
158  ByteBuffer buffer = keyParts.get(0).buffer;
159  int length = keyParts.get(0).length;
160  ndbTransaction = ndb.startTransaction(table, buffer, length);
161  if (ndbTransaction == null) {
162  logger.warn(local.message("ERR_Transaction_Start_Failed",
163  tableName, buffer.position(), buffer.limit(), buffer.capacity(), length));
164  }
165  handleError (ndbTransaction, ndb);
166  return ndbTransaction;
167  }
168  key_part_ptrArray = Key_part_ptrArray.create(keyPartsSize + 1);
169  try {
170  // the key part pointer array has one entry for each key part
171  // plus one extra for "null-terminated array concept"
172  Key_part_ptr key_part_ptr;
173  for (int i = 0; i < keyPartsSize; ++i) {
174  // each key part ptr consists of a ByteBuffer (char *) and length
175  key_part_ptr = key_part_ptrArray.at(i);
176  key_part_ptr.ptr(keyParts.get(i).buffer);
177  key_part_ptr.len(keyParts.get(i).length);
178  }
179  // the last key part needs to be initialized to (char *)null
180  key_part_ptr = key_part_ptrArray.at(keyPartsSize);
181  key_part_ptr.ptr(null);
182  key_part_ptr.len(0);
183  ndbTransaction = ndb.startTransaction(
184  table, key_part_ptrArray,
185  partitionKeyScratchBuffer, partitionKeyScratchBuffer.capacity());
186  handleError (ndbTransaction, ndb);
187  return ndbTransaction;
188  } finally {
189  // even if error, delete the key part array to avoid memory leaks
190  Key_part_ptrArray.delete(key_part_ptrArray);
191  }
192  }
193 
202  public NdbTransaction enlist(String tableName, int partitionId) {
203  NdbTransaction result = null;
204  if (tableName == null) {
205  result = ndb.startTransaction(null, null, 0);
206  } else {
207  TableConst table= ndbDictionary.getTable(tableName);
208  result = ndb.startTransaction(table, partitionId);
209  }
210  handleError (result, ndb);
211  return result;
212  }
213 
220  public ByteBuffer getCoordinatedTransactionIdBuffer() {
221  return coordinatedTransactionIdBuffer;
222  }
223 
231  public NdbTransaction joinTransaction(String coordinatedTransactionId) {
232  if (logger.isDetailEnabled()) logger.detail("CoordinatedTransactionId: "
233  + coordinatedTransactionId);
234 // NdbTransaction result = ndb.joinTransaction(coordinatedTransactionId);
235 // handleError(result, ndb);
236 // return result;
237  throw new ClusterJFatalInternalException("Not Implemented");
238  }
239 
244  public BufferManager getBufferManager() {
245  return bufferManager;
246  }
247 
248  public class BufferManager {
250  public static final int STRING_BYTE_BUFFER_INITIAL_SIZE = 1000;
251 
253  private int stringByteBufferCurrentSize = STRING_BYTE_BUFFER_INITIAL_SIZE;
254 
257  ByteBuffer stringByteBuffer = null;
258  CharBuffer stringCharBuffer = null;
259 
261  public static final int STRING_STORAGE_BUFFER_INITIAL_SIZE = 500;
262 
264  private ByteBuffer stringStorageBuffer = ByteBuffer.allocateDirect(STRING_STORAGE_BUFFER_INITIAL_SIZE);
265 
267  private static final int RESULT_DATA_BUFFER_INITIAL_SIZE = 8000;
268 
270  private ByteBuffer resultDataBuffer = ByteBuffer.allocateDirect(RESULT_DATA_BUFFER_INITIAL_SIZE);
271 
277  public void guaranteeStringStorageBufferSize(int sizeNeeded) {
278  if (sizeNeeded > stringStorageBuffer.capacity()) {
279  if (logger.isDebugEnabled()) logger.debug(local.message("MSG_Reallocated_Byte_Buffer",
280  "string storage", stringStorageBuffer.capacity(), sizeNeeded));
281  // the existing shared buffer will be garbage collected
282  stringStorageBuffer = ByteBuffer.allocateDirect(sizeNeeded);
283  }
284  stringStorageBuffer.limit(stringStorageBuffer.capacity());
285  }
286 
292  public ByteBuffer copyStringToByteBuffer(CharSequence value) {
293  if (value == null) {
294  stringByteBuffer.limit(0);
295  return stringByteBuffer;
296  }
297  int sizeNeeded = value.length() * 2;
298  guaranteeStringByteBufferSize(sizeNeeded);
299  stringCharBuffer.append(value);
300  // characters in java are always two bytes (UCS-16)
301  stringByteBuffer.limit(stringCharBuffer.position() * 2);
302  return stringByteBuffer;
303  }
304 
308  public void clearStringStorageBuffer() {
309  stringStorageBuffer.clear();
310  }
311 
312  public ByteBuffer getStringStorageBuffer(int sizeNeeded) {
314  return stringStorageBuffer;
315  }
316 
317  public ByteBuffer getStringByteBuffer(int sizeNeeded) {
318  guaranteeStringByteBufferSize(sizeNeeded);
319  return stringByteBuffer;
320  }
321 
327  protected void guaranteeStringByteBufferSize(int sizeNeeded) {
328  if (sizeNeeded > stringByteBufferCurrentSize) {
329  stringByteBufferCurrentSize = sizeNeeded;
330  stringByteBuffer = ByteBuffer.allocateDirect(stringByteBufferCurrentSize);
331  stringCharBuffer = stringByteBuffer.asCharBuffer();
332  }
333  if (stringByteBuffer == null) {
334  stringByteBuffer = ByteBuffer.allocateDirect(stringByteBufferCurrentSize);
335  stringCharBuffer = stringByteBuffer.asCharBuffer();
336  } else {
337  stringByteBuffer.clear();
338  stringCharBuffer.clear();
339  }
340  }
341 
346  public CharBuffer getStringCharBuffer() {
347  return stringCharBuffer;
348  }
349 
355  public ByteBuffer getResultDataBuffer(int sizeNeeded) {
356  if (sizeNeeded > resultDataBuffer.capacity()) {
357  if (logger.isDebugEnabled()) logger.debug(local.message("MSG_Reallocated_Byte_Buffer",
358  "result data", resultDataBuffer.capacity(), sizeNeeded));
359  // the existing result data buffer will be garbage collected
360  resultDataBuffer = ByteBuffer.allocateDirect(sizeNeeded);
361  }
362  resultDataBuffer.clear();
363  return resultDataBuffer;
364  }
365 
366  }
367 
368 }