Class DbObject

java.lang.Object
ghidra.program.database.DbObject
Direct Known Subclasses:
BookmarkDB, DBAnnotatedObject, EquateDB, FunctionDB, FunctionTagDB, InstructionDB, PropertyMapDB, SourceArchiveDB, SymbolDB

public abstract class DbObject extends Object
Base class for objects stored in the database.

The general contract for database objects is that there should only ever be one instance for a specific database object at any given time. To facilitate this, instances of database objects should be stored in a DbCache and the cache should be queried before creating any new instances.

Database objects have keys that are used by the database record and also serves as the key for cache lookup. They are marked as invalid when a database cache is invalidated and can be revived on a refresh as long as they haven't been deleted.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    protected long
     
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
    DbObject(long key)
    Constructs a new DatabaseObject and adds it to the specified cache.
  • Method Summary

    Modifier and Type
    Method
    Description
    protected void
    Checks if this object has been deleted, in which case any use of the object is not allowed.
    long
    Get the database key for this object.
    boolean
    Returns true if this object has been deleted.
    final boolean
    Return true if the object is known to be valid at this time.
    protected void
    keyChanged(long newKey)
    Method for updating the cache if a object record key changed.
    protected final boolean
    Returns true if the object needs to be refreshed prior to further use.
    protected abstract boolean
    refresh(DBRecord record)
    Tells the object to refresh its state from the database using the specified record if provided.
    protected boolean
    Refreshes the object's state from the database if it is possibly stale.
    protected void
    Marks the object as deleted.
    void
    Invalidate this object.
    protected void
    Marks this object as valid.
    protected boolean
    validate(Lock lock)
    This method provides a cheap (lock free) way to test if an object is valid.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • key

      protected long key
  • Constructor Details

    • DbObject

      protected DbObject(long key)
      Constructs a new DatabaseObject and adds it to the specified cache.
      Parameters:
      key - database key to uniquely identify this object
  • Method Details

    • getKey

      public long getKey()
      Get the database key for this object.
      Returns:
      the database key for this object.
    • setDeleted

      protected void setDeleted()
      Marks the object as deleted.
    • setInvalid

      public void setInvalid()
      Invalidate this object. This does not necessarily mean that this object can never be used again. If the object can refresh itself, it may still be usable.
    • setValid

      protected void setValid()
      Marks this object as valid. Note that this call does no checking on its own should be used very carefully and only when the caller is absolutely sure that the object is valid. Used in a special case for default symbols that have no corresponding record.
    • keyChanged

      protected void keyChanged(long newKey)
      Method for updating the cache if a object record key changed. This is a very unusual situation and should generally be avoided.
      Parameters:
      newKey - the new key for the associated record for this object
    • needsRefreshing

      protected final boolean needsRefreshing()
      Returns true if the object needs to be refreshed prior to further use. An object needs to be refreshed if the cache has been invalidated since the last time the object was checked for validity. There is a special case if the object has been deleted. It certainly doesn't need to be refreshed but clients that have the object already in hand still want to be able to call its getter methods without encountering an error. The assumption is that eventually the client will be kicked so it knows it needs to re-aquire its objects.

      An object that has not been deleted may be marked as stale and in need of a refresh in one of two ways. The cache was invalidated or the object was specifically marked as invalid via its setInvalid() method. A common situation where this can occur is an undo/redo operation against the underlying database. The methods refreshIfNeeded(), checkDeleted(), validate(Lock) and isDeleted(Lock) are methods which will force a re-validation if required.

      This method is final as it is intended to be a "fast" check that doesn't require a lock to see if the object is possibly in need of a refresh. We don't want any subclass to add additional checks that might require a database lock. The idea is that if the cache modification hasn't changed, then we know the object is valid. If the modification count has changed then we may or may not be valid and stronger checks are needed which will require a lock. Subclasses should override refreshIfNeeded(), refresh(DBRecord) to do the more robust validation checking.

      Returns:
      true if this object is invalid and must be re-validated, else false if object state is currently valid which may include a deleted state.
    • isValid

      public final boolean isValid()
      Return true if the object is known to be valid at this time. Note that this is is subtly different from being the inverse of needsRefreshing(), specifically in the case where the object has been deleted. For a deleted object, the isValid() method will return false, but the needsRefreshing() will also return false.
      Returns:
      true if the object is known to be valid at this time.
    • refreshIfNeeded

      protected boolean refreshIfNeeded()
      Refreshes the object's state from the database if it is possibly stale. The check to see if an object is stale is fast, so this generally is a quick call unless an undo or redo has taken place and a true refresh is required. If a refresh is performed, the object may be discovered to be deleted. This method should only be called while holding a ReentrantReadWriteLock.readLock()
      Returns:
      true if the object is valid, else false if deleted
    • checkDeleted

      protected void checkDeleted()
      Checks if this object has been deleted, in which case any use of the object is not allowed. This method should be invoked before any modifications to the object are performed to ensure it still exists and is in a valid state.
      Throws:
      ConcurrentModificationException - if the object has been deleted from the database.
    • validate

      protected boolean validate(Lock lock)
      This method provides a cheap (lock free) way to test if an object is valid. If this object is invalid and not deleted, then the lock will be used to refresh as needed. A deleted object will not be refreshed.
      Parameters:
      lock - the lock that will be used if the object needs to be refreshed.
      Returns:
      true if object is valid or false if deleted
    • isDeleted

      public boolean isDeleted(Lock lock)
      Returns true if this object has been deleted. Note: once an object has been deleted, it will never be "refreshed". For example, if an object is ever deleted and is resurrected via an "undo", you will have get a fresh instance of the object.
      Parameters:
      lock - object cache lock object
      Returns:
      true if this object has been deleted.
    • refresh

      protected abstract boolean refresh(DBRecord record)
      Tells the object to refresh its state from the database using the specified record if provided. The record may be null and the object is generally expected to be able to retrieve its own record from the database as needed. Is is mostly passed as a parameter for efficiency to keep an object from having to look up its record when the client already has the record in hand such as when it is iterating over records.

      This method generally should not be called directly as it provides no recursion protection. Instead, most clients should call refreshIfNeeded() instead which WILL provide recursion protection. If clients must call this method, they either need to provided their own recursion protection or be absolutely certain that recursive calls won't occur.

      Parameters:
      record - valid record associated with object's key (optional, may be null to force record lookup or other refresh technique)
      Returns:
      true if the object was able to refresh itself. Return false if record is null and object was deleted. Objects that extend this class must implement a refresh method. If an object can never refresh itself, then it should always return false.