Class PersistenceContext

java.lang.Object
org.nuxeo.ecm.core.storage.sql.PersistenceContext

public class PersistenceContext extends Object
This class holds persistence context information.

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 SimpleFragments, which represent one row, CollectionFragments, 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.

  • Field Details

    • SEL_WARN_THRESHOLD_PROP

      public static final String SEL_WARN_THRESHOLD_PROP
      Property for threshold at which we warn that a Selection may be too big, with stack trace.
      Since:
      7.1
      See Also:
    • SEL_WARN_THRESHOLD_DEFAULT

      public static final String SEL_WARN_THRESHOLD_DEFAULT
      See Also:
    • POS_COMPARATOR

      protected static final SimpleFragment.FieldComparator POS_COMPARATOR
    • VER_CREATED_COMPARATOR

      protected static final SimpleFragment.FieldComparator VER_CREATED_COMPARATOR
    • model

      protected final Model model
    • mapper

      protected final RowMapper mapper
    • session

      protected final SessionImpl session
    • versionAclMode

      protected final BaseSession.VersionAclMode versionAclMode
    • disableReadVersionPermission

      protected final boolean disableReadVersionPermission
    • hierComplex

      protected final SelectionContext hierComplex
    • hierNonComplex

      public final SelectionContext hierNonComplex
    • pristine

      protected final Map<RowId,Fragment> pristine
      The pristine fragments. All held data is identical to what is present in the database and could be refetched if needed.

      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.

    • modified

      protected final Map<RowId,Fragment> modified
      The fragments changed by the session.

      This contains fragment that are Fragment.State.CREATED, Fragment.State.MODIFIED or Fragment.State.DELETED.

    • userChangeIds

      protected final Set<Serializable> userChangeIds
      Document ids modified as "user changes", which means that a change token should be checked.
      Since:
      9.2
    • registry

      protected final io.dropwizard.metrics5.MetricRegistry registry
      Cache statistics
      Since:
      5.7
    • cacheCount

      protected final io.dropwizard.metrics5.Counter cacheCount
    • cacheHitCount

      protected final io.dropwizard.metrics5.Counter cacheHitCount
    • bigSelWarnThreshold

      protected long bigSelWarnThreshold
      Threshold at which we warn that a Selection may be too big, with stack trace.
  • Constructor Details

  • Method Details

    • clearCaches

      protected int clearCaches()
    • clearLocalCaches

      protected int clearLocalCaches()
    • getCacheSize

      protected long getCacheSize()
    • getCacheMapperSize

      protected long getCacheMapperSize()
    • getCachePristineSize

      protected long getCachePristineSize()
    • getCacheSelectionSize

      protected long getCacheSelectionSize()
    • generateNewId

      protected Serializable generateNewId(Serializable id)
      Generates a new id, or used a pre-generated one (import).
    • isIdNew

      protected boolean isIdNew(Serializable id)
    • markUserChange

      protected void markUserChange(Serializable id)
      Marks this document id as belonging to a user change.
      Since:
      9.2
    • getSaveBatch

      protected RowMapper.RowBatch getSaveBatch(List<Fragment> fragmentsToClearDirty)
      Saves all the created, modified and deleted rows into a batch object, for later execution.

      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).

    • updateChangeToken

      protected Map<String,Serializable> updateChangeToken(SimpleFragment hier)
      Updates a change token in the main fragment, and returns the condition to check.
    • findModifiedDocuments

      protected Set<Serializable> findModifiedDocuments()
      Finds the documents having been modified.

      A document is modified if any of its direct fragments (same id) is modified, or if any of its complex property fragments having it as an ancestor is created, modified or deleted.

      Created and deleted documents aren't considered modified.

      Returns:
      the set of modified documents
      Since:
      9.1
    • findDirtyDocuments

      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.
      Parameters:
      dirtyStrings - set of ids, updated by this method
      dirtyBinaries - set of ids, updated by this method
    • markInvalidated

      protected void markInvalidated(VCSInvalidations invalidations)
      Marks locally all the invalidations gathered by a Mapper operation (like a version restore).
    • setFragmentModified

      protected void setFragmentModified(Fragment fragment)
    • setFragmentPristine

      protected void setFragmentPristine(Fragment fragment)
    • sendInvalidationsToOthers

      public void sendInvalidationsToOthers()
      Post-transaction invalidations notification.

      Called post-transaction by session commit/rollback or transactionless save.

    • processReceivedInvalidations

      public void processReceivedInvalidations()
      Applies all invalidations accumulated.

      Called pre-transaction by start or transactionless save;

    • checkInvalidationsConflict

      public void checkInvalidationsConflict()
    • getIfPresent

      protected Fragment getIfPresent(RowId rowId)
      Gets a fragment, if present in the context.

      Called by get(org.nuxeo.ecm.core.storage.sql.RowId, boolean), and by the Mapper to reuse known selection fragments.

      Parameters:
      rowId - the fragment id
      Returns:
      the fragment, or null if not found
    • get

      protected Fragment get(RowId rowId, boolean allowAbsent)
      Gets a fragment.

      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.

      Parameters:
      rowId - the fragment id
      allowAbsent - true to return an absent fragment as an object instead of null
      Returns:
      the fragment, or null if none is found and allowAbsent was false
    • getFromMapper

      protected Fragment getFromMapper(RowId rowId, boolean allowAbsent, boolean cacheOnly)
      Gets a fragment from the context or the mapper cache or the underlying database.
      Parameters:
      rowId - the fragment id
      allowAbsent - true to return an absent fragment as an object instead of null
      cacheOnly - only check memory, not the database
      Returns:
      the fragment, or when allowAbsent is false, a null if not found
    • getFromMapper

      protected List<Fragment> getFromMapper(Collection<RowId> rowIds, boolean allowAbsent, boolean cacheOnly)
      Gets a collection of fragments from the mapper. No order is kept between the inputs and outputs.

      Fragments not found are not returned if allowAbsent is false.

    • getMulti

      public List<Fragment> getMulti(Collection<RowId> rowIds, boolean allowAbsent)
      Gets a list of fragments.

      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.

      Parameters:
      rowIds - the row ids
      allowAbsent - true to return an absent fragment as an object instead of skipping it
      Returns:
      the fragments, in arbitrary order (no nulls)
    • getFragmentsFromFetchedRows

      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.

      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.

      Parameters:
      rowIds - the list of rows or row ids
      allowAbsent - true to return an absent fragment as an object instead of null
      Returns:
      the list of fragments
    • getFragmentFromFetchedRow

      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.

      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.

      Parameters:
      rowId - the row or row id (may be null)
      allowAbsent - true to return an absent fragment as an object instead of null
      Returns:
      the fragment, or null if it was deleted
    • createHierarchyFragment

      public SimpleFragment createHierarchyFragment(Row row)
    • createdProxyFragment

      public void createdProxyFragment(SimpleFragment fragment)
    • removedProxyTarget

      public void removedProxyTarget(SimpleFragment fragment)
    • addedProxyTarget

      public void addedProxyTarget(SimpleFragment fragment)
    • removePropertyNode

      public void removePropertyNode(SimpleFragment hierFragment)
      Removes a property node and its children.

      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).

    • getNodeAndDescendantsInfo

      public List<RowMapper.NodeInfo> getNodeAndDescendantsInfo(SimpleFragment hierFragment)
      Gets descendants infos from a given root node. This includes information about the root node itself.
      Since:
      9.2
    • removeNode

      public void removeNode(SimpleFragment hierFragment, List<RowMapper.NodeInfo> nodeInfos)
      Removes a document node and its children.

      Assumes a full flush was done.

    • removeFragment

      public void removeFragment(Fragment fragment, boolean primary)
      Deletes a fragment from the context. May generate a database DELETE if primary is true, otherwise consider that database removal will be a cascade-induced consequence of another DELETE.
    • recomputeVersionSeries

      public void recomputeVersionSeries(Serializable versionSeriesId)
      Recomputes isLatest / isLatestMajor on all versions.
    • getVersionIds

      public List<Serializable> getVersionIds(Serializable versionSeriesId)
      Gets the version ids for a version series, ordered by creation time.
    • getSeriesProxyIds

      public List<Serializable> getSeriesProxyIds(Serializable versionSeriesId)
    • getTargetProxyIds

      public List<Serializable> getTargetProxyIds(Serializable targetId)
    • getTargetProxies

      public Set<Serializable> getTargetProxies(Set<Serializable> ids)
    • getPath

      public String getPath(SimpleFragment hierFragment)
      Gets the path by recursing up the hierarchy.
    • getPathOrMissingParentId

      public PersistenceContext.PathAndId getPathOrMissingParentId(SimpleFragment hierFragment, boolean fetch)
      Gets the full path, or the closest parent id which we don't have in cache.

      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.

      Parameters:
      fetch - true if we can use the database, false if only caches should be used
    • getContainingDocument

      public Serializable getContainingDocument(Serializable id)
      Finds the id of the enclosing non-complex-property node.
      Parameters:
      id - the id
      Returns:
      the id of the containing document, or null if there is no parent or the parent has been deleted.
    • getHier

      protected SimpleFragment getHier(Serializable id, boolean allowAbsent)
    • isDeleted

      public boolean isDeleted(Serializable id)
      Recursively checks if any of a fragment's parents has been deleted.
    • getNextPos

      public Long getNextPos(Serializable nodeId, boolean complexProp)
      Gets the next pos value for a new child in a folder.
      Parameters:
      nodeId - the folder node id
      complexProp - whether to deal with complex properties or regular children
      Returns:
      the next pos, or null if not orderable
    • orderBefore

      public void orderBefore(Serializable parentId, Serializable sourceId, Serializable destId)
      Order a child before another.
      Parameters:
      parentId - the parent id
      sourceId - the node id to move
      destId - the node id before which to place the source node, if null then move the source to the end
    • getChildHierByName

      public SimpleFragment getChildHierByName(Serializable parentId, String name, boolean complexProp)
    • getChildren

      public List<SimpleFragment> getChildren(Serializable parentId, String name, boolean complexProp)
      Gets hier fragments for children.
    • checkNotUnder

      protected void checkNotUnder(Serializable parentId, Serializable id, String op)
      Checks that we don't move/copy under ourselves.
    • checkFreeName

      protected void checkFreeName(Serializable parentId, String name, boolean complexProp)
      Checks that a name is free. Cannot check concurrent sessions though.
    • move

      public void move(Node source, Serializable parentId, String name)
      Move a child to a new parent with a new name.
      Parameters:
      source - the source
      parentId - the destination parent id
      name - the new name
    • copy

      public Serializable copy(Node source, Serializable parentId, String name, Consumer<Serializable> afterRecordCopy)
      Copy a child to a new parent with a new name.
      Parameters:
      source - the source of the copy
      parentId - the destination parent id
      name - the new name
      afterRecordCopy - a consumer called on ids of nodes that were records before copy
      Returns:
      the id of the copy
    • checkIn

      public Serializable checkIn(Node node, String label, String checkinComment)
      Checks in a node (creates a version).
      Parameters:
      node - the node to check in
      label - the version label
      checkinComment - the version description
      Returns:
      the created version id
    • checkOut

      public void checkOut(Node node)
      Checks out a node.
      Parameters:
      node - the node to check out
    • restoreVersion

      public void restoreVersion(Node node, Node version)
      Restores a node to a given version.

      The restored node is checked in.

      Parameters:
      node - the node
      version - the version to restore on this node