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.
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>
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
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
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...
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.
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>
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>-->
Mixing runtime configurations can give you some hassle. Terracotta lives best when running one of the following:
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.
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.
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.