<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="JCR.WorkspacePersistenceStorage">
  <title>Workspace Data Container</title>

  <para>Each Workspace of JCR has its own persistent storage to hold
  workspace's items data. eXo Content Repository can be configured so that it
  can use one or more workspaces that are logical units of the repository
  content. Physical data storage mechanism is configured using mandatory
  element <emphasis role="bold">container</emphasis>. The type of container is
  described in the attribute <emphasis role="bold">class</emphasis> = fully
  qualified name of
  org.exoplatform.services.jcr.storage.WorkspaceDataContainer subclass
  like</para>

  <programlisting language="xml">&lt;container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer"&gt;
  &lt;properties&gt;
    &lt;property name="source-name" value="jdbcjcr1"/&gt;
    &lt;property name="dialect" value="hsqldb"/&gt;
    &lt;property name="multi-db" value="true"/&gt;
    &lt;property name="max-buffer-size" value="200K"/&gt;
    &lt;property name="swap-directory" value="target/temp/swap/ws"/&gt;
    &lt;property name="lazy-node-iterator-page-size" value="50"/&gt;
    &lt;property name="acl-bloomfilter-false-positive-probability" value="0.1d"/&gt;
    &lt;property name="acl-bloomfilter-elements-number" value="1000000"/&gt;
    &lt;property name="acl-bloomfilter-enabled" value="true"/&gt;
    &lt;property name="check-sns-new-connection" value="false"/&gt;
    &lt;property name="batch-size" value="1000"/&gt;
  &lt;/properties&gt;</programlisting>

  <para><emphasis role="bold">Workspace Data Container specific
  parameters:</emphasis></para>

  <itemizedlist>
    <listitem>
      <para><emphasis role="bold">max-buffer-size</emphasis>: A threshold in
      bytes, if a value size is greater, then it will be spooled to a
      temporary file. Default value is 200k.</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">swap-directory</emphasis>: A location where
      the value will be spooled if no value storage is configured but a
      max-buffer-size is exceeded. Default value is the value of
      "java.io.tmpdir" system property.</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">lazy-node-iterator-page-size</emphasis>:
      "Lazy" child nodes iterator settings. Defines size of page, the number
      of nodes that are retrieved from persistent storage at once. Default
      value is 100.</para>
    </listitem>

    <listitem>
      <para><emphasis
      role="bold">acl-bloomfilter-false-positive-probability</emphasis>: ACL
      Bloom-filter settings. ACL Bloom-filter desired false positive
      probability. Range [0..1]. Default value 0.1d.</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">acl-bloomfilter-elements-number</emphasis>:
      ACL Bloom-filter settings. Expected number of ACL-elements in the
      Bloom-filter. Default value 1000000.</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">acl-bloomfilter-enabled</emphasis>:
      Add the ability to disable the bloomfilter. Default value true (enabled).</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">check-sns-new-connection:</emphasis> Defines
      if we need to create new connection for checking if an older same-name
      sibling exists. Default value is "false".</para>
    </listitem>

    <listitem>
      <para><emphasis
      role="bold">trigger-events-for-descendants-on-rename:</emphasis>
      Indicates whether or not each descendant item must be included into the
      changes log in case of a rename. If it is set to false, it will allow to
      increase performance on rename operations if there is a big amount of
      nodes under the source parent node but it will decrease the performance
      with a small amount of sub nodes. If it is set to true, we will get the
      exact opposite, the performance will be better in case of small amount
      of sub nodes and worse in case of big amount of sub nodes. When this
      parameter is not set, the application will rely on the parameter
      <emphasis>max-descendant-nodes-allowed-on-move</emphasis> to add or not
      the descendant items to the changes log. If this parameter is not set
      but the parameter
      <emphasis>trigger-events-for-descendants-on-move</emphasis> is set, it
      will have the same value.</para>
    </listitem>

    <listitem>
      <para><emphasis
      role="bold">trigger-events-for-descendants-on-move:</emphasis> Indicates
      whether or not each descendant item must be included into the changes
      log in case of a move. If it is set to false, it will allow to increase
      performance on move operations if there is a big amount of nodes under
      the source parent node but it will decrease the performance with a small
      amount of sub nodes. If it is set to true, we will get the exact
      opposite, the performance will be better in case of small amount of sub
      nodes and worse in case of big amount of sub nodes. When this parameter
      is not set, the application will rely on the parameter
      <emphasis>max-descendant-nodes-allowed-on-move</emphasis> to add or not
      the descendant items to the changes log.</para>
    </listitem>

    <listitem>
      <para><emphasis
      role="bold">max-descendant-nodes-allowed-on-move:</emphasis> The maximum
      amount of descendant nodes allowed before considering that the
      descendant items should not be included into the changes log. This
      allows to have the best possible performances whatever the total amount
      of sub nodes. The default value is 100. This parameter is only used if
      and only if <emphasis>trigger-events-for-descendants-on-move</emphasis>
      is not set and in case of a rename
      <emphasis>trigger-events-for-descendants-on-rename</emphasis> is not
      set.</para>
    </listitem>
  </itemizedlist>

  <note>
    <para>Bloom filters are not supported by all the cache implementations so
    far only the inplementation for infinispan supports it. They are used to
    avoid read nodes that definitely do not have ACL. <emphasis
    role="bold">acl-bloomfilter-false-positive-probability</emphasis> and
    <emphasis role="bold">acl-bloomfilter-elements-number</emphasis> used to
    configure such filters.More about Bloom filters you can read <ulink
    url="http://en.wikipedia.org/wiki/Bloom_filter&quot; &gt;http://en.wikipedia.org/wiki/Bloom_filter">here</ulink>.</para>
  </note>

  <para>eXo JCR has an RDB (JDBC) based, production ready <emphasis
  role="bold">Workspace Data Container</emphasis>.</para>

  <para><emphasis role="bold">JDBC Workspace Data Container specific
  parameters:</emphasis></para>

  <itemizedlist>
    <listitem>
      <para><emphasis role="bold">source-name</emphasis>: JDBC data source
      name, registered in JDNI by InitialContextInitializer. ( <emphasis
      role="bold">sourceName</emphasis> prior v.1.9). This property is
      <emphasis role="bold">mandatory</emphasis>.</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">dialect</emphasis>: Database dialect, one of
      "hsqldb", "h2", "mysql", "mysql-myisam", "mysql-utf8",
      "mysql-myisam-utf8", "pgsql", "pgsql-scs", "oracle", "oracle-oci",
      "mssql", "sybase", "derby", "db2" , "db2v8". The default value
      is "auto".</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">multi-db</emphasis>: Enable multi-database
      container with this parameter (if "true"). Otherwise (if "false")
      configured for single-database container. Please, be aware, that this
      property is currently <emphasis role="bold">deprecated</emphasis>. It is
      advised to use <emphasis>db-structure-type</emphasis> instead.</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">db-structure-type</emphasis>: Can be set to
      <emphasis>isolated, multi, single</emphasis> to set corresponding
      configuration for data container. This property is <emphasis
      role="bold">mandatory.</emphasis></para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">db-tablename-suffix:</emphasis> If
      <emphasis>db-structure-type </emphasis>is set to
      <emphasis>isolated</emphasis>, tables, used by repository service, have
      the following format:</para>

      <itemizedlist>
        <listitem>
          <para>JCR_I${db-tablename-suffix} - for items</para>
        </listitem>

        <listitem>
          <para>JCR_V${db-tablename-suffix} - for values</para>
        </listitem>

        <listitem>
          <para>JCR_R${db-tablename-suffix} - for references</para>

          <para><emphasis>db-tablename-suffix</emphasis> by default equals to
          workspace name, but can be set via configuration to any
          suitable.</para>
        </listitem>
      </itemizedlist>
    </listitem>

    <listitem>
      <para><emphasis role="bold">batch-size:</emphasis> the batch size.
      Default value is -1 (disabled)</para>
    </listitem>

    <listitem>
      <para><emphasis role="bold">use-sequence-for-order-number:</emphasis> Indicates whether or not a sequence must
      be used to manage the order number. The value expected for this parameter is a boolean or "auto",
      by default it is set to "auto" where the value of use-sequence will be set automatically according to your database type.</para>
      <itemizedlist>
        <listitem>
          <para>It is enabled in case of H2, HSQLDB, PGSQL and ORACLE.</para>
        </listitem>

        <listitem>
          <para>It is disabled in case of MSSQL, MYSQL, DB2 and SYBASE.</para>
        </listitem>
      </itemizedlist>
    </listitem>
  </itemizedlist>

  <para>Workspace Data Container MAY support external storages for
  javax.jcr.Value (which can be the case for BLOB values for example) using
  the optional element <emphasis role="bold">value-storages</emphasis>. Data
  Container will try to read or write Value using underlying value storage
  plugin if the filter criteria (see below) match the current property.</para>

  <programlisting language="xml">&lt;value-storages&gt;
  &lt;value-storage id="Storage #1" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage"&gt;
    &lt;properties&gt;
      &lt;property name="path" value="data/values"/&gt;
    &lt;/properties&gt;
    &lt;filters&gt;
     &lt;filter property-type="Binary" min-value-size="1M"/&gt;&lt;!-- Values large of 1Mbyte --&gt;
    &lt;/filters&gt;
.........
&lt;/value-storages&gt;</programlisting>

  <para>Where <emphasis role="bold">value-storage</emphasis> is the subclass
  of org.exoplatform.services.jcr.storage.value.ValueStoragePlugin and
  <emphasis role="bold">properties</emphasis> are optional plugin specific
  parameters.</para>

  <para><emphasis role="bold">filters</emphasis> : Each file value storage can
  have the filter(s) for incoming values. If there are several filter
  criteria, they all have to match (AND-Condition).</para>

  <para>A filter can match values by property type (property-type), property
  name (property-name), ancestor path (ancestor-path) and/or the size of
  values stored (min-value-size, e.g. 1M, 4.2G, 100 (bytes)).</para>

  <para>In a code sample, we use a filter with property-type and
  min-value-size only. That means that the storage is only for binary values
  whose size is greater than 1Mbyte.</para>

  <para>It's recommended to store properties with large values in a file value
  storage only.</para>

  <section id="JCR.WorkspacePersistenceStorage.DatabasesDialects">
    <title>Database's dialects</title>

    <section id="JCR.WorkspacePersistenceStorage.DatabasesDialects.PostgreSQLDatabase">
      <title>PostgreSQL/PostgrePlus database</title>

      <para>PostgreSQL/PostgrePlus's dialect is set automatically. The dialect
      depends on the version of database. If you change default value of
      <emphasis>standard_conforming_strings</emphasis> parameter than you must
      configure one of the following dialects manually:<itemizedlist>
          <listitem>
            <para>PgSQL - this dialect is used if
            <emphasis>standard_conforming_strings</emphasis> is set to off.
            This is default value for version before 9.1.</para>
          </listitem>

          <listitem>
            <para>PgSQL-SCS - this dialect is used if
            <emphasis>standard_conforming_strings</emphasis> is set to on.
            This is default value for version after 9.1.</para>
          </listitem>
        </itemizedlist></para>
    </section>

    <section>
      <title>DB2 database</title>

      <para>As well as PostgreSQL, DB2's dialect is set automatically depends
      on the version of database. If you change the default value of
      DB2_COMPATIBILITY_VECTOR parameter than you must configure one of the
      following dialects manually:</para>

      <itemizedlist>
        <listitem>
          <para>DB2V8 - this dialect is used if version of database is lower
          than 9</para>
        </listitem>
      </itemizedlist>

      <itemizedlist>
        <listitem>
          <para>DB2 - this dialect is used if version of database not lower
          than 9 and <emphasis>DB2_COMPATIBILITY_VECTOR</emphasis> is se to
          <emphasis>0</emphasis></para>
        </listitem>

      </itemizedlist>
    </section>

    <section>
      <title>MySQL database</title>

      <itemizedlist>
        <listitem>
          <para>mysql - this dialect is used if needed to create JCR tables
          with InnoDB engine <emphasis role="bold">(by
          default)</emphasis></para>
        </listitem>

        <listitem>
          <para>mysql-utf8 - this dialect is used if needed to create JCR
          tables with InnoDB engine with UTF-8 encoding support</para>
        </listitem>

        <listitem>
          <para>mysql-myisam - this dialect is used if needed to create JCR
          tables with MyISAM engine</para>
        </listitem>

        <listitem>
          <para>mysql-myisam-utf8 - this dialect is used if needed to create
          JCR tables with MyISAM engine with UTF-8 encoding support</para>
        </listitem>

        <listitem>
          <para>mysql-ndb - this dialect is used if needed to create JCR
          tables with NDB engine (mysql cluster)</para>
        </listitem>

        <listitem>
          <para>mysql-ndb-utf8 - this dialect is used if needed to create JCR
          tables with NDB engine (mysql cluster) with UTF-8 encoding
          support</para>
        </listitem>
      </itemizedlist>

      <note>
        <para>MySQL NDB engine (version 7.2) does not support foreign keys, which may
        lead to improper item removal and as consequence to
        InvalidItemStateException. In this case you will need to use
        consistency checker tool.
        Foreign keys are supported in MySQL Cluster NDB 7.3 and later.</para>
      </note>

      <note>
        <para>
        To migrate the jcr tables from innoDB to NDB engine.
        You need to make 3 steps  (Example of database structure : single):
        </para>

        <itemizedlist>
          <listitem>
            <para> Drop the constraints foreign keys :
            <programlisting>
              ALTER TABLE JCR_SVALUE DROP FOREIGN KEY JCR_FK_SVALUE_PROPERTY;
              ALTER TABLE JCR_SITEM DROP FOREIGN KEY JCR_FK_SITEM_PARENT;
            </programlisting></para>
          </listitem>
          <listitem>
            <para> Alter the jcr tables use the NDB engine :
            <programlisting>
              ALTER TABLE JCR_SREF ENGINE=NDB;
              ALTER TABLE JCR_SVALUE ENGINE=NDB;
              ALTER TABLE JCR_SITEM ENGINE=NDB;
            </programlisting></para>
          </listitem>
          <listitem>
            <para> Recreate the constraints foreign keys ( since 7.3 Mysql cluster version) :
            <programlisting>
              ALTER TABLE JCR_SVALUE ADD CONSTRAINT `JCR_FK_SVALUE_PROPERTY` FOREIGN KEY (`PROPERTY_ID`) REFERENCES `JCR_SITEM` (`ID`);
              ALTER TABLE JCR_SITEM ADD CONSTRAINT `JCR_FK_SITEM_PARENT` FOREIGN KEY (`PARENT_ID`) REFERENCES `JCR_SITEM` (`ID`);
            </programlisting></para>
          </listitem>

        </itemizedlist>
        <para>
          You should use the same steps to migrate from innoDB to NDB engine for isolated and multi database structure.
        </para>
      </note>
    </section>
  </section>
</section>
