public class PersistenceContext extends Object
All non-saved modified data is referenced here. At save time, the data is sent to the database by the Mapper
.
The database will at some time later be committed by the external transaction manager in effect.
Internally a fragment can be in at most one of the "pristine" or "modified" map. After a save() all the fragments are pristine, and may be partially invalidated after commit by other local or clustered contexts that committed too.
Depending on the table, the context may hold SimpleFragment
s, which represent one row,
CollectionFragment
s, which represent several rows.
This class is not thread-safe, it should be tied to a single session and the session itself should not be used concurrently.
Modifier and Type | Class and Description |
---|---|
static class |
PersistenceContext.PathAndId |
Modifier and Type | Field and Description |
---|---|
protected long |
bigSelWarnThreshold
Threshold at which we warn that a Selection may be too big, with stack trace.
|
protected com.codahale.metrics.Counter |
cacheCount |
protected com.codahale.metrics.Counter |
cacheHitCount |
protected SelectionContext |
hierComplex |
SelectionContext |
hierNonComplex |
protected static org.apache.commons.logging.Log |
log |
protected RowMapper |
mapper |
protected Model |
model |
protected Map<RowId,Fragment> |
modified
The fragments changed by the session.
|
protected static SimpleFragment.FieldComparator |
POS_COMPARATOR |
protected Map<RowId,Fragment> |
pristine
The pristine fragments.
|
protected com.codahale.metrics.MetricRegistry |
registry
Cache statistics
|
static String |
SEL_WARN_THRESHOLD_DEFAULT |
static String |
SEL_WARN_THRESHOLD_PROP
Property for threshold at which we warn that a Selection may be too big, with stack trace.
|
protected SessionImpl |
session |
protected static SimpleFragment.FieldComparator |
VER_CREATED_COMPARATOR |
Constructor and Description |
---|
PersistenceContext(Model model,
RowMapper mapper,
SessionImpl session) |
Modifier and Type | Method and Description |
---|---|
void |
addedProxyTarget(SimpleFragment fragment) |
protected void |
checkFreeName(Serializable parentId,
String name,
boolean complexProp)
Checks that a name is free.
|
Serializable |
checkIn(Node node,
String label,
String checkinComment)
Checks in a node (creates a version).
|
void |
checkInvalidationsConflict() |
protected void |
checkNotUnder(Serializable parentId,
Serializable id,
String op)
Checks that we don't move/copy under ourselves.
|
void |
checkOut(Node node)
Checks out a node.
|
protected int |
clearCaches() |
protected int |
clearLocalCaches() |
Serializable |
copy(Node source,
Serializable parentId,
String name)
Copy a child to a new parent with a new name.
|
void |
createdProxyFragment(SimpleFragment fragment) |
SimpleFragment |
createHierarchyFragment(Row row) |
protected void |
findDirtyDocuments(Set<Serializable> dirtyStrings,
Set<Serializable> dirtyBinaries)
Finds the documents having dirty text or dirty binaries that have to be reindexed as fulltext.
|
protected Serializable |
generateNewId(Serializable id)
Generates a new id, or used a pre-generated one (import).
|
protected Fragment |
get(RowId rowId,
boolean allowAbsent)
Gets a fragment.
|
protected long |
getCacheMapperSize() |
protected long |
getCachePristineSize() |
protected long |
getCacheSelectionSize() |
protected long |
getCacheSize() |
SimpleFragment |
getChildHierByName(Serializable parentId,
String name,
boolean complexProp) |
List<SimpleFragment> |
getChildren(Serializable parentId,
String name,
boolean complexProp)
Gets hier fragments for children.
|
Serializable |
getContainingDocument(Serializable id)
Finds the id of the enclosing non-complex-property node.
|
protected Fragment |
getFragmentFromFetchedRow(RowId rowId,
boolean allowAbsent)
Turns the given row (just fetched from the mapper) into a fragment and record it in the context.
|
protected List<Fragment> |
getFragmentsFromFetchedRows(List<? extends RowId> rowIds,
boolean allowAbsent)
Turns the given rows (just fetched from the mapper) into fragments and record them in the context.
|
protected List<Fragment> |
getFromMapper(Collection<RowId> rowIds,
boolean allowAbsent,
boolean cacheOnly)
Gets a collection of fragments from the mapper.
|
protected Fragment |
getFromMapper(RowId rowId,
boolean allowAbsent,
boolean cacheOnly)
Gets a fragment from the context or the mapper cache or the underlying database.
|
protected SimpleFragment |
getHier(Serializable id,
boolean allowAbsent) |
protected Fragment |
getIfPresent(RowId rowId)
Gets a fragment, if present in the context.
|
List<Fragment> |
getMulti(Collection<RowId> rowIds,
boolean allowAbsent)
Gets a list of fragments.
|
Long |
getNextPos(Serializable nodeId,
boolean complexProp)
Gets the next pos value for a new child in a folder.
|
String |
getPath(SimpleFragment hierFragment)
Gets the path by recursing up the hierarchy.
|
PersistenceContext.PathAndId |
getPathOrMissingParentId(SimpleFragment hierFragment,
boolean fetch)
Gets the full path, or the closest parent id which we don't have in cache.
|
protected RowMapper.RowBatch |
getSaveBatch(List<Fragment> fragmentsToClearDirty)
Saves all the created, modified and deleted rows into a batch object, for later execution.
|
List<Serializable> |
getSeriesProxyIds(Serializable versionSeriesId) |
List<Serializable> |
getTargetProxyIds(Serializable targetId) |
List<Serializable> |
getVersionIds(Serializable versionSeriesId)
Gets the version ids for a version series, ordered by creation time.
|
boolean |
isDeleted(Serializable id)
Recursively checks if any of a fragment's parents has been deleted.
|
protected boolean |
isIdNew(Serializable id) |
protected void |
markInvalidated(Invalidations invalidations)
Marks locally all the invalidations gathered by a
Mapper operation (like a version restore). |
void |
move(Node source,
Serializable parentId,
String name)
Move a child to a new parent with a new name.
|
void |
orderBefore(Serializable parentId,
Serializable sourceId,
Serializable destId)
Order a child before another.
|
void |
processReceivedInvalidations()
Applies all invalidations accumulated.
|
void |
recomputeVersionSeries(Serializable versionSeriesId)
Recomputes isLatest / isLatestMajor on all versions.
|
void |
removedProxyTarget(SimpleFragment fragment) |
void |
removeFragment(Fragment fragment,
boolean primary)
Deletes a fragment from the context.
|
void |
removeNode(SimpleFragment hierFragment)
Removes a document node and its children.
|
void |
removePropertyNode(SimpleFragment hierFragment)
Removes a property node and its children.
|
void |
restoreVersion(Node node,
Node version)
Restores a node to a given version.
|
void |
sendInvalidationsToOthers()
Post-transaction invalidations notification.
|
protected void |
setFragmentModified(Fragment fragment) |
protected void |
setFragmentPristine(Fragment fragment) |
protected static final org.apache.commons.logging.Log log
public static final String SEL_WARN_THRESHOLD_PROP
public static final String SEL_WARN_THRESHOLD_DEFAULT
protected static final SimpleFragment.FieldComparator POS_COMPARATOR
protected static final SimpleFragment.FieldComparator VER_CREATED_COMPARATOR
protected final SessionImpl session
protected final SelectionContext hierComplex
public final SelectionContext hierNonComplex
protected final Map<RowId,Fragment> pristine
This contains fragment that are Fragment.State.PRISTINE
or Fragment.State.ABSENT
, or in some cases
Fragment.State.INVALIDATED_MODIFIED
or Fragment.State.INVALIDATED_DELETED
.
Pristine fragments must be kept here when referenced by the application, because the application must get the same fragment object if asking for it twice, even in two successive transactions.
This is memory-sensitive, a fragment can always be refetched if nobody uses it and the GC collects it. Use a weak reference for the values, we don't hold them longer than they need to be referenced, as the underlying mapper also has its own cache.
protected final Map<RowId,Fragment> modified
This contains fragment that are Fragment.State.CREATED
, Fragment.State.MODIFIED
or Fragment.State.DELETED
.
protected final com.codahale.metrics.MetricRegistry registry
protected final com.codahale.metrics.Counter cacheCount
protected final com.codahale.metrics.Counter cacheHitCount
protected long bigSelWarnThreshold
public PersistenceContext(Model model, RowMapper mapper, SessionImpl session)
protected int clearCaches()
protected int clearLocalCaches()
protected long getCacheSize()
protected long getCacheMapperSize()
protected long getCachePristineSize()
protected long getCacheSelectionSize()
protected Serializable generateNewId(Serializable id)
protected boolean isIdNew(Serializable id)
protected RowMapper.RowBatch getSaveBatch(List<Fragment> fragmentsToClearDirty)
Also updates the passed fragmentsToClearDirty list with dirty modified fragments, for later call of clearDirty (it's important to call it later and not now because for delta values we need the delta during batch write, and they are cleared by clearDirty).
protected void findDirtyDocuments(Set<Serializable> dirtyStrings, Set<Serializable> dirtyBinaries)
dirtyStrings
- set of ids, updated by this methoddirtyBinaries
- set of ids, updated by this methodprotected void markInvalidated(Invalidations invalidations)
Mapper
operation (like a version restore).protected void setFragmentModified(Fragment fragment)
protected void setFragmentPristine(Fragment fragment)
public void sendInvalidationsToOthers()
Called post-transaction by session commit/rollback or transactionless save.
public void processReceivedInvalidations()
Called pre-transaction by start or transactionless save;
public void checkInvalidationsConflict()
protected Fragment getIfPresent(RowId rowId)
Called by get(org.nuxeo.ecm.core.storage.sql.RowId, boolean)
, and by the Mapper
to reuse known selection fragments.
rowId
- the fragment idnull
if not foundprotected Fragment get(RowId rowId, boolean allowAbsent)
If it's not in the context, fetch it from the mapper. If it's not in the database, returns null
or an
absent fragment.
Deleted fragments may be returned.
rowId
- the fragment idallowAbsent
- true
to return an absent fragment as an object instead of null
null
if none is found and was false
protected Fragment getFromMapper(RowId rowId, boolean allowAbsent, boolean cacheOnly)
rowId
- the fragment idallowAbsent
- true
to return an absent fragment as an object instead of null
cacheOnly
- only check memory, not the databaseallowAbsent
is false
, a null
if not foundprotected List<Fragment> getFromMapper(Collection<RowId> rowIds, boolean allowAbsent, boolean cacheOnly)
Fragments not found are not returned if allowAbsent
is false
.
public List<Fragment> getMulti(Collection<RowId> rowIds, boolean allowAbsent)
If a fragment is not in the context, fetch it from the mapper. If it's not in the database, use an absent fragment or skip it.
Deleted fragments are skipped.
id
- the fragment idallowAbsent
- true
to return an absent fragment as an object instead of skipping itnull
s)protected List<Fragment> getFragmentsFromFetchedRows(List<? extends RowId> rowIds, boolean allowAbsent)
For each row, if the context already contains a fragment with the given id, it is returned instead of building a new one.
Deleted fragments are skipped.
If a simple RowId
is passed, it means that an absent row was found by the mapper. An absent fragment will
be returned, unless allowAbsent
is false
in which case it will be skipped.
rowIds
- the list of rows or row idsallowAbsent
- true
to return an absent fragment as an object instead of null
protected Fragment getFragmentFromFetchedRow(RowId rowId, boolean allowAbsent)
If the context already contains a fragment with the given id, it is returned instead of building a new one.
If the fragment was deleted, null
is returned.
If a simple RowId
is passed, it means that an absent row was found by the mapper. An absent fragment will
be returned, unless allowAbsent
is false
in which case null
will be returned.
rowId
- the row or row id (may be null
)allowAbsent
- true
to return an absent fragment as an object instead of null
null
if it was deletedpublic SimpleFragment createHierarchyFragment(Row row)
public void createdProxyFragment(SimpleFragment fragment)
public void removedProxyTarget(SimpleFragment fragment)
public void addedProxyTarget(SimpleFragment fragment)
public void removePropertyNode(SimpleFragment hierFragment)
There's less work to do than when we have to remove a generic document node (less selections, and we can assume the depth is small so recurse).
public void removeNode(SimpleFragment hierFragment)
Assumes a full flush was done.
public void removeFragment(Fragment fragment, boolean primary)
true
, otherwise
consider that database removal will be a cascade-induced consequence of another DELETE.public void recomputeVersionSeries(Serializable versionSeriesId)
public List<Serializable> getVersionIds(Serializable versionSeriesId)
public List<Serializable> getSeriesProxyIds(Serializable versionSeriesId)
public List<Serializable> getTargetProxyIds(Serializable targetId)
public String getPath(SimpleFragment hierFragment)
public PersistenceContext.PathAndId getPathOrMissingParentId(SimpleFragment hierFragment, boolean fetch)
If fetch
is true
, returns the full path.
If fetch
is false
, does not touch the mapper, only the context, therefore may return a missing
parent id instead of the path.
fetch
- true
if we can use the database, false
if only caches should be usedpublic Serializable getContainingDocument(Serializable id)
id
- the idnull
if there is no parent or the parent has been deleted.protected SimpleFragment getHier(Serializable id, boolean allowAbsent)
public boolean isDeleted(Serializable id)
public Long getNextPos(Serializable nodeId, boolean complexProp)
nodeId
- the folder node idcomplexProp
- whether to deal with complex properties or regular childrennull
if not orderablepublic void orderBefore(Serializable parentId, Serializable sourceId, Serializable destId)
parentId
- the parent idsourceId
- the node id to movedestId
- the node id before which to place the source node, if null
then move the source to the endpublic SimpleFragment getChildHierByName(Serializable parentId, String name, boolean complexProp)
public List<SimpleFragment> getChildren(Serializable parentId, String name, boolean complexProp)
protected void checkNotUnder(Serializable parentId, Serializable id, String op)
protected void checkFreeName(Serializable parentId, String name, boolean complexProp)
public void move(Node source, Serializable parentId, String name)
source
- the sourceparentId
- the destination parent idname
- the new namepublic Serializable copy(Node source, Serializable parentId, String name)
source
- the source of the copyparentId
- the destination parent idname
- the new namepublic Serializable checkIn(Node node, String label, String checkinComment)
node
- the node to check inlabel
- the version labelcheckinComment
- the version descriptionpublic void checkOut(Node node)
node
- the node to check outpublic void restoreVersion(Node node, Node version)
The restored node is checked in.
node
- the nodeversion
- the version to restore on this nodeCopyright © 2016 Nuxeo SA. All rights reserved.