rollback_wip_ecf_20200609.patch
src/com/goldencode/p2j/persist/RecordBuffer.java 2020-06-09 11:42:38 +0000 | ||
---|---|---|
10086 | 10086 |
* validation failure and is recoverable. |
10087 | 10087 |
*/ |
10088 | 10088 |
private Object[] validateMaybeFlush(Session session, |
10089 |
BaseRecord dmo,
|
|
10089 |
Record dmo, |
|
10090 | 10090 |
String bufferName, |
10091 | 10091 |
UniqueTracker uniqueTracker, |
10092 | 10092 |
UniqueTracker.Context uniqueTrackerCtx, |
... | ... | |
10095 | 10095 |
throws PersistenceException, |
10096 | 10096 |
ValidationException |
10097 | 10097 |
{ |
10098 |
if (currentRecord == null)
|
|
10098 |
if (dmo == null)
|
|
10099 | 10099 |
{ |
10100 | 10100 |
return null; |
10101 | 10101 |
} |
10102 | 10102 |
|
10103 |
boolean insert = currentRecord.checkState(DmoState.NEW);
|
|
10103 |
boolean insert = dmo.checkState(DmoState.NEW);
|
|
10104 | 10104 |
|
10105 | 10105 |
Validation validation = new Validation(session, |
10106 | 10106 |
dmo, |
... | ... | |
10111 | 10111 |
force); |
10112 | 10112 |
Object[] diffs = validation.validateMaybeFlush(); |
10113 | 10113 |
|
10114 |
if (validation.wasFlushed()) |
|
10114 |
if (dmo == currentRecord && validation.wasFlushed())
|
|
10115 | 10115 |
{ |
10116 | 10116 |
if (insert) |
10117 | 10117 |
{ |
10118 | 10118 |
markPersisted(); |
10119 | 10119 |
} |
10120 | 10120 |
|
10121 |
reportChange(currentRecord, insert, false);
|
|
10121 |
reportChange(dmo, insert, false);
|
|
10122 | 10122 |
} |
10123 | 10123 |
|
10124 | 10124 |
return diffs; |
... | ... | |
10883 | 10883 |
* if there is no record loaded into the buffer and the error |
10884 | 10884 |
* manager is not in silent mode. |
10885 | 10885 |
*/ |
10886 |
private void load(Record target, |
|
10887 |
LockType lockType, |
|
10888 |
boolean undo, |
|
10889 |
boolean allowWriteTrigger) |
|
10886 |
private void load(Record target, LockType lockType, boolean undo, boolean allowWriteTrigger) |
|
10890 | 10887 |
{ |
10891 | 10888 |
if (target == currentRecord && undo && isTemporary()) |
10892 | 10889 |
{ |
... | ... | |
11507 | 11504 |
* This class also ensures uncommitted updates to permanent tables are |
11508 | 11505 |
* shared across contexts via the dirty share manager. |
11509 | 11506 |
* |
11510 |
* @deprecated |
|
11507 |
* @deprecated This class must be removed entirely once the dirty share manager |
|
11508 |
* is re-integrated. |
|
11511 | 11509 |
*/ |
11512 | 11510 |
protected class ValidationHelper |
11513 | 11511 |
{ |
... | ... | |
13306 | 13304 |
|
13307 | 13305 |
LightweightUndoable copy = (LightweightUndoable) from; |
13308 | 13306 |
|
13309 |
// Reset current record and snapshot to what they were before backup. |
|
13307 |
// reset current record, snapshot, and pinned lock type to what they were before backup |
|
13308 |
/* |
|
13310 | 13309 |
Record active = copy.activeRecord; |
13311 | 13310 |
if (active != null) |
13312 | 13311 |
{ |
... | ... | |
13331 | 13330 |
setCurrentRecord(null, true, false, false, false); |
13332 | 13331 |
} |
13333 | 13332 |
} |
13333 |
*/ |
|
13334 |
setCurrentRecord(copy.activeRecord, true, false, false, false); |
|
13334 | 13335 |
snapshot = copy.activeSnapshot; |
13336 |
LockType lockType = copy.pinnedLockType; |
|
13337 |
Long id = copy.activeRecord.primaryKey(); |
|
13338 |
|
|
13339 |
LockType pinned = getPinnedLockType(id); |
|
13340 |
if (lockType == null) |
|
13341 |
{ |
|
13342 |
lockType = pinned; |
|
13343 |
} |
|
13344 |
if (!lockType.equals(pinned)) |
|
13345 |
{ |
|
13346 |
setPinnedLockType(id, lockType); |
|
13347 |
} |
|
13335 | 13348 |
} |
13336 | 13349 |
|
13337 | 13350 |
/** |
src/com/goldencode/p2j/persist/orm/BaseRecord.java 2020-06-08 22:22:56 +0000 | ||
---|---|---|
391 | 391 |
} |
392 | 392 |
|
393 | 393 |
/** |
394 |
* Does the table to which this record belongs have any unique index defined? |
|
395 |
* |
|
396 |
* @return {@code true} if at least on unique index exists, else {@code false}. |
|
397 |
*/ |
|
398 |
public boolean hasUniqueConstraints() |
|
399 |
{ |
|
400 |
return _recordMeta().uniqueIndices.length > 0; |
|
401 |
} |
|
402 |
|
|
403 |
/** |
|
394 | 404 |
* Indicate whether all index components for any index on this record are dirty (i.e., have been touched, |
395 | 405 |
* not necessarily changed.. |
396 | 406 |
* |
... | ... | |
683 | 693 |
* sub-transactions. |
684 | 694 |
*/ |
685 | 695 |
void rollback(Session session, int txLevel) |
696 |
throws PersistenceException |
|
686 | 697 |
{ |
687 | 698 |
if (changeSet == null) |
688 | 699 |
{ |
src/com/goldencode/p2j/persist/orm/ChangeSet.java 2020-06-09 11:36:18 +0000 | ||
---|---|---|
66 | 66 | |
67 | 67 |
import java.util.*; |
68 | 68 |
import java.util.logging.*; |
69 |
import com.goldencode.p2j.persist.*; |
|
69 | 70 |
import com.goldencode.p2j.util.*; |
70 | 71 | |
71 | 72 |
/** |
... | ... | |
216 | 217 |
* Record to be rolled back. |
217 | 218 |
*/ |
218 | 219 |
void rollback(Session session, int txLevel, BaseRecord dmo) |
220 |
throws PersistenceException |
|
219 | 221 |
{ |
220 | 222 |
if (changes == null || txLevel < outer || txLevel > inner) |
221 | 223 |
{ |
... | ... | |
310 | 312 |
// TODO: is this needed? |
311 | 313 |
} |
312 | 314 |
|
313 |
if ((next & Event.INSERT) == Event.INSERT) |
|
315 |
if ((next & Event.CREATE) == Event.CREATE) |
|
316 |
{ |
|
317 |
dmo.updateState(DmoState.NEW, false); |
|
318 |
} |
|
319 |
|
|
320 |
boolean insert = (next & Event.INSERT) == Event.INSERT; |
|
321 |
boolean delete = (next & Event.DELETE) == Event.DELETE; |
|
322 |
|
|
323 |
if (insert) |
|
314 | 324 |
{ |
315 | 325 |
dmo.updateState(DmoState.NEW, true); |
326 |
|
|
327 |
if (!delete) |
|
328 |
{ |
|
329 |
// if not deleted in the same block, evict record from session cache |
|
330 |
session.evict(dmo); |
|
331 |
} |
|
316 | 332 |
} |
317 | 333 |
|
318 |
// handle create and/or delete |
|
319 |
if ((next & (Event.CREATE | Event.DELETE)) != Event.NONE) |
|
334 |
if (delete) |
|
320 | 335 |
{ |
321 |
// mark record stale to allow higher level recovery code to restore record; this essentially |
|
322 |
// ignores any data-level rollback done above, since the database's state will be used instead |
|
323 |
|
|
324 |
// FOR CREATE: whether or not the record was also inserted at this block, the database will |
|
325 |
// have rolled back its existence at this or an inner block, so we should end up with a null |
|
326 |
// record after sync'ing with the database |
|
327 |
|
|
328 |
// FOR DELETE: since an application delete and database delete will happen within the same |
|
329 |
// block scope, the state of the record in the database should be what we want in the DMO at |
|
330 |
// the time of rollback |
|
331 |
|
|
332 |
dmo.updateState(DmoState.STALE, true); |
|
336 |
dmo.updateState(DmoState.DELETED, false); |
|
337 |
|
|
338 |
if (!insert) |
|
339 |
{ |
|
340 |
// if not inserted in the same block, add record to session cache |
|
341 |
// TODO: optimization: if insert is rolled back in an outer block, this effort is wasted |
|
342 |
session.associate(dmo); |
|
343 |
} |
|
333 | 344 |
} |
334 | 345 |
|
335 | 346 |
// events have been rolled back; clear the flags |
src/com/goldencode/p2j/persist/orm/SavepointManager.java 2020-06-08 22:22:53 +0000 | ||
---|---|---|
634 | 634 |
* Roll back changes to undoable records and activate redoable actions for NO-UNDO records. |
635 | 635 |
*/ |
636 | 636 |
void rollback(Session session) |
637 |
throws PersistenceException |
|
637 | 638 |
{ |
638 | 639 |
for (BaseRecord dmo : changed) |
639 | 640 |
{ |