1 21 22 package org.apache.derby.impl.store.raw.data; 23 24 import org.apache.derby.iapi.reference.SQLState; 25 26 import org.apache.derby.impl.store.raw.data.BasePage; 27 28 import org.apache.derby.iapi.services.sanity.SanityManager; 29 import org.apache.derby.iapi.services.io.FormatIdUtil; 30 import org.apache.derby.iapi.services.io.StoredFormatIds; 31 32 import org.apache.derby.iapi.store.raw.Page; 33 import org.apache.derby.iapi.store.raw.RecordHandle; 34 import org.apache.derby.iapi.store.raw.Transaction; 35 import org.apache.derby.iapi.store.raw.log.LogInstant; 36 import org.apache.derby.iapi.store.raw.xact.RawTransaction; 37 38 import org.apache.derby.iapi.error.StandardException; 39 40 import org.apache.derby.iapi.services.io.CompressedNumber; 41 import org.apache.derby.iapi.services.io.FormatableBitSet; 42 import org.apache.derby.iapi.util.ByteArray; 43 import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream; 44 45 46 import java.io.OutputStream ; 47 import java.io.ObjectOutput ; 48 import java.io.ObjectInput ; 49 import java.io.IOException ; 50 import org.apache.derby.iapi.services.io.LimitObjectInput; 51 52 72 public class CopyRowsOperation extends PhysicalPageOperation { 73 74 protected int num_rows; 75 protected int destSlot; protected int[] recordIds; protected int[] reservedSpace; 79 transient protected ByteArray preparedLog; 80 81 public CopyRowsOperation(RawTransaction t, BasePage destPage, BasePage srcPage, 82 int destSlot, int num_rows, 83 int srcSlot, int[] recordIds) 84 throws StandardException 85 { 86 super(destPage); 87 88 this.num_rows = num_rows; 89 this.destSlot = destSlot; 90 this.recordIds = recordIds; 91 92 try { 93 reservedSpace = new int[num_rows]; 94 for (int i = 0; i < num_rows; i++) { 95 reservedSpace[i] = srcPage.getReservedCount(i + srcSlot); 96 } 97 98 writeOptionalDataToBuffer(t, srcPage, srcSlot); 99 } catch (IOException ioe) { 100 throw StandardException.newException( 101 SQLState.DATA_UNEXPECTED_EXCEPTION, ioe); 102 } 103 } 104 105 108 109 public CopyRowsOperation() { super(); } 111 114 public void writeExternal(ObjectOutput out) throws IOException 115 { 116 super.writeExternal(out); 117 118 CompressedNumber.writeInt(out, num_rows); 119 CompressedNumber.writeInt(out, destSlot); 120 121 for (int i = 0; i < num_rows; i++) { 122 CompressedNumber.writeInt(out, recordIds[i]); 123 CompressedNumber.writeInt(out, reservedSpace[i]); 124 } 125 } 126 127 132 public void readExternal(ObjectInput in) 133 throws IOException , ClassNotFoundException 134 { 135 super.readExternal(in); 136 137 num_rows = CompressedNumber.readInt(in); 138 destSlot = CompressedNumber.readInt(in); 139 140 recordIds = new int[num_rows]; 141 reservedSpace = new int[num_rows]; 142 for (int i = 0; i < num_rows; i++) { 143 recordIds[i] = CompressedNumber.readInt(in); 144 reservedSpace[i] = CompressedNumber.readInt(in); 145 } 146 } 147 148 151 public int getTypeFormatId() { 152 return StoredFormatIds.LOGOP_COPY_ROWS; 153 } 154 155 158 164 public void doMe(Transaction xact, LogInstant instant, LimitObjectInput in) 165 throws StandardException, IOException 166 { 167 170 for (int i = 0; i < num_rows; i++) 171 { 172 page.storeRecord(instant, destSlot+i, true, in); 173 174 if (reservedSpace[i] > 0) 175 page.reserveSpaceForSlot(instant, destSlot + i, reservedSpace[i]); 176 } 177 } 178 179 182 183 190 public void undoMe(Transaction xact, BasePage undoPage, 191 LogInstant CLRInstant, LimitObjectInput in) 192 throws StandardException, IOException 193 { 194 199 int slot; 200 201 for (int i = num_rows-1; i >= 0; i--) 202 { 203 slot = undoPage.findRecordById(recordIds[i], i); 204 undoPage.purgeRecord(CLRInstant, slot, recordIds[i]); 205 } 206 207 undoPage.setAuxObject(null); 208 } 209 210 213 214 220 public void restoreMe(Transaction xact, BasePage undoPage, 221 LogInstant CLRInstant, LimitObjectInput in) 222 throws StandardException, IOException 223 { 224 undoMe(xact, undoPage, CLRInstant, in); 225 } 226 227 232 233 public ByteArray getPreparedLog() 234 { 235 return (this.preparedLog); 236 } 237 238 245 private void writeOptionalDataToBuffer(RawTransaction t, BasePage srcPage, int srcSlot) 246 throws StandardException, IOException 247 { 248 if (SanityManager.DEBUG) { 249 SanityManager.ASSERT(this.page != null); 250 SanityManager.ASSERT(srcPage != null); 251 } 252 253 DynamicByteArrayOutputStream logBuffer = t.getLogBuffer(); 254 int optionalDataStart = logBuffer.getPosition(); 255 256 if (SanityManager.DEBUG) { 257 SanityManager.ASSERT(optionalDataStart == 0, 258 "Buffer for writing the optional data should start at position 0"); 259 } 260 261 int[] spaceNeeded = new int[num_rows]; 264 int startPosition = logBuffer.getPosition(); 265 266 for (int i = 0; i < num_rows; i++) 267 { 268 srcPage.logRecord(i + srcSlot, BasePage.LOG_RECORD_DEFAULT, 272 recordIds[i], (FormatableBitSet) null, logBuffer, 273 (RecordHandle)null); 274 spaceNeeded[i] = logBuffer.getPosition() - startPosition; 275 startPosition = logBuffer.getPosition(); 276 277 spaceNeeded[i] += reservedSpace[i]; 282 } 283 284 if (!page.spaceForCopy(num_rows, spaceNeeded)) 286 { 287 throw StandardException.newException( 288 SQLState.DATA_NO_SPACE_FOR_RECORD); 289 } 290 291 int optionalDataLength = logBuffer.getPosition() - optionalDataStart; 292 293 if (SanityManager.DEBUG) { 294 if (optionalDataLength != logBuffer.getUsed()) 295 SanityManager.THROWASSERT("wrong optional data length, optionalDataLength = " 296 + optionalDataLength + ", logBuffer.getUsed() = " + logBuffer.getUsed()); 297 } 298 299 logBuffer.setPosition(optionalDataStart); 301 302 this.preparedLog = new ByteArray(logBuffer.getByteArray(), optionalDataStart, 303 optionalDataLength); 304 } 305 306 309 public String toString() 310 { 311 if (SanityManager.DEBUG) 312 { 313 String str = super.toString() + 314 "CopyRows : " + num_rows + " to slots starting at " + destSlot; 315 316 for (int i = 0; i < num_rows; i++) 317 { 318 str += " (recordId=" + recordIds[i] + ")"; 319 } 320 return str; 321 } 322 else 323 return null; 324 } 325 } 326 | Popular Tags |