# 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();
       }
    }