org.electrocodeogram.cpc.core.api.provider.store
Interface IStoreProvider

All Superinterfaces:
IProvider
All Known Subinterfaces:
IDebuggableStoreProvider, IRemotableStoreProvider

public interface IStoreProvider
extends IProvider

A local storage provider provides persistence for arbitrary clone data objects.
The IStoreProvider interface specifies the API implemented by all local storage providers.

Only one local storage provider may be active at any given point in time.

All methods of this interface are thread safe.

All implementations of this interface also need to implement IRemotableStoreProvider.

Object Identity and Modification

All data returned by this API is detached from it's corresponding background storage. As such any returned objects can be arbitrarily modified without changing the stored versions of the objects and without affecting any other users of the API.
To persist any modifications made to an object the corresponding add/update or remove methods have to be called. Making modifications requires the ownership of an exclusive write lock (see Locking).
Locking
Read access to clone data does not require the manual acquisition of a lock. Each lookup/get method will internally acquire a shared read lock and release it at the end of the method, before returning the result.
All write accesses require exclusive locks on the entire store provider.

A repeatable read is only guaranteed to the lock holder AFTER the lock was granted and only for the duration of the lock. This means that the lock holder should retrieve fresh versions of all clone data objects it needs after the lock was granted.

Read locks are only held for the duration of a method call. Any read only users which require the data to remain unchanged during their runtime have to acquire an exclusive write lock. Even though they do not intend to make any modifications to the data.

The owner of the registered IStoreProviderWriteLockHook, if any, may hold an implicit write lock and might be concurrently modifying local cached versions of the clone data. If a read-only client needs to ensure that it receives the latest version of the clone data it has to acquire an exclusive write lock.
Once a client requests an exclusive write lock, a registered IStoreProviderWriteLockHook will be notified and will be given the opportunity to transfer any dirty clone data back to the store provider before the client's lock request is granted.

Clone Modification and Persistence Events
In general, the store provider is responsible for the generation of CloneModificationEvents for all clone data modifications made by its clients. The events are generated once a client has relinquished its exclusive write lock.
A client may choose to handle the modification event generation itself. This fact can be communicated to the store provider by means of the IStoreProvider.LockMode parameter at lock acquisition time.
The store provider will furthermore generate ClonePersistenceEvents whenever clone data is persisted or purged.
Design Considerations:
Care has been taken in the design of this API interface to allow maximum implementation freedom and flexibility for local storage providers. The internal storage representation is not disclosed and may vary from implementation to implementation. As the internal storage may not allow concurrent writes and may not be object oriented this enforces some API aspects which can feel somewhat cumbersome.
I.e. it is not possible to navigate through the returned object tree (ICloneFile and ICloneGroup do not hold lists of clones) and exclusive, pessimistic locking is enforced.
The normal mode of operation of the CPC Sensor ensures that almost all accesses to the store provider are issued from the main thread. As such lock contention is not a major issue and exclusive locks do are unlikely to introduce performance problems.
It is up to the user of the storage provider API to ensure that deadlocks are avoided.
During normal use a StoreLockingException will never occur. Always having to add a corresponding try/catch block may thus seem somewhat bothersome. However, it is critical that locks are always released, even in the event of other exceptions. Forcing the user of the IStoreProvider API to add a try/catch block around each code block which acquires an exclusive lock does reduce the likely hood of lock "leaking" quite considerably. The user will also receive direct feedback from the IDE during programming if an exclusive lock-requiring operation is used outside of such a try/catch block.

Author:
vw
See Also:
IDebuggableStoreProvider, IRemotableStoreProvider, IStoreProviderWriteLockHook

Nested Class Summary
static class IStoreProvider.LockMode
          Determines the behaviour of the acquireWriteLock(LockMode) exclusive write lock.
static class IStoreProvider.UpdateMode
          Used to provide updateClone(IClone, UpdateMode) with information on the type of modification done to the given clone.
 
Method Summary
 void acquireWriteLock(IStoreProvider.LockMode mode)
          Acquires an exclusive write lock for the entire Store repository.
 boolean acquireWriteLockNonBlocking(IStoreProvider.LockMode mode, long maxWait)
          Similar to acquireWriteLock(LockMode) but does not block in case the lock can not be obtained.
 void addClone(IClone clone)
          Adds a given clone to the data store.
 void addCloneGroup(ICloneGroup group)
          Adds the given ICloneGroup to the data store.
 void addClones(java.util.List<IClone> clones)
          Convenience method, see: addClone(IClone).
 java.util.List<IClone> getClonesByFile(java.lang.String fileUuid)
          Convenience method, equals getClonesByFile(String, int, int) with a startOffset and endOffset of -1.
 java.util.List<IClone> getClonesByFile(java.lang.String fileUuid, int startOffset, int endOffset)
          Retrieves all clones for a given offset range in a given file.
 java.util.List<IClone> getClonesByGroup(java.lang.String groupUuid)
          Retrieves all clones which are part of the given clone group.
 ICloneObjectExtensionLazyMultiStatefulObject getFullCloneObjectExtension(ICloneObject cloneObject, java.lang.Class<? extends ICloneObjectExtension> extensionClass)
          Takes an IClone object and an ICloneObjectExtension interface class and retrieves the extension for the given interface class from the clone.
 ICloneObjectExtensionLazyMultiStatefulObject getFullCloneObjectExtension(ICloneObject cloneObject, ICloneObjectExtensionLazyMultiStatefulObject extension)
          Takes an ICloneObjectExtensionLazyMultiStatefulObject which is only partially loaded and returns a new cloned copy with all sub-elements fully loaded.
 java.lang.String getPersistedCloneFileContent(ICloneFile file)
          Retrieves the persisted content of the given file.
 java.util.List<IClone> getPersistedClonesForFile(java.lang.String fileUuid)
          Retrieves the persisted clone entries for the given file.
 void hintPurgeCache(ICloneFile file)
          All users of the store provider API are encouraged to give certain hints to the store provider implementation which can internally be used to improve performance and to reduce memory usage.
 void hintPurgeCache(ICloneGroup group)
          All users of the store provider API are encouraged to give certain hints to the store provider implementation which can internally be used to improve performance and to reduce memory usage.
 boolean holdingWriteLock()
          Checks whether the current thread is holding the exclusive write lock for the store provider.
 IClone lookupClone(java.lang.String cloneUuid)
          Retrieves an IClone object by clone uuid.
 ICloneFile lookupCloneFile(java.lang.String fileUuid)
          Retrieves an ICloneFile handle by file uuid.
 ICloneFile lookupCloneFileByPath(java.lang.String project, java.lang.String path, boolean createNewUuidIfNeeded, boolean followFileMove)
          Retrieves or creates an ICloneFile handle for the given file.
 ICloneGroup lookupCloneGroup(java.lang.String groupUuid)
          Retrieves an ICloneGroup object by clone group uuid.
 void moveCloneFile(ICloneFile cloneFile, java.lang.String project, java.lang.String path)
          Moves the given clone file to the given project and path.
 void persistData(ICloneFile file)
          Stores the current clone data for the given file in persistent storage.
 void purgeCache()
          Called to indicate that the store provider implementation should purge all it's internal caches.
 void purgeData()
          Called to indicate that the store provider implementation should delete ALL data.
 void purgeData(ICloneFile cloneFile, boolean removeCloneFile)
          Permanently removes all clones which are associated with the given file from persistent storage and from all internal cache structures.
 void releaseWriteLock()
          Releases the exclusive write lock.
 void removeClone(IClone clone)
          Removes the given clone from the data store.
 void removeCloneGroup(ICloneGroup group)
          TODO:/FIXME: clarify semantics of this operation.
 void removeClones(java.util.List<IClone> clones)
          Convenience method, see: removeClone(IClone).
 void revertData(ICloneFile file)
          Reverts the clone data for the given file to the latest version from persistent storage.
 void setWriteLockHook(IStoreProviderWriteLockHook hook)
          Registers a special write lock hook which will receive a callback whenever a user of this provider requests an exclusive write lock.
 void updateClone(IClone clone, IStoreProvider.UpdateMode mode)
          Updates a given clone in the data store.
 void updateCloneGroup(ICloneGroup group)
          Updates the given group in the data store.
 void updateClones(java.util.List<IClone> clones, IStoreProvider.UpdateMode mode)
          Convenience method, see: updateClone(IClone, UpdateMode).
 
Methods inherited from interface org.electrocodeogram.cpc.core.api.provider.IProvider
getProviderName, toString
 

Method Detail

lookupCloneFileByPath

ICloneFile lookupCloneFileByPath(java.lang.String project,
                                 java.lang.String path,
                                 boolean createNewUuidIfNeeded,
                                 boolean followFileMove)
Retrieves or creates an ICloneFile handle for the given file.

The file itself may no longer exist. I.e. because it was recently deleted.
In this case the method returns the old ICloneFile handle, if one exists in the cache or persistent storage. Otherwise it returns NULL.

If a file was recently moved and followFileMove is set to true this method may also return the ICloneFile handle for the new location of the file. In this case the ICloneFile's project and path values might not match the given project and path parameters.
It is up to the implementation to decide whether and how long to store file move information.

Parameters:
project - project the file in question belongs to, never null
path - path to the file in question, relative to project, never null
createNewUuidIfNeeded - in situations where no existing ICloneFile UUID can be found for the file in question, a new ICloneFile instance with a new UUID is generated if this value is true. If this value is false, NULL will be returned instead of generating a new UUID and ICloneFile instance.
Setting this to true should be the default. A false value is useful if you only want to check whether a given file location is of interest to CPC.
followFileMove - whether the store provider should internally check if the file was moved (true) to another location and return the ICloneFile instance for the new file location if this is the case or whether NULL should be returned (false).
An IStoreProvider is not required to support this feature. If tracking of moved files is not supported, this parameter is silently ignored.
Returns:
a CloneFile instance for the given path or NULL on error (i.e. file not found/not readable)

lookupCloneFile

ICloneFile lookupCloneFile(java.lang.String fileUuid)
Retrieves an ICloneFile handle by file uuid.

This method does not check whether the underlying file exists.
If an ICloneFile with the given uuid is found in the cache or in the persistent storage, it is returned. Otherwise NULL is returned.

Parameters:
fileUuid - the file uuid to lookup, never null.
Returns:
an ICloneFile instance for the given uuid or NULL if no file with this uuid was found.

lookupClone

IClone lookupClone(java.lang.String cloneUuid)
Retrieves an IClone object by clone uuid.

Parameters:
cloneUuid - UUID of the clone to lookup, never null.
Returns:
an IClone instance for the given UUID or NULL if no clone with this UUID was found.

lookupCloneGroup

ICloneGroup lookupCloneGroup(java.lang.String groupUuid)
Retrieves an ICloneGroup object by clone group uuid.

Parameters:
groupUuid - UUID of the clone group to lookup, never null.
Returns:
an ICloneGroup instance for the given UUID or NULL if no clone group with this UUID was found.

getClonesByFile

java.util.List<IClone> getClonesByFile(java.lang.String fileUuid)
Convenience method, equals getClonesByFile(String, int, int) with a startOffset and endOffset of -1.

See Also:
getClonesByFile(String, int, int)

getClonesByFile

java.util.List<IClone> getClonesByFile(java.lang.String fileUuid,
                                       int startOffset,
                                       int endOffset)
Retrieves all clones for a given offset range in a given file.
Offsets start at 0.
All clones which collide with the given offset range will be returned. Even if they are only partly included in the range.

Automatically acquires and releases a shared read lock.

Parameters:
fileUuid - UUID of the file to retrieve the clone data for, never null.
startOffset - the offset from which on all clones should be returned, any clone ending on this offset is still included. Must be >= 0.
endOffset - the offset till which all clones should be returned, any clone starting on this offset is still included. Must be >= startOffset or -1 for all clones till end of file.
Returns:
a sorted (by start offset), distinct list of clones for the given interval. Never null.

getClonesByGroup

java.util.List<IClone> getClonesByGroup(java.lang.String groupUuid)
Retrieves all clones which are part of the given clone group.

Automatically acquires and releases a shared read lock.

Parameters:
groupUuid - uuid of the group for which all clones should be returned, never null.
Returns:
unsorted list of group members, never null.

getFullCloneObjectExtension

ICloneObjectExtensionLazyMultiStatefulObject getFullCloneObjectExtension(ICloneObject cloneObject,
                                                                         ICloneObjectExtensionLazyMultiStatefulObject extension)
Takes an ICloneObjectExtensionLazyMultiStatefulObject which is only partially loaded and returns a new cloned copy with all sub-elements fully loaded.

The given clone and extension instances itself are not modified.

Parameters:
cloneObject - the clone object to which this extension is added, never null.
extension - the extension to load all sub-elements for, never null.
Returns:
a new cloned copy of the extension with all sub-elements loaded, never null.

getFullCloneObjectExtension

ICloneObjectExtensionLazyMultiStatefulObject getFullCloneObjectExtension(ICloneObject cloneObject,
                                                                         java.lang.Class<? extends ICloneObjectExtension> extensionClass)
Takes an IClone object and an ICloneObjectExtension interface class and retrieves the extension for the given interface class from the clone.
Convenience method.
It is then passed to the getFullCloneObjectExtension(ICloneObject, ICloneObjectExtensionLazyMultiStatefulObject) method.
If no extension of that interface class type is added, NULL is returned.

Parameters:
cloneObject - the clone object to which this extension is added, never null.
extensionClass - the ICloneObjectExtension interface class for which the currently added extension should be fully loaded, never null.
Returns:
a new cloned copy of the extension with all sub-elements loaded or NULL if no extension for that interface class was present.
See Also:
getFullCloneObjectExtension(ICloneObject, ICloneObjectExtensionLazyMultiStatefulObject)

addClone

void addClone(IClone clone)
              throws StoreLockingException
Adds a given clone to the data store. If the clone already exists, nothing is done.
A ICloneGroup or ICloneFile referenced by the clone instance is not automatically persisted!

If the clone contains an ICloneModificationHistoryExtension any CloneDiff objects it contains will be added to the internal modification history for this clone. The history can be retrieved via a call to getFullCloneObjectExtension(ICloneObject, Class).

If IStoreProvider.LockMode does not disable events, this clone will be included in the CloneModificationEvent.getAddedClones() list of a CloneModificationEvent once the lock is released.

An exclusive write lock is required before this method may be called.

Parameters:
clone - the clone to store, never null
Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.
See Also:
ICloneModificationHistoryExtension, acquireWriteLock(LockMode), IStoreProvider.LockMode

addClones

void addClones(java.util.List<IClone> clones)
               throws StoreLockingException
Convenience method, see: addClone(IClone).

An exclusive write lock is required before this method may be called.

Parameters:
clones - list of clones to add, may be empty, never null.
Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.

addCloneGroup

void addCloneGroup(ICloneGroup group)
                   throws StoreLockingException
Adds the given ICloneGroup to the data store.

An exclusive write lock is required before this method may be called.

Parameters:
group - the group to add, never null.
Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.

updateClone

void updateClone(IClone clone,
                 IStoreProvider.UpdateMode mode)
                 throws StoreLockingException,
                        java.lang.IllegalArgumentException
Updates a given clone in the data store. Throws an exception if the clone doesn't exist.

If the clone contains an ICloneModificationHistoryExtension any CloneDiff objects it contains will be added to the internal modification history for this clone. The history can be retrieved via a call to getFullCloneObjectExtension(ICloneObject, Class).

If IStoreProvider.LockMode does not disable events, this clone will be included in the CloneModificationEvent.getMovedClones() and/or CloneModificationEvent.getModifiedClones() list of a CloneModificationEvent once the lock is released. Depending on the given IStoreProvider.UpdateMode.

An exclusive write lock is required before this method may be called.

Parameters:
clone - the clone to update, never null
mode - specifies how this clone was modified, see: IStoreProvider.UpdateMode, never null.
Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.
java.lang.IllegalArgumentException - thrown if a clone with that uuid doesn't exists in the data store
See Also:
ICloneModificationHistoryExtension, IStoreProvider.LockMode, IStoreProvider.UpdateMode

updateClones

void updateClones(java.util.List<IClone> clones,
                  IStoreProvider.UpdateMode mode)
                  throws StoreLockingException,
                         java.lang.IllegalArgumentException
Convenience method, see: updateClone(IClone, UpdateMode).

An exclusive write lock is required before this method may be called.

Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.
java.lang.IllegalArgumentException - thrown if a clone with that uuid doesn't exists in the data store

updateCloneGroup

void updateCloneGroup(ICloneGroup group)
                      throws StoreLockingException
Updates the given group in the data store.

An exclusive write lock is required before this method may be called.

Parameters:
group - the group to update, never null.
Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.

removeClone

void removeClone(IClone clone)
                 throws StoreLockingException
Removes the given clone from the data store. If it does not exist, the call is ignored.

If IStoreProvider.LockMode does not disable events, this clone will be included in the CloneModificationEvent.getRemovedClones() list of a CloneModificationEvent once the lock is released.

An exclusive write lock is required before this method may be called.

Parameters:
clone - the clone to remove, never null
Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.
See Also:
IStoreProvider.LockMode

removeClones

void removeClones(java.util.List<IClone> clones)
                  throws StoreLockingException
Convenience method, see: removeClone(IClone).

An exclusive write lock is required before this method may be called.

Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.

removeCloneGroup

void removeCloneGroup(ICloneGroup group)
                      throws StoreLockingException
TODO:/FIXME: clarify semantics of this operation. Does it delete the clone members of this group? Does it reset them to no-group?

An exclusive write lock is required before this method may be called.

Parameters:
group -
Throws:
StoreLockingException - thrown if the current thread does not hold an exclusive write lock.

moveCloneFile

void moveCloneFile(ICloneFile cloneFile,
                   java.lang.String project,
                   java.lang.String path)
                   throws StoreLockingException
Moves the given clone file to the given project and path.

This method is used to indicate that:

A clone file's uuid is not affected by a move.
The given ICloneFile instance itself is not updated.

This change is instantly persisted. A call to persistData(ICloneFile) is not needed.

An exclusive write lock is required before this method may be called.

Parameters:
cloneFile - the clone file which should be moved, never null.
project - the new project name for the file, never null.
path - the new project relative path for the file, never null.
Throws:
StoreLockingException - thrown if the caller does not currently hold an exclusive write lock

persistData

void persistData(ICloneFile file)
                 throws StoreLockingException
Stores the current clone data for the given file in persistent storage.
This should be called when a user saves a modified source file.

This method will update the ICloneFile.getModificationDate() and ICloneFile.getSize() values.
The given ICloneFile instance itself is not updated.
If the latest version is required, it should be obtained by calling lookupCloneFile(String).

NOTE: this method may depend on internal caching data which may only be available if all clones for the given file were loaded once via getClonesByFile() before any modifications on the clone data were made.

An exclusive write lock is required before this method may be called.

Parameters:
file - the file in question, never null
Throws:
StoreLockingException - thrown if the caller does not currently hold an exclusive write lock

revertData

void revertData(ICloneFile file)
                throws StoreLockingException
Reverts the clone data for the given file to the latest version from persistent storage.
This is called if a user closes a modified source file without saving it or if he reverts to the saved version.

If IStoreProvider.LockMode does not disable events, a single CloneModificationEvent with CloneModificationEvent.isFullModification() set to true for this file will be generated for this action once the lock is released.

An exclusive write lock is required before this method may be called.

Parameters:
file - the file in question, never null
Throws:
StoreLockingException - thrown if the caller does not currently hold an exclusive write lock
See Also:
IStoreProvider.LockMode

purgeData

void purgeData(ICloneFile cloneFile,
               boolean removeCloneFile)
               throws StoreLockingException
Permanently removes all clones which are associated with the given file from persistent storage and from all internal cache structures. This action is irreversible.

This modification is automatically persisted. No call to persistData(ICloneFile) is required.

If IStoreProvider.LockMode does not disable events, a single CloneModificationEvent with CloneModificationEvent.isFullModification() set to true for this file will be generated for this action once the lock is released.

An exclusive write lock is required before this method may be called.

Parameters:
cloneFile - the file in question, never null
removeCloneFile - if true the clone file handle will also be purged from storage. In that case a future lookupCloneFileByPath(String, String, boolean, boolean) for the project and path of this file would return a new ICloneFile with a new unique uuid and a call to lookupCloneFile(String) with the uuid of this clone file would fail. If this is false, the clone file entry will be retained and only the clone data for the file will be purged.
Throws:
StoreLockingException - thrown if thread is now the owner of the current exclusive write lock
See Also:
IStoreProvider.LockMode

getPersistedCloneFileContent

java.lang.String getPersistedCloneFileContent(ICloneFile file)
                                              throws StoreLockingException
Retrieves the persisted content of the given file. The content represents the state of the file at the time of the last call of persistData(ICloneFile).

An exclusive write lock is required before this method may be called.

Parameters:
file - the clone file to retrieve the content for, never null.
Returns:
the persisted clone content or NULL if no content is available.
Throws:
StoreLockingException - thrown if the caller does not currently hold an exclusive write lock
See Also:
persistData(ICloneFile)

getPersistedClonesForFile

java.util.List<IClone> getPersistedClonesForFile(java.lang.String fileUuid)
Retrieves the persisted clone entries for the given file.
The result represents the clone data state for the file at the time of the last call of persistData(ICloneFile).

Use of this method will not perform any checks for external modifications of the file and will not trigger any reconciliation operations.

This method may be slower than getClonesByFile(String).

Parameters:
fileUuid - UUID of the ICloneFile to retrieve the clone data for, never null.
Returns:
a list of persisted IClone instances for this file, may be empty, never null.

acquireWriteLock

void acquireWriteLock(IStoreProvider.LockMode mode)
                      throws StoreLockingException
Acquires an exclusive write lock for the entire Store repository.

If a user of this store provider has the intention of modifying ANY of the data stored by this provider it is mandatory that an exclusive write lock is obtained BEFORE any data is retrieved from the store provider.

Read locks are automatically acquired and released by the lookup/get methods. Each read lock is only held for the duration of the method call. If any read only user of the storage provider needs to ensure that data is not changed over a specific period (i.e. to guarantee repeatable reads), such a read only user should also acquire an exclusive write lock.

The owner of the registered IStoreProviderWriteLockHook, if any, may be holding an implicit write lock and may be modifying local cached data while no other party is holding a write lock. Such modified data will be transfered back to the store provider when a 3rd party requests a write lock. Acquiring and releasing a write lock is therefore required if a 3rd party needs to ensure that it will obtain the latest version of the data.

This method will block until a lock can be obtained.

Exclusive write locks are reentrant. However, the IStoreProvider.LockMode can't be changed during a re-entry. The lock mode used when initially acquiring the exclusive lock will remain in effect until the lock is released.

See IStoreProvider.LockMode for a description of the possible modes.

NOTE: In situations where a client needs additional locks it is advisable to ensure that either:

Otherwise deadlocks may occur.

Parameters:
mode - configures specific behaviour of this lock, null is equal to LockMode.DEFAULT.
Throws:
StoreLockingException - If maximum number of allowed re-entries is exceeded. Please also refer to the design considerations section in IStoreProvider.
See Also:
releaseWriteLock(), IStoreProvider.LockMode

acquireWriteLockNonBlocking

boolean acquireWriteLockNonBlocking(IStoreProvider.LockMode mode,
                                    long maxWait)
                                    throws StoreLockingException,
                                           java.lang.InterruptedException
Similar to acquireWriteLock(LockMode) but does not block in case the lock can not be obtained.
If this method returns true an exclusive write lock was granted to this thread.
False is returned if another thread already holds an exclusive write lock. In which case, this method has no effect.

NOTE: This method does not honour any fairness conditions. The lock is re-entrant.
NOTE: Please refer to the javadoc for acquireWriteLock(LockMode).

Parameters:
mode - configures specific behaviour of this lock, null is equal to LockMode.DEFAULT.
maxWait - the maximum amount of time in milliseconds that the caller is willing to wait to acquire a lock. Set to 0 to try once and fail instantly if the lock is currently held.
Returns:
true if the lock could be obtained, false if the lock is currently held by another thread.
Throws:
StoreLockingException - If maximum number of allowed re-entries is exceeded. Please also refer to the design considerations section in IStoreProvider.
java.lang.InterruptedException - If the thread is interrupted while waiting for the lock.
See Also:
acquireWriteLock(LockMode)

releaseWriteLock

void releaseWriteLock()
Releases the exclusive write lock.

Unless the generation of CloneModificationEvents was disabled at lock acquisition time by the given IStoreProvider.LockMode, a call to this method may generate one or more CloneModificationEvents.
The exclusive lock is relinquished first, then all interested parties are notified about the modification and then the control is returned to the caller.

This method may only be called by the current holder of the write lock, otherwise an error is logged and the call is ignored.

See Also:
acquireWriteLock(LockMode), IStoreProvider.LockMode

holdingWriteLock

boolean holdingWriteLock()
Checks whether the current thread is holding the exclusive write lock for the store provider.
This method does not block.

Returns:
true if the current thread holds the exclusive write lock for the store provider, false otherwise.

setWriteLockHook

void setWriteLockHook(IStoreProviderWriteLockHook hook)
Registers a special write lock hook which will receive a callback whenever a user of this provider requests an exclusive write lock.
The registered hook will be called on every call to acquireWriteLock(LockMode) directly AFTER the write lock has been granted but before the control is returned to the caller.
Registration of a hook is optional.

IMPORTANT: there can be only one registered write lock hook at any given time. Calling this method multiple times will remove any write look hook registered earlier.

NOTE: registration of a write lock hook is reserved for the CPC Track module.

Rationale:

The majority of all clone data modifications is made by the CPC Track module. A single user action, i.e. a refactoring or source reformat can trigger thousands of clone updates. There are also some user actions inside of an editor which can potentially create a large number of clone data updates.
In theory the existing API would be enough even for these extreme cases. However, due to performance considerations it seems highly prudent to allow a certain amount of clone modification caching inside of the CPC Track module.
The write lock hook is meant as a best effort, extended-write lock for the CPC Track module. Once it has registered its hook it can release any exclusive lock which it might be holding on the clone data and can still continue to internally update and modify its cached clone data. Should any other party wish to modify clone data, the store provider will acquire the exclusive write lock and will then delegate control to the registered hook which in turn will give the CPC Track module the chance to transmit all its clone modifications back to the store provider.
The effect is similar to a situation where the CPC Track module keeps a permanent exclusive lock on the store provider and only temporarily relinquishes it, whenever some other code needs to access the store provider exclusively.

Parameters:
hook - a write lock hook reference, never null.

hintPurgeCache

void hintPurgeCache(ICloneFile file)
All users of the store provider API are encouraged to give certain hints to the store provider implementation which can internally be used to improve performance and to reduce memory usage.

This method should be called if it is unlikely that the clone data for a specific file will be needed again shortly. This is typically the case if the user closes the corresponding file.

This method does not affect the persistence state of clone data in any way and does not lead to data loss. If the clone data for the given clone file is dirty, it will remain in cache.

Parameters:
file - the clone file which is most likely not being accessed again in the near future

hintPurgeCache

void hintPurgeCache(ICloneGroup group)
All users of the store provider API are encouraged to give certain hints to the store provider implementation which can internally be used to improve performance and to reduce memory usage.

This method should be called if it is unlikely that the clone data for a specific clone group will be needed again shortly.

This method does not affect the persistence state of clone data in any way and does not lead to data loss. If the clone data for the given clone group is dirty, it will remain in cache.

Parameters:
group - the clone group which is most likely not being accessed again in the near future

purgeCache

void purgeCache()
Called to indicate that the store provider implementation should purge all it's internal caches.
This method may be called if another CPC part detects a low memory condition.

This method does not affect the persistence state of clone data in any way and does not lead to data loss. If the clone data for the given clone group is dirty, it will remain in cache.

Store provider implementations which do not allocate potentially large in-memory caches, do not need to do anything in this method.

All store provider implementations are encouraged to keep track of available memory on their own and to reduce their memory consumption if the available system resources reach critical levels.


purgeData

void purgeData()
               throws StoreLockingException
Called to indicate that the store provider implementation should delete ALL data.
The result of a call to this method is equivalent to a freshly installed store provider. No data of prior sessions may remain in storage.

This method is typically called in unit tests to ensure a defined starting state.

If IStoreProvider.LockMode does not disable events, a single CloneModificationEvent with CloneModificationEvent.isFullModification() set to true and CloneEvent.getCloneFile() set to NULL will be generated for this action once the lock is released.

An exclusive write lock is required before this method may be called.

Throws:
StoreLockingException - thrown if thread is now the owner of the current exclusive write lock
See Also:
IStoreProvider.LockMode