2 * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
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.
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.
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
18 package com.mysql.clusterj.tie;
20 import java.nio.ByteBuffer;
21 import java.util.ArrayList;
22 import java.util.List;
24 import com.mysql.clusterj.core.store.Column;
25 import com.mysql.clusterj.core.store.PartitionKey;
26 import com.mysql.clusterj.core.util.I18NHelper;
27 import com.mysql.clusterj.core.util.Logger;
28 import com.mysql.clusterj.core.util.LoggerFactoryService;
29 import com.mysql.clusterj.tie.DbImpl.BufferManager;
30 import com.mysql.ndbjtie.ndbapi.NdbOperation;
31 import com.mysql.ndbjtie.ndbapi.NdbTransaction;
34 * This class manages the startTransaction operation based on partition keys.
36 class PartitionKeyImpl implements PartitionKey {
38 /** My message translator */
39 static final I18NHelper local = I18NHelper
40 .getInstance(PartitionKeyImpl.class);
43 static final Logger logger = LoggerFactoryService.getFactory()
44 .getInstance(PartitionKeyImpl.class);
46 private static PartitionKeyImpl theInstance = new PartitionKeyImpl();
48 /** The partition key part builders */
49 private List<KeyPartBuilder> keyPartBuilders = new ArrayList<KeyPartBuilder>();
51 /** The partition key parts */
52 private List<KeyPart> keyParts = new ArrayList<KeyPart>();
55 private String tableName = null;
57 /** The partition id */
58 private int partitionId;
60 /** Add an int key to the partition key.
61 * The partition key will actually be constructed when needed, at enlist time.
63 public void addIntKey(final Column storeColumn, final int key) {
64 keyPartBuilders.add(new KeyPartBuilder() {
65 public void addKeyPart(BufferManager bufferManager) {
66 ByteBuffer buffer = Utility.convertValue(storeColumn, key);
67 KeyPart keyPart = new KeyPart(buffer, buffer.limit());
68 keyParts.add(keyPart);
73 /** Add a long key to the partition key.
74 * The partition key will actually be constructed when needed, at enlist time.
76 public void addLongKey(final Column storeColumn, final long key) {
77 keyPartBuilders.add(new KeyPartBuilder() {
78 public void addKeyPart(BufferManager bufferManager) {
79 ByteBuffer buffer = Utility.convertValue(storeColumn, key);
80 KeyPart keyPart = new KeyPart(buffer, buffer.limit());
81 keyParts.add(keyPart);
86 /** Add a String key to the partition key.
87 * The partition key will actually be constructed when needed, at enlist time.
88 * This is done so that the buffer manager can be used to efficiently create
89 * the encoded string key. The buffer manager is not know at the time this method
92 public void addStringKey(final Column storeColumn, final String string) {
93 keyPartBuilders.add(new KeyPartBuilder() {
94 public void addKeyPart(BufferManager bufferManager) {
95 ByteBuffer buffer = Utility.encode(string, storeColumn, bufferManager);
96 // allocate a new buffer because the shared buffer might be overwritten by another key field
97 ByteBuffer copy = ByteBuffer.allocateDirect(buffer.limit() - buffer.position());
100 KeyPart keyPart = new KeyPart(copy, copy.limit());
101 keyParts.add(keyPart);
106 /** Add a byte array key to the partition key.
107 * The partition key will actually be constructed when needed, at enlist time.
109 public void addBytesKey(final Column storeColumn, final byte[] key) {
110 keyPartBuilders.add(new KeyPartBuilder() {
111 public void addKeyPart(BufferManager bufferManager) {
112 ByteBuffer buffer = Utility.convertValue(storeColumn, key);
113 KeyPart keyPart = new KeyPart(buffer, buffer.limit());
114 keyParts.add(keyPart);
119 public void setTable(String tableName) {
120 this.tableName = tableName;
123 public void setPartitionId(int partitionId) {
124 this.partitionId = partitionId;
127 protected void handleError(int returnCode, NdbOperation ndbOperation) {
128 if (returnCode == 0) {
131 Utility.throwError(returnCode, ndbOperation.getNdbError());
135 protected static void handleError(Object object, NdbOperation ndbOperation) {
136 if (object != null) {
139 Utility.throwError(null, ndbOperation.getNdbError());
143 public NdbTransaction enlist(DbImpl db) {
144 BufferManager bufferManager = db.getBufferManager();
145 // construct the keyParts now that buffer manager is available
146 for (KeyPartBuilder keyPartBuilder: keyPartBuilders) {
147 keyPartBuilder.addKeyPart(bufferManager);
149 NdbTransaction result = null;
150 if (keyParts == null || keyParts.size() == 0) {
151 if (logger.isDebugEnabled()) logger.debug(
152 "PartitionKeyImpl.enlist via partitionId with keyparts "
153 + (keyParts==null?"null.":("size " + keyParts.size()))
154 + " table: " + (tableName==null?"null":tableName)
155 + " partition id: " + partitionId);
156 result = db.enlist(tableName, partitionId);
158 if (logger.isDebugEnabled()) logger.debug(
159 "PartitionKeyImpl.enlist via keyParts with keyparts "
160 + (keyParts==null?"null.":("size " + keyParts.size()))
161 + " table: " + (tableName==null?"null":tableName));
162 result = db.enlist(tableName, keyParts);
167 /** Get a singleton instance of PartitionKeyImpl that doesn't name a specific table.
169 * @return the instance
171 public static PartitionKeyImpl getInstance() {
175 private static interface KeyPartBuilder {
176 public void addKeyPart(BufferManager bufferManager);