RecordLockInfo.java

/*
** Module   : RecordLockInfo.java
** Abstract : Information about a single record lock held by the lock manager
**
** Copyright (c) 2009-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- -----------------------------------Description-----------------------------------
** 001 ECF 20090623   @42788 Created initial version. Information about a
**                           single record lock held by the P2J lock manager.
** 002 ECF 20090801   @43503 Added physical database name.
** 003 CA  20091119   @44435 Record lockers are identified by session tokens
**                           instead of session IDs, to provide the subject 
**                           name too.
** 004 SVL 20091126   @44446 Make this class extend RecordInfo.
** 005 SBI 20170225          Changed to be a simple DTO that can used by GWT RPC,
**                           moved record type out to its own module.
** 006 CA  20180605          Added program traces in the session and record locks views.
** 007 OM  20241128          Multi-tenant runtime support: selected the proper persistence context, eventually
**                           based on [sharedDb] parameter.
*/

/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/


package com.goldencode.p2j.admin;

import java.io.Serializable;
import java.util.Arrays;

import com.goldencode.p2j.security.SessionToken;


/**
 * Information about a single record lock held by the P2J lock manager.
 * Represents a transient snapshot of lock information at the moment this
 * information is requested.
 * <p>
 * The information is read-only, once the object is constructed.  It includes
 * the type of lock, the time the lock was acquired, the table name and
 * primary key of the lock, and an array of session IDs of those contexts
 * which currently hold the lock (must be at least one).
 */
public final class RecordLockInfo
extends RecordInfo
implements Serializable
{
   /** Lock type */
   private RecordLockType type = RecordLockType.NONE;
   
   /** Timestamp (time of epoch) at which lock was acquired */
   private long timeAcquired;
   
   /** Session tokens of one or more contexts which hold the lock */
   private SessionToken[] lockers;
   
   /** The program traces associated with each FWD session. */
   private StacktraceInfo[][] stacktraces;
   
   /** The Java stacktrace associated with each FWD session. */
   private String[][] javaStacktraces;
   
   /** Default constructor */
   public RecordLockInfo()
   {
      super();
   }

   /**
    * Constructor.
    * 
    * @param   type
    *          Lock type.
    * @param   timeAcquired
    *          Timestamp (time of epoch) at which lock was acquired.
    * @param   databaseName
    *          Physical database name.
    * @param   tableName
    *          Name of table.
    * @param   recordID
    *          Primary key ID of locked record.
    * @param   lockers
    *          Session tokens of one or more contexts which hold the lock.
    * @param   sharedDb
    *          {@code true} if the buffers are shared (not tenant private).
    */
   public RecordLockInfo(RecordLockType type,
                         long timeAcquired,
                         String databaseName,
                         String tableName,
                         long recordID,
                         SessionToken[] lockers,
                         boolean sharedDb)
   {
      super(databaseName, tableName, recordID, sharedDb);
      this.type = type;
      this.timeAcquired = timeAcquired;
      this.lockers = lockers;
   }
   
   /**
    * Get the program stacktraces for this record lock.
    * 
    * @return    See above.
    */
   public StacktraceInfo[][] getStacktraces()
   {
      return stacktraces;
   }
   
   /**
    * Set the program stacktraces for this record lock.
    * 
    * @param    stacktraces
    *           The program traces.
    */
   public void setStacktraces(StacktraceInfo[][] stacktraces)
   {
      this.stacktraces = stacktraces;
   }
   
   /**
    * Get the Java stacktraces for this record lock.
    * 
    * @return    See above.
    */
   public String[][] getJavaStacktraces()
   {
      return javaStacktraces;
   }
   
   /**
    * Set the Java stacktraces for this record lock.
    * 
    * @param    stacktraces
    *           The Java stacktraces.
    */
   public void setJavaStacktraces(String[][] stacktraces)
   {
      this.javaStacktraces = stacktraces;
   }
   
   /**
    * Retrieve the lock type.
    * 
    * @return  Lock type.
    */
   public RecordLockType getType()
   {
      return type;
   }
   
   /**
    * Retrieve the timestamp (time of epoch) at which the lock was acquired.
    * 
    * @return  Acquisition timestamp.
    */
   public long getTimeAcquired()
   {
      return timeAcquired;
   }
   
   /**
    * Retrieve an array of session tokens which hold this lock.  This method
    * actually returns a copy to ensure the stored value is immutable.
    * 
    * @return  Copy of lockers' session tokens.  Must not be <code>null</code>
    *          and must contain at least one entry (possibly more for lock
    *          type <code>SHARE</code>.
    */
   public SessionToken[] getLockers()
   {
      return Arrays.copyOf(lockers, lockers.length);
   }

   /**
    * Sets the lock type.
    *
    * @param    type
    *           The new lock type
    */
   public void setType(RecordLockType type)
   {
      this.type = type;
   }

   /**
    * Sets the timestamp (time of epoch) at which lock was acquired.
    *
    * @param    timeAcquired
    *           The new timestamp (time of epoch) at which lock was acquired
    */
   public void setTimeAcquired(long timeAcquired)
   {
      this.timeAcquired = timeAcquired;
   }

   /**
    * Sets the session tokens of one or more contexts which hold the lock.
    *
    * @param    lockers
    *           The new session tokens of one or more contexts which hold the lock
    */
   public void setLockers(SessionToken[] lockers)
   {
      this.lockers = lockers;
   }
   
   /**
    * Gets the lockers presentation.
    *
    * @return   The lockers presentation
    */
   public String getLockersPresentation()
   {
      StringBuilder builder = new StringBuilder();
      
      SessionToken[] tokens = getLockers();
      
      int last = tokens.length - 1;
      
      for(int i = 0; i < last; i++)
      {
         builder.append(tokens[i]).append(", ");
      }
      
      builder.append(tokens[last]);
      
      return builder.toString();
   }
}