<?xml version="1.0" encoding="UTF-8"?>
<!-- This document was created with Syntext Serna Free. -->
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="JCR.LockManagerConfiguration">
  <title>LockManager configuration</title>

  <para>What LockManager does?</para>

  <para>In general, LockManager stores Lock objects, so it can give a Lock
  object or can release it.</para>

  <para>Also, LockManager is responsible for removing Locks that live too
  long. This parameter may be configured with "time-out" property.</para>

  <para>JCR provides one basic implementations of LockManager:</para>

  <itemizedlist>
    <listitem>
      <para><classname>oorg.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl</classname></para>
    </listitem>
  </itemizedlist>

  <section id="JCR.LockManagerConfiguration.CacheableLockManagerImpl">
    <title>CacheableLockManagerImpl</title>

    <para>ISPNCacheableLockManagerImpl stores Lock objects in Infinispan, so
    Locks are replicable and affect on cluster, not only a single node. Also,
    Infinispan has a JdbcStringBasedCacheStore, so Locks will be stored to the
    database.</para>

    <para>You can enable LockManager by adding lock-manager-configuration to
    workspace-configuration.</para>

    <para>For example:</para>

    <programlisting language="xml">&lt;workspace name="ws"&gt;
   ...
   &lt;lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl"&gt;
      &lt;properties&gt;
         &lt;property name="time-out" value="15m" /&gt;
         ...
      &lt;/properties&gt;
   &lt;/lock-manager&gt;               
   ...
&lt;/workspace&gt;</programlisting>

    <para>Wher <emphasis>time-out</emphasis> parameter represents interval to
    remove Expired Locks. LockRemover separates threads, that periodically ask
    LockManager to remove Locks that live so long.</para>

    <section id="JCR.LockManagerConfiguration.CacheableLockManagerImpl.Configuration">
      <title>Configuration</title>

      <para>The configuration uses the template Infinispan configuration for
      all LockManagers.</para>

      <para><citetitle>Lock template configuration</citetitle></para>

      <para><filename>test-infinispan-lock.xml</filename></para>

      <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;infinispan
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="urn:infinispan:config:5.2 http://www.infinispan.org/schemas/infinispan-config-5.2.xsd"
      xmlns="urn:infinispan:config:5.2"&gt;

    &lt;global&gt;
      &lt;evictionScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory"&gt;
        &lt;properties&gt;
          &lt;property name="threadNamePrefix" value="EvictionThread"/&gt;
        &lt;/properties&gt;
      &lt;/evictionScheduledExecutor&gt;

      &lt;globalJmxStatistics jmxDomain="exo" enabled="true" allowDuplicateDomains="true"/&gt;

      &lt;transport transportClass="org.infinispan.remoting.transport.jgroups.JGroupsTransport" clusterName="${infinispan-cluster-name}" distributedSyncTimeout="20000"&gt;
        &lt;properties&gt;
          &lt;property name="configurationFile" value="${jgroups-configuration}"/&gt;
        &lt;/properties&gt;
      &lt;/transport&gt;
    &lt;/global&gt;

    &lt;default&gt;
      &lt;clustering mode="replication"&gt;
        &lt;stateTransfer timeout="20000" fetchInMemoryState="false" /&gt;
        &lt;sync replTimeout="20000"/&gt;
      &lt;/clustering&gt;

      &lt;locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500" useLockStriping="false"/&gt;
      &lt;transaction transactionManagerLookupClass="org.exoplatform.services.transaction.infinispan.JBossStandaloneJTAManagerLookup" syncRollbackPhase="true" syncCommitPhase="true"/&gt;
      &lt;jmxStatistics enabled="true"/&gt;
      &lt;eviction strategy="NONE"/&gt;

      &lt;loaders passivation="false" shared="true" preload="true"&gt;
        &lt;store class="org.exoplatform.services.jcr.infinispan.JdbcStringBasedCacheStore" fetchPersistentState="true" ignoreModifications="false" purgeOnStartup="false"&gt;
          &lt;properties&gt;
             &lt;property name="stringsTableNamePrefix" value="${infinispan-cl-cache.jdbc.table.name}"/&gt;
             &lt;property name="idColumnName" value="${infinispan-cl-cache.jdbc.id.column}"/&gt;
             &lt;property name="dataColumnName" value="${infinispan-cl-cache.jdbc.data.column}"/&gt;
             &lt;property name="timestampColumnName" value="${infinispan-cl-cache.jdbc.timestamp.column}"/&gt;
             &lt;property name="idColumnType" value="${infinispan-cl-cache.jdbc.id.type}"/&gt;
             &lt;property name="dataColumnType" value="${infinispan-cl-cache.jdbc.data.type}"/&gt;
             &lt;property name="timestampColumnType" value="${infinispan-cl-cache.jdbc.timestamp.type}"/&gt;
             &lt;property name="dropTableOnExit" value="${infinispan-cl-cache.jdbc.table.drop}"/&gt;
             &lt;property name="createTableOnStart" value="${infinispan-cl-cache.jdbc.table.create}"/&gt;
             &lt;property name="connectionFactoryClass" value="${infinispan-cl-cache.jdbc.connectionFactory}"/&gt;
             &lt;property name="datasourceJndiLocation" value="${infinispan-cl-cache.jdbc.datasource}"/&gt;
          &lt;/properties&gt;
          &lt;async enabled="false"/&gt;
        &lt;/store&gt;
      &lt;/loaders&gt;
   &lt;/default&gt;

&lt;/infinispan&gt;</programlisting>

      <note>
        <para>To prevent any consistency issue regarding the lock data +
        please ensure that your cache loader is
        <emphasis>org.exoplatform.services.jcr.infinispan.JdbcStringBasedCacheStore</emphasis>
        and that your database engine is transactional.</para>
      </note>

      <para>As you see, all configurable parameters are filled by templates
      and will be replaced by LockManagers configuration parameters:</para>

      <programlisting language="xml">&lt;lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl"&gt;
   &lt;properties&gt;
      &lt;property name="time-out" value="15m" /&gt;
      &lt;property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-lock.xml" /&gt;
      &lt;property name="jgroups-configuration" value="udp-mux.xml" /&gt;
      &lt;property name="infinispan-cluster-name" value="JCR-cluster" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.table.name" value="lk" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.table.create" value="true" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.table.drop" value="false" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.id.column" value="id" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.data.column" value="data" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcr" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.dialect" value="${dialect}" /&gt;
      &lt;property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.exoplatform.services.jcr.infinispan.ManagedConnectionFactory" /&gt;
   &lt;/properties&gt;
&lt;/lock-manager&gt;</programlisting>

      <para>Configuration requirements:<itemizedlist>
          <listitem>
            <para>infinispan-cl-cache.jdbc.id.type,
            infinispan-cl-cache.jdbc.data.type and
            infinispan-cl-cache.jdbc.timestamp.type are injected in the
            Infinispan configuration into the property respectively
            idColumnType, dataColumnType and timestampColumnType. You can set
            those data types according to your database type or set it as AUTO
            (or do not set at all) and data type will be detected
            automatically.</para>
          </listitem>

          <listitem>
            <para>As you see, jgroups-configuration is moved to separate the
            configuration file - udp-mux.xml. In this case, the udp-mux.xml
            file is a common JGroup configuration for all components
            (QueryHandler, Cache, LockManager), but we can still create our
            own configuration.</para>
          </listitem>
        </itemizedlist></para>

      <para><filename>our udp-mux.xml</filename></para>

      <programlisting language="xml">&lt;config&gt;
    &lt;UDP
         singleton_name="JCR-cluster" 
         mcast_addr="${jgroups.udp.mcast_addr:228.10.10.10}"
         mcast_port="${jgroups.udp.mcast_port:45588}"
         tos="8" 
         ucast_recv_buf_size="20000000"
         ucast_send_buf_size="640000" 
         mcast_recv_buf_size="25000000" 
         mcast_send_buf_size="640000" 
         loopback="false"
         discard_incompatible_packets="true" 
         max_bundle_size="64000" 
         max_bundle_timeout="30"
         use_incoming_packet_handler="true" 
         ip_ttl="${jgroups.udp.ip_ttl:2}"
         enable_bundling="false" 
         enable_diagnostics="true"
         thread_naming_pattern="cl" 

         use_concurrent_stack="true" 

         thread_pool.enabled="true" 
         thread_pool.min_threads="2"
         thread_pool.max_threads="8" 
         thread_pool.keep_alive_time="5000" 
         thread_pool.queue_enabled="true"
         thread_pool.queue_max_size="1000"
         thread_pool.rejection_policy="discard"

         oob_thread_pool.enabled="true"
         oob_thread_pool.min_threads="1"
         oob_thread_pool.max_threads="8"
         oob_thread_pool.keep_alive_time="5000"
         oob_thread_pool.queue_enabled="false" 
         oob_thread_pool.queue_max_size="100" 
         oob_thread_pool.rejection_policy="Run" /&gt;

    &lt;PING timeout="2000"&lt;config xmlns="urn:org:jgroups"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/JGroups-3.2.xsd"&gt;
    &lt;UDP
         singleton_name="JCR-cluster" 
         mcast_port="${jgroups.udp.mcast_port:45588}"
         tos="8"
         ucast_recv_buf_size="20M"
         ucast_send_buf_size="640K"
         mcast_recv_buf_size="25M"
         mcast_send_buf_size="640K"
         loopback="true"
         max_bundle_size="64K"
         max_bundle_timeout="30"
         ip_ttl="${jgroups.udp.ip_ttl:8}"
         enable_bundling="true"
         enable_diagnostics="true"
         thread_naming_pattern="cl"

         timer_type="old"
         timer.min_threads="4"
         timer.max_threads="10"
         timer.keep_alive_time="3000"
         timer.queue_max_size="500"

         thread_pool.enabled="true"
         thread_pool.min_threads="2"
         thread_pool.max_threads="8"
         thread_pool.keep_alive_time="5000"
         thread_pool.queue_enabled="true"
         thread_pool.queue_max_size="10000"
         thread_pool.rejection_policy="discard"

         oob_thread_pool.enabled="true"
         oob_thread_pool.min_threads="1"
         oob_thread_pool.max_threads="8"
         oob_thread_pool.keep_alive_time="5000"
         oob_thread_pool.queue_enabled="false"
         oob_thread_pool.queue_max_size="100"
         oob_thread_pool.rejection_policy="Run"/&gt;

    &lt;PING timeout="2000"
            num_initial_members="20"/&gt;
    &lt;MERGE2 max_interval="30000"
            min_interval="10000"/&gt;
    &lt;FD_SOCK/&gt;
    &lt;FD_ALL/&gt;
    &lt;VERIFY_SUSPECT timeout="1500"  /&gt;
    &lt;BARRIER /&gt;
    &lt;pbcast.NAKACK2 xmit_interval="1000"
                    xmit_table_num_rows="100"
                    xmit_table_msgs_per_row="2000"
                    xmit_table_max_compaction_time="30000"
                    max_msg_batch_size="500"
                    use_mcast_xmit="false"
                    discard_delivered_msgs="true"/&gt;
    &lt;UNICAST  xmit_interval="2000"
              xmit_table_num_rows="100"
              xmit_table_msgs_per_row="2000"
              xmit_table_max_compaction_time="60000"
              conn_expiry_timeout="60000"
              max_msg_batch_size="500"/&gt;
    &lt;pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
                   max_bytes="4M"/&gt;
    &lt;pbcast.GMS print_local_addr="true" join_timeout="3000"
                view_bundling="true"/&gt;
    &lt;UFC max_credits="2M"
         min_threshold="0.4"/&gt;
    &lt;MFC max_credits="2M"
         min_threshold="0.4"/&gt;
    &lt;FRAG2 frag_size="60K"  /&gt;
    &lt;RSVP resend_interval="2000" timeout="10000"/&gt;
    &lt;pbcast.STATE_TRANSFER /&gt;
    &lt;!-- pbcast.FLUSH  /--&gt;
&lt;/config&gt;</programlisting>
    </section>

    <section id="datatypes">
      <title id="datatypes.title">Data Types in Different Databases</title>

      <table>
        <title>Data, id and timestamp type in different databases</title>

        <tgroup cols="4">
          <thead>
            <row>
              <entry>DataBase name</entry>

              <entry>Data type</entry>

              <entry>Id type</entry>

              <entry>Timestamp type</entry>
            </row>
          </thead>

          <tbody>
            <row>
              <entry>default</entry>

              <entry>BLOB</entry>

              <entry>VARCHAR(512)</entry>

              <entry>BIGINT</entry>
            </row>

            <row>
              <entry>HSSQL</entry>

              <entry>VARBINARY(65535)</entry>

              <entry>VARCHAR(512)</entry>

              <entry>BIGINT</entry>
            </row>

            <row>
              <entry>MySQL</entry>

              <entry>LONGBLOB</entry>

              <entry>VARCHAR(512)</entry>

              <entry>BIGINT</entry>
            </row>

            <row>
              <entry>ORACLE</entry>

              <entry>BLOB</entry>

              <entry>VARCHAR2(512)</entry>

              <entry>NUMBER(19, 0)</entry>
            </row>

            <row>
              <entry>PostgreSQL/PostgrePlus</entry>

              <entry>bytea</entry>

              <entry>VARCHAR(512)</entry>

              <entry>BIGINT</entry>
            </row>

            <row>
              <entry>MSSQL</entry>

              <entry>VARBINARY(MAX)</entry>

              <entry>VARCHAR(512)</entry>

              <entry>BIGINT</entry>
            </row>

            <row>
              <entry>DB2</entry>

              <entry>BLOB</entry>

              <entry>VARCHAR(512)</entry>

              <entry>BIGINT</entry>
            </row>

            <row>
              <entry>Sybase</entry>

              <entry>IMAGE</entry>

              <entry>VARCHAR(512)</entry>

              <entry>BIGINT</entry>
            </row>

            <row>
              <entry>Ingres</entry>

              <entry>long byte</entry>

              <entry>VARCHAR(512)</entry>

              <entry>BIGINT</entry>
            </row>
          </tbody>
        </tgroup>
      </table>
    </section>

    <section id="LockMigrationFrom1.12.x">
      <title>Lock migration from 1.12.x</title>

      <para>There are 3 choices:</para>

      <para>I. When new Shareable Cache feature is not going to be used and
      all locks should be kept after migration.</para>

      <itemizedlist>
        <listitem>
          <para>Ensure that the same lock tables used in configuration;</para>
        </listitem>

        <listitem>
          <para>Start the server;</para>
        </listitem>
      </itemizedlist>

      <para>II. When new Shareable Cache feature is not going to be used and
      all locks should be removed after migration.</para>

      <itemizedlist>
        <listitem>
          <para>Ensure that the same lock tables used in configuration;</para>
        </listitem>

        <listitem>
          <para>Start the sever WITH system property
          -Dorg.exoplatform.jcr.locks.force.remove=true;</para>
        </listitem>

        <listitem>
          <para>Stop the server;</para>
        </listitem>

        <listitem>
          <para>Start the server (WITHOUT system property
          -Dorg.exoplatform.jcr.locks.force.remove);</para>
        </listitem>
      </itemizedlist>

      <para>III. When new Shareable Cache feature will be used (in this case
      all locks are removed after migration).</para>

      <itemizedlist>
        <listitem>
          <para>Start the sever WITH system property
          -Dorg.exoplatform.jcr.locks.force.remove=true;</para>
        </listitem>

        <listitem>
          <para>Stop the server;</para>
        </listitem>

        <listitem>
          <para>Start the server (WITHOUT system property
          -Dorg.exoplatform.jcr.locks.force.remove);</para>
        </listitem>

        <listitem>
          <para>(Not mandatory) manually remove old tables for lock;</para>
        </listitem>
      </itemizedlist>
    </section>
  </section>
</section>
