Previous: Preliminaries Up: Installation Next: Tutorials

This chapter can be skipped, if you are not going to use Terracotta, or if you are not going to use Terracotta right away.

This explanation is aimed at Terracotta version 3.4.1.

Configuration of Terracotta

You can use SemiSpace's tc-config as a starting point for your configuration.

You can download the configuration SemiSpace is set up to use from the subversion repository:
http://www.semispace.org/svn/trunk/tc-config.xml
The TIM version can be found here:
http://www.semispace.org/svn/trunk/tc-tim.xml

The configurations can be modified to your own needs. You find comments inside it which should help you along. See Terracotta documentation for more information about configuration.

You want to set the environment variable TC_INSTALL_DIR pointing at the, surprise, installation directory of Terracotta:

export TC_INSTALL_DIR=<where you have exploded the terracotta-3.x.x.tar.gz file>

Using Maven for SemiSpace TIM reference

The easiest way of configuring SemiSpace for Terracotta, is to use Maven and add a <repository/> section in your tc-config.xml. This tells Terracotta where it can find these modules:

    <modules>
        <!-- You only need jetty module if you are actually using jetty -->
        <module name="tim-jetty-6.1" version="2.2.1"/>
        <repository>%(user.home)/.m2/repository</repository>
        <module name="semispace-tim" version="1.3.0" group-id="org.semispace"/>
	</modules>

Notice that the bundle reference only works with released versions, as it does not manage to parse "SNAPSHOT" as an integer.

--- assuming that your local Maven repository is at:

~/.m2/repository

Jetty TIM module

If you are going to use Jetty, you need the jetty TIM module for the Terracotta configuration, if this has not already been installed. You can check and obtain it by doing as follows:

$TC_INSTALL_DIR/bin/tim-get.sh list jetty  
$TC_INSTALL_DIR/bin/tim-get.sh install tim-jetty-6.1 2.2.1 org.terracotta.modules

Starting the server

Start the terracotta server with an invocation similar to:

${TC_INSTALL_DIR}/bin/start-tc-server.sh -f some/path/to/config/tc-config.xml 

The server part of the configuration file may look something like this:

  <servers>

    <!-- When having remote clients in a multiserver setup, you _must_ give the host an IP address -->
    <server host="%i" name="localhost">
      <dso-port>9510</dso-port>
      <jmx-port>9520</jmx-port>
      <l2-group-port>9530</l2-group-port>
      <data>/tmp/terracotta/server-data</data>
      <logs>/tmp/terracotta/server-logs</logs>
      <!-- If you are sharing disk space over nfs or NAS, or are running in single VM modus 
      <dso>
        <persistence>
          <mode>permanent-store</mode>
        </persistence>
      </dso>
       -->
      <dso>
        <persistence>
          <mode>temporary-swap-only</mode>
        </persistence>
      </dso>
    </server>
    <!-- If you have some other server available
    <server host="servername.some.domain" name="servername">
      <dso-port>9510</dso-port>
      <jmx-port>9520</jmx-port>
      <l2-group-port>9530</l2-group-port>
      <data>/tmp/terracotta/server-data</data>
      <logs>/tmp/terracotta/server-logs</logs>
      <dso>
        <persistence>
          <mode>temporary-swap-only</mode>
        </persistence>
      </dso>
    </server>
     -->
    <ha>
      <mode>networked-active-passive</mode>
      <networked-active-passive>
        <election-time>5</election-time>
      </networked-active-passive>
    </ha>
  </servers>
  <clients>
    <logs>terracotta/client-logs</logs>
    <!-- Load jetty-module. Notice that Eclipse integration will fail 
        if TIM support has not been installed. The module version
         may exist in different versions--> 
	<modules>
	    <!-- module name="tim-jetty-6.1" version="2.2.1"/ -->
        <!-- module name="semispace-tim" version="1.3.0" group-id="org.semispace"/ -->
	</modules> 
  </clients>

Notice that you need to exchange the "%i" with a real DNS name or IP address if you are using remote clients that receive the configuration from the server. Otherwise they will simply not find the server...

Sharing the configuration with clients

Clients need to use the same configuration as the Terracotta server. This is most easily performed by letting the clients retrieve the configuration from the server (exchanging localhost with the name of your real host if applicable):

${TC_INSTALL_DIR}/bin/dso-java.sh -Dtc.config=localhost:9510

In addition to the configuration of the Terracotta server itself, you need to either configure up SemiSpace to use java objects, or to retrieve the space configuration from spring.

The Terracotta configuration can naturally be amended with your "other" configuration as well; Just add it. This may be useful if you also want to, lets say, distribute the webapp session objects.

Notice that only some configuration highlights are presented here. You will benefit from reading more about Terracotta on their home page.

POJO configuration

This is typically the configuration you will use outside a webapp. Note that this is not relevant if you use the SemiSpace TIM, as the TIM will take care of the configuration for you.

If you prefer to obtain a distributed reference to Terracotta without using Spring, you need to add the relevant SemiSpace specific class files.

The relevant configuration snippet for this is:

<application>
  <dso>
    <!-- Could not share a common root between different
       contexts even when https://jira.terracotta.org/jira/browse/CDV-272
       indicates I can:
    <app-groups>
      <app-group name="space">
        <web-application>semispace-war</web-application>
        <web-application>semispace-google</web-application>
      </app-group>
    </app-groups>
      -->      
    <instrumented-classes>
      <include>
        <class-expression>org.semispace.HolderContainer</class-expression>
        <honor-transient>true</honor-transient>
      </include>
      <include>
        <class-expression>org.semispace.Holder</class-expression>
        <honor-transient>true</honor-transient>
      </include>
      <include>
        <class-expression>org.semispace.HolderContainer</class-expression>
        <honor-transient>true</honor-transient>
      </include>
      <include>
        <class-expression>org.semispace.HolderElement</class-expression>
        <honor-transient>true</honor-transient>
      </include>
      <include>
        <class-expression>org.semispace.EventDistributor</class-expression>
        <honor-transient>true</honor-transient>
      </include>
      <include>
        <class-expression>org.semispace.SemiSpaceStatistics</class-expression>
        <honor-transient>true</honor-transient>
      </include>
        <include>
           <class-expression>org.semispace.event.SemiEvent</class-expression>
         </include>
        <include>
           <class-expression>org.semispace.event.SemiExpirationEvent</class-expression>
         </include>
      <include>
         <class-expression>org.semispace.event.SemiAvailabilityEvent</class-expression>
       </include>        
      <include>
         <class-expression>org.semispace.event.SemiTakenEvent</class-expression>
       </include>        
      <include>
         <class-expression>org.semispace.event.SemiRenewalEvent</class-expression>
       </include>        
    </instrumented-classes>
    <locks>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.removeHolderById(..)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.removeEmptyHeads(..)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.addHolder(..)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.findById(long,String)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.size(..)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.retrieveGroupNames(..)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.waitHolder(..)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.readHolderWithId(..)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderContainer.retrieveClassNames(..)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      
      <autolock>
        <method-expression>* org.semispace.HolderElement.size(..)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderElement.removeHolderById(..)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderElement.addHolder(..)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderElement.toArray(..)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderElement.iterator(..)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderElement.isWaiting(..)</method-expression>
        <lock-level>read</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.HolderElement.waitHolder(..)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
      
      <autolock>
        <method-expression>* org.semispace.Holder.setLiveUntil(long)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
      <autolock>
        <method-expression>* org.semispace.EventDistributor.distributeEvent(DistributedEvent)</method-expression>
        <lock-level>write</lock-level>
      </autolock>
    </locks>
    <roots>
      <root>
        <field-name>org.semispace.HolderContainer.instance</field-name>
      </root>
    </roots>
    <!-- transient-fields>
      <field-name>org.semispace.SemiSpace.listeners</field-name>
      <field-name>org.semispace.SemiSpace.admin</field-name>
      <field-name>org.semispace.SemiSpace.xStream</field-name>
    </transient-fields -->
    <!-- distributed-methods>
      <method-expression>void org.semispace.SemiSpace.notifyListeners(org.semispace.EventDistributor)</method-expression>
    </distributed-methods  -->
    <distributed-methods>
      <method-expression>void org.semispace.EventDistributor.distributeEvent(org.semispace.DistributedEvent)</method-expression>
    </distributed-methods>      
  </dso>

Spring configuration

If you are running within a webapp, and are using spring, you can add the following. Note that this is not relevant if you use the SemiSpace TIM. You will need a named configuration element for each of your webapps. Depending on your scenario, you may find it easier / more maintainable to just define and use the application in a POJO manner.

<!--
  Clustering Spring no longer requires special configuration. For more information, see http://www.terracotta.org/spring.
  <spring>
    <jee-application name="*">
      <application-contexts>
        <application-context>
          <paths>
            <path>*.xml</path>
          </paths>
          <beans>
            The other beans to share beside semispace 
            SemiSpace is covered in the dso configuration, and we do NOT need: <bean name="semispace" />
          </beans>
        </application-context>
      </application-contexts>
    </jee-application>
  </spring>-->

You can only mix some Terracotta runtime configurations

Mixing runtime configurations can give you some hassle. Terracotta lives best when running one of the following:

  • Running with a POJO container, such as a standalone console program.
  • Running Spring configured in a webapp.
  • Running POJO-invoked in a webapp.

It is possible to mix some configurations, but it may involve an effort. The reason and explanation can be found here: Object identity in Terracotta is dependent on the classLoaderName + fully qualified reference name.

Mixing console app and webapp

Presuming you are running with Jetty, the following extra parameter will interface your console application with your webapp:

-Dcom.tc.loader.system.name="Jetty.path:/some_path"

Terracottas documentation explains this in greater detail. The problem is even larger if you are using spring to configure the application.

Running with Terracotta within Eclipse

For test purposes, or ease of development, you may want to run Terracotta within Eclipse.

Besides Eclipse itself, you will need the Terracotta eclipse plugin. Activate your project as a "Terracotta DSO project".

If you do not have a tc-config.xml file already, create one as explained above.

Presumably, your program is already using SemiSpace. Then the easiest way of testing the Eclipse / Terracotta easiest way of performing tests, is to create a junit test. Then choose to run the tests as "Terracotta DSO junit test". This will prompt you to start a local Terracotta server, which you may have to do, depending on the contents of you tc-config.xml file.

Notice that you probably want to remove the TIM module from the configuration whilst running under Eclipse, as this will make the integration fail. Presumably, you do not need Jetty integration in Eclipse.


Previous: Preliminaries Up: Installation Next: Tutorials