1 21 22 package org.apache.derby.impl.store.raw.data; 23 24 import org.apache.derby.iapi.reference.SQLState; 25 import org.apache.derby.impl.store.raw.data.BasePage; 26 import org.apache.derby.impl.store.raw.data.ReclaimSpace; 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.access.conglomerate.LogicalUndo; 33 34 import org.apache.derby.iapi.store.raw.PageKey; 35 import org.apache.derby.iapi.store.raw.Compensation; 36 import org.apache.derby.iapi.store.raw.Page; 37 import org.apache.derby.iapi.store.raw.RecordHandle; 38 import org.apache.derby.iapi.store.raw.Transaction; 39 40 import org.apache.derby.iapi.store.raw.log.LogInstant; 41 import org.apache.derby.iapi.store.raw.xact.RawTransaction; 42 43 import org.apache.derby.iapi.error.StandardException; 44 45 import org.apache.derby.iapi.types.DataValueDescriptor; 46 47 import org.apache.derby.iapi.services.io.CompressedNumber; 48 import org.apache.derby.iapi.services.io.FormatableBitSet; 49 import org.apache.derby.iapi.util.ByteArray; 50 import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream; 51 import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream; 52 53 import java.io.OutputStream ; 54 import java.io.ObjectOutput ; 55 import java.io.ObjectInput ; 56 import java.io.IOException ; 57 import org.apache.derby.iapi.services.io.LimitObjectInput; 58 59 60 79 public final class InsertOperation extends LogicalPageOperation 80 { 81 82 protected int doMeSlot; protected byte insertFlag; 85 86 transient protected int startColumn; 87 88 transient protected ByteArray preparedLog; 89 90 public InsertOperation( 92 RawTransaction t, 93 BasePage page, 94 int slot, 95 int recordId, 96 Object [] row, 97 FormatableBitSet validColumns, 98 LogicalUndo undo, 99 byte insertFlag, 100 int startColumn, 101 boolean isLongColumn, 102 int realStartColumn, 103 DynamicByteArrayOutputStream logBuffer, 104 int realSpaceOnPage, 105 int overflowThreshold) 106 throws StandardException 107 { 108 super(page, undo, recordId); 109 110 this.doMeSlot = slot; 111 this.insertFlag = insertFlag; 112 this.startColumn = startColumn; 113 114 try { 115 writeOptionalDataToBuffer(t, logBuffer, row, validColumns, 116 isLongColumn, realStartColumn, realSpaceOnPage, overflowThreshold); 117 } catch (IOException ioe) { 118 throw StandardException.newException( 119 SQLState.DATA_UNEXPECTED_EXCEPTION, ioe); 120 } 121 } 122 123 126 127 public InsertOperation() { super(); } 129 130 134 public void writeExternal(ObjectOutput out) throws IOException 135 { 136 super.writeExternal(out); 137 CompressedNumber.writeInt(out, doMeSlot); 138 out.writeByte(insertFlag); 139 140 } 141 142 147 public void readExternal(ObjectInput in) 148 throws IOException , ClassNotFoundException 149 { 150 super.readExternal(in); 151 doMeSlot = CompressedNumber.readInt(in); 152 insertFlag = in.readByte(); 153 } 154 155 158 public int getTypeFormatId() { 159 return StoredFormatIds.LOGOP_INSERT; 160 } 161 162 165 171 public void doMe(Transaction xact, LogInstant instant, LimitObjectInput in) 172 throws StandardException, IOException 173 { 174 this.page.storeRecord(instant, doMeSlot, true, in); 175 } 176 177 180 181 190 public void undoMe(Transaction xact, BasePage undoPage, int undoRecordId, 191 LogInstant CLRInstant, LimitObjectInput in) 192 throws StandardException, IOException 193 { 194 int slot = 195 undoPage.findRecordById(undoRecordId, Page.FIRST_SLOT_NUMBER); 196 197 if (SanityManager.DEBUG) 198 { 199 if (undoRecordId != this.recordId) 204 if (undoPage.getPageNumber() == getPageId().getPageNumber()) 205 SanityManager.THROWASSERT( 206 "recordId changed from " + this.recordId + 207 " to " + undoRecordId + 208 " but page number did not change " + 209 undoPage.getPageNumber()); 210 211 if (slot == -1) 212 SanityManager.THROWASSERT( 213 "recordId " + 214 undoRecordId + 215 " not found on page " + 216 undoPage.getPageNumber()); 217 } 218 219 if ((insertFlag & Page.INSERT_UNDO_WITH_PURGE) != 0) 220 { 221 undoPage.purgeRecord(CLRInstant, slot, undoRecordId); 222 223 RawTransaction rxact = (RawTransaction)xact; 224 225 if (rxact.handlesPostTerminationWork() && 230 undoPage.isOverflowPage() && undoPage.recordCount() == 0) 231 { 232 ReclaimSpace work = 233 new ReclaimSpace(ReclaimSpace.PAGE, (PageKey)undoPage.getIdentity(), 234 rxact.getDataFactory(), true ); 235 rxact.addPostTerminationWork(work); 236 } 237 } 238 else 239 { 240 undoPage.setDeleteStatus(CLRInstant, slot, true); 241 } 242 243 undoPage.setAuxObject(null); 244 } 245 246 249 250 251 257 public void restoreLoggedRow(Object [] row, LimitObjectInput in) 258 throws StandardException, IOException 259 260 { 261 Page p = null; 262 263 try { 264 p = getContainer().getPage(getPageId().getPageNumber()); 270 271 ((BasePage)p).restoreRecordFromStream(in, row); 272 273 } finally { 274 275 if (p != null) { 276 p.unlatch(); 277 p = null; 278 } 279 } 280 } 281 282 285 286 293 294 public void restoreMe(Transaction xact, BasePage undoPage, LogInstant CLRinstant, LimitObjectInput in) 295 throws StandardException, IOException 296 { 297 if (SanityManager.DEBUG) 298 { 299 int slot = undoPage.findRecordById(recordId,Page.FIRST_SLOT_NUMBER); 300 301 if ( ! getPageId().equals(undoPage.getPageId())) 302 SanityManager.THROWASSERT( 303 "restoreMe cannot restore to a different page. " 304 + "doMe page:" + getPageId() + " undoPage:" + 305 undoPage.getPageId()); 306 if (slot != doMeSlot) 307 SanityManager.THROWASSERT( 308 "restoreMe cannot restore to a different slot. " 309 + "doMe slot:" + doMeSlot + " undoMe slot: " + 310 slot + " recordId:" + recordId); 311 } 312 insertFlag |= Page.INSERT_UNDO_WITH_PURGE; 313 314 undoMe(xact, undoPage, recordId, CLRinstant, in); 316 } 317 318 323 324 public ByteArray getPreparedLog() 325 { 326 return (this.preparedLog); 327 } 328 329 330 public int getNextStartColumn() 331 { 332 return (this.startColumn); 333 } 334 335 341 private void writeOptionalDataToBuffer( 342 RawTransaction t, 343 DynamicByteArrayOutputStream logBuffer, 344 Object [] row, 345 FormatableBitSet validColumns, 346 boolean isLongColumn, 347 int realStartColumn, 348 int realSpaceOnPage, 349 int overflowThreshold) 350 throws StandardException, IOException 351 { 352 353 if (SanityManager.DEBUG) { 354 SanityManager.ASSERT(this.page != null); 355 } 356 357 DynamicByteArrayOutputStream localLogBuffer = null; 358 if (logBuffer != null) { 359 localLogBuffer = (DynamicByteArrayOutputStream) logBuffer; 360 } else { 361 realStartColumn = -1; 362 realSpaceOnPage = -1; 363 localLogBuffer = t.getLogBuffer(); 364 } 365 366 if (isLongColumn) { 367 this.startColumn = this.page.logLongColumn(doMeSlot, recordId, 368 row[0], localLogBuffer); 369 } else { 370 this.startColumn = this.page.logRow(doMeSlot, true, recordId, 371 row, validColumns, localLogBuffer, this.startColumn, insertFlag, 372 realStartColumn, realSpaceOnPage, overflowThreshold); 373 } 374 375 int optionalDataStart = localLogBuffer.getBeginPosition(); 376 int optionalDataLength = localLogBuffer.getPosition() - optionalDataStart; 377 378 this.preparedLog = new ByteArray (localLogBuffer.getByteArray(), optionalDataStart, 379 optionalDataLength); 380 } 381 382 385 public String toString() 386 { 387 if (SanityManager.DEBUG) 388 { 389 return super.toString() + 390 "Insert : " + 391 " Slot=" + doMeSlot + 392 " recordId=" + recordId; 393 } 394 else 395 return null; 396 } 397 398 } 399 | Popular Tags |