1 /* 2 Copyright (c) 2009, 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, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License, version 2.0, for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 package com.mysql.clusterj.tie; 26 27 import java.math.BigDecimal; 28 import java.math.BigInteger; 29 import java.nio.ByteBuffer; 30 import java.util.ArrayList; 31 import java.util.Arrays; 32 import java.util.List; 33 34 import com.mysql.clusterj.core.store.Blob; 35 import com.mysql.clusterj.core.store.Column; 36 import com.mysql.clusterj.core.store.Operation; 37 import com.mysql.clusterj.core.store.ResultData; 38 import com.mysql.clusterj.core.store.Table; 39 40 import com.mysql.clusterj.core.util.I18NHelper; 41 import com.mysql.clusterj.core.util.Logger; 42 import com.mysql.clusterj.core.util.LoggerFactoryService; 43 import com.mysql.clusterj.tie.DbImpl.BufferManager; 44 45 import com.mysql.ndbjtie.ndbapi.NdbBlob; 46 import com.mysql.ndbjtie.ndbapi.NdbOperation; 47 48 /** 49 * 50 */ 51 class OperationImpl implements Operation { 52 53 /** My message translator */ 54 static final I18NHelper local = I18NHelper 55 .getInstance(OperationImpl.class); 56 57 /** My logger */ 58 static final Logger logger = LoggerFactoryService.getFactory() 59 .getInstance(OperationImpl.class); 60 61 private NdbOperation ndbOperation; 62 63 protected List<Column> storeColumns = new ArrayList<Column>(); 64 65 protected ClusterTransactionImpl clusterTransaction; 66 67 /** The size of the receive buffer for this operation (may be zero for non-read operations) */ 68 protected int bufferSize; 69 70 /** The maximum column id for this operation (may be zero for non-read operations) */ 71 protected int maximumColumnId; 72 73 /** The offsets into the buffer for each column (may be null for non-read operations) */ 74 protected int[] offsets; 75 76 /** The lengths of fields in the buffer for each column (may be null for non-read operations) */ 77 protected int[] lengths; 78 79 /** The maximum length of any column in this operation */ 80 protected int maximumColumnLength; 81 82 protected BufferManager bufferManager; 83 84 /** Constructor used for insert and delete operations that do not need to read data. 85 * 86 * @param operation the operation 87 * @param transaction the transaction 88 */ OperationImpl(NdbOperation operation, ClusterTransactionImpl transaction)89 public OperationImpl(NdbOperation operation, ClusterTransactionImpl transaction) { 90 this.ndbOperation = operation; 91 this.clusterTransaction = transaction; 92 this.bufferManager = clusterTransaction.getBufferManager(); 93 } 94 95 /** Constructor used for read operations. The table is used to obtain data used 96 * to lay out memory for the result. 97 * @param storeTable the table 98 * @param operation the operation 99 * @param transaction the transaction 100 */ OperationImpl(Table storeTable, NdbOperation operation, ClusterTransactionImpl transaction)101 public OperationImpl(Table storeTable, NdbOperation operation, ClusterTransactionImpl transaction) { 102 this(operation, transaction); 103 TableImpl tableImpl = (TableImpl)storeTable; 104 this.maximumColumnId = tableImpl.getMaximumColumnId(); 105 this.bufferSize = tableImpl.getBufferSize(); 106 this.offsets = tableImpl.getOffsets(); 107 this.lengths = tableImpl.getLengths(); 108 this.maximumColumnLength = tableImpl.getMaximumColumnLength(); 109 } 110 equalBigInteger(Column storeColumn, BigInteger value)111 public void equalBigInteger(Column storeColumn, BigInteger value) { 112 ByteBuffer buffer = Utility.convertValue(storeColumn, value); 113 int returnCode = ndbOperation.equal(storeColumn.getName(), buffer); 114 handleError(returnCode, ndbOperation); 115 } 116 equalBoolean(Column storeColumn, boolean booleanValue)117 public void equalBoolean(Column storeColumn, boolean booleanValue) { 118 byte value = (booleanValue?(byte)0x01:(byte)0x00); 119 int returnCode = ndbOperation.equal(storeColumn.getName(), value); 120 handleError(returnCode, ndbOperation); 121 } 122 equalByte(Column storeColumn, byte value)123 public void equalByte(Column storeColumn, byte value) { 124 int storeValue = Utility.convertByteValueForStorage(storeColumn, value); 125 int returnCode = ndbOperation.equal(storeColumn.getName(), storeValue); 126 handleError(returnCode, ndbOperation); 127 } 128 equalBytes(Column storeColumn, byte[] value)129 public void equalBytes(Column storeColumn, byte[] value) { 130 if (logger.isDetailEnabled()) logger.detail("Column: " + storeColumn.getName() + " columnId: " + storeColumn.getColumnId() + " data length: " + value.length); 131 ByteBuffer buffer = Utility.convertValue(storeColumn, value); 132 int returnCode = ndbOperation.equal(storeColumn.getName(), buffer); 133 handleError(returnCode, ndbOperation); 134 } 135 equalDecimal(Column storeColumn, BigDecimal value)136 public void equalDecimal(Column storeColumn, BigDecimal value) { 137 ByteBuffer buffer = Utility.convertValue(storeColumn, value); 138 int returnCode = ndbOperation.equal(storeColumn.getName(), buffer); 139 handleError(returnCode, ndbOperation); 140 } 141 equalDouble(Column storeColumn, double value)142 public void equalDouble(Column storeColumn, double value) { 143 ByteBuffer buffer = Utility.convertValue(storeColumn, value); 144 int returnCode = ndbOperation.equal(storeColumn.getName(), buffer); 145 handleError(returnCode, ndbOperation); 146 } 147 equalFloat(Column storeColumn, float value)148 public void equalFloat(Column storeColumn, float value) { 149 ByteBuffer buffer = Utility.convertValue(storeColumn, value); 150 int returnCode = ndbOperation.equal(storeColumn.getName(), buffer); 151 handleError(returnCode, ndbOperation); 152 } 153 equalInt(Column storeColumn, int value)154 public void equalInt(Column storeColumn, int value) { 155 int returnCode = ndbOperation.equal(storeColumn.getName(), value); 156 handleError(returnCode, ndbOperation); 157 } 158 equalShort(Column storeColumn, short value)159 public void equalShort(Column storeColumn, short value) { 160 int storeValue = Utility.convertShortValueForStorage(storeColumn, value); 161 int returnCode = ndbOperation.equal(storeColumn.getName(), storeValue); 162 handleError(returnCode, ndbOperation); 163 } 164 equalLong(Column storeColumn, long value)165 public void equalLong(Column storeColumn, long value) { 166 long storeValue = Utility.convertLongValueForStorage(storeColumn, value); 167 int returnCode = ndbOperation.equal(storeColumn.getName(), storeValue); 168 handleError(returnCode, ndbOperation); 169 } 170 equalString(Column storeColumn, String value)171 public void equalString(Column storeColumn, String value) { 172 ByteBuffer stringStorageBuffer = Utility.encode(value, storeColumn, bufferManager); 173 int returnCode = ndbOperation.equal(storeColumn.getName(), stringStorageBuffer); 174 bufferManager.clearStringStorageBuffer(); 175 handleError(returnCode, ndbOperation); 176 } 177 getBlob(Column storeColumn)178 public void getBlob(Column storeColumn) { 179 NdbBlob ndbBlob = ndbOperation.getBlobHandleM(storeColumn.getColumnId()); 180 handleError(ndbBlob, ndbOperation); 181 } 182 getBlobHandle(Column storeColumn)183 public Blob getBlobHandle(Column storeColumn) { 184 NdbBlob blobHandle = ndbOperation.getBlobHandleM(storeColumn.getColumnId()); 185 handleError(blobHandle, ndbOperation); 186 return new BlobImpl(blobHandle); 187 } 188 189 /** Specify the columns to be used for the operation. 190 * For now, just save the columns. When resultData is called, pass the columns 191 * to the ResultData constructor and then execute the operation. 192 * 193 */ getValue(Column storeColumn)194 public void getValue(Column storeColumn) { 195 storeColumns.add(storeColumn); 196 } 197 postExecuteCallback(Runnable callback)198 public void postExecuteCallback(Runnable callback) { 199 clusterTransaction.postExecuteCallback(callback); 200 } 201 202 /** Construct a new ResultData using the saved column data and then execute the operation. 203 * 204 */ resultData()205 public ResultData resultData() { 206 return resultData(true); 207 } 208 209 /** Construct a new ResultData and if requested, execute the operation. 210 * 211 */ resultData(boolean execute)212 public ResultData resultData(boolean execute) { 213 if (logger.isDetailEnabled()) logger.detail("storeColumns: " + Arrays.toString(storeColumns.toArray())); 214 ResultDataImpl result; 215 if (execute) { 216 result = new ResultDataImpl(ndbOperation, storeColumns, maximumColumnId, bufferSize, 217 offsets, lengths, bufferManager, false); 218 clusterTransaction.executeNoCommit(false, true); 219 } else { 220 result = new ResultDataImpl(ndbOperation, storeColumns, maximumColumnId, bufferSize, 221 offsets, lengths, bufferManager, true); 222 } 223 return result; 224 } 225 setBigInteger(Column storeColumn, BigInteger value)226 public void setBigInteger(Column storeColumn, BigInteger value) { 227 ByteBuffer buffer = Utility.convertValue(storeColumn, value); 228 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), buffer); 229 handleError(returnCode, ndbOperation); 230 } 231 setBoolean(Column storeColumn, Boolean value)232 public void setBoolean(Column storeColumn, Boolean value) { 233 byte byteValue = (value?(byte)0x01:(byte)0x00); 234 setByte(storeColumn, byteValue); 235 } 236 setByte(Column storeColumn, byte value)237 public void setByte(Column storeColumn, byte value) { 238 int storeValue = Utility.convertByteValueForStorage(storeColumn, value); 239 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), storeValue); 240 handleError(returnCode, ndbOperation); 241 } 242 setBytes(Column storeColumn, byte[] value)243 public void setBytes(Column storeColumn, byte[] value) { 244 // TODO use the string storage buffer instead of allocating a new buffer for each value 245 ByteBuffer buffer = Utility.convertValue(storeColumn, value); 246 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), buffer); 247 handleError(returnCode, ndbOperation); 248 } 249 setDecimal(Column storeColumn, BigDecimal value)250 public void setDecimal(Column storeColumn, BigDecimal value) { 251 ByteBuffer buffer = Utility.convertValue(storeColumn, value); 252 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), buffer); 253 handleError(returnCode, ndbOperation); 254 } 255 setDouble(Column storeColumn, Double value)256 public void setDouble(Column storeColumn, Double value) { 257 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), value); 258 handleError(returnCode, ndbOperation); 259 } 260 setFloat(Column storeColumn, Float value)261 public void setFloat(Column storeColumn, Float value) { 262 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), value); 263 handleError(returnCode, ndbOperation); 264 } 265 setInt(Column storeColumn, Integer value)266 public void setInt(Column storeColumn, Integer value) { 267 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), value); 268 handleError(returnCode, ndbOperation); 269 } 270 setLong(Column storeColumn, long value)271 public void setLong(Column storeColumn, long value) { 272 long storeValue = Utility.convertLongValueForStorage(storeColumn, value); 273 int returnCode = ndbOperation.setValue(storeColumn.getName(), storeValue); 274 handleError(returnCode, ndbOperation); 275 } 276 setNull(Column storeColumn)277 public void setNull(Column storeColumn) { 278 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), null); 279 handleError(returnCode, ndbOperation); 280 } 281 setShort(Column storeColumn, Short value)282 public void setShort(Column storeColumn, Short value) { 283 int storeValue = Utility.convertShortValueForStorage(storeColumn, value); 284 int returnCode = ndbOperation.setValue(storeColumn.getName(), storeValue); 285 handleError(returnCode, ndbOperation); 286 } 287 setString(Column storeColumn, String value)288 public void setString(Column storeColumn, String value) { 289 ByteBuffer stringStorageBuffer = Utility.encode(value, storeColumn, bufferManager); 290 int returnCode = ndbOperation.setValue(storeColumn.getColumnId(), stringStorageBuffer); 291 bufferManager.clearStringStorageBuffer(); 292 handleError(returnCode, ndbOperation); 293 } 294 errorCode()295 public int errorCode() { 296 return ndbOperation.getNdbError().code(); 297 } 298 handleError(int returnCode, NdbOperation ndbOperation)299 protected void handleError(int returnCode, NdbOperation ndbOperation) { 300 if (returnCode == 0) { 301 return; 302 } else { 303 Utility.throwError(returnCode, ndbOperation.getNdbError()); 304 } 305 } 306 handleError(Object object, NdbOperation ndbOperation)307 protected static void handleError(Object object, NdbOperation ndbOperation) { 308 if (object != null) { 309 return; 310 } else { 311 Utility.throwError(null, ndbOperation.getNdbError()); 312 } 313 } 314 315 } 316