Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## org.quartz.spi
Interface JobStore

All Known Subinterfaces:
  ClusteredJobStore, TerracottaJobStoreExtensions

All Known Implementing Classes:
  AbstractTerracottaJobStore, JobStoreCMT, JobStoreSupport, JobStoreTX, PlainTerracottaJobStore, RAMJobStore, TerracottaJobStore

    public interface JobStore

The interface to be implemented by classes that want to provide a ``Job`` and ``Trigger`` storage mechanism for the ``QuartzScheduler``'s use.

Storage of `Job` s and `Trigger` s should be keyed on the combination of their name and group for uniqueness.

Author:
  James House, Eric Mueller
See Also:
  `QuartzScheduler`, `Trigger`, `Job`, `JobDetail`, `JobDataMap`, `Calendar`

Method Summary
`List<OperableTrigger>` | `acquireNextTriggers(long noLaterThan, int maxCount, long timeWindow)` Get a handle to the next trigger to be fired, and mark it as 'reserved' by the calling scheduler.
`boolean` | `checkExists(JobKey jobKey)` Determine whether a `Job` with the given identifier already exists within the scheduler.
`boolean` | `checkExists(TriggerKey triggerKey)` Determine whether a `Trigger` with the given identifier already exists within the scheduler.
`void` | `clearAllSchedulingData()` Clear (delete!) all scheduling data - all `Job`s, `Trigger`s `Calendar`s.
`List<String>` | `getCalendarNames()` Get the names of all of the ``Calendar`` s in the `JobStore`.
`long` | `getEstimatedTimeToReleaseAndAcquireTrigger()` How long (in milliseconds) the `JobStore` implementation estimates that it will take to release a trigger and acquire a new one.
`List<String>` | `getJobGroupNames()` Get the names of all of the ``Job`` groups.
`Set<JobKey>` | `getJobKeys(GroupMatcher<JobKey> matcher)` Get the keys of all of the ``Job`` s that have the given group name.
`int` | `getNumberOfCalendars()` Get the number of ``Calendar`` s that are stored in the `JobsStore`.
`int` | `getNumberOfJobs()` Get the number of ``Job`` s that are stored in the `JobsStore`.
`int` | `getNumberOfTriggers()` Get the number of ``Trigger`` s that are stored in the `JobsStore`.
`Set<String>` | `getPausedTriggerGroups()`
`List<String>` | `getTriggerGroupNames()` Get the names of all of the ``Trigger`` groups.
`Set<TriggerKey>` | `getTriggerKeys(GroupMatcher<TriggerKey> matcher)` Get the names of all of the ``Trigger`` s that have the given group name.
`List<OperableTrigger>` | `getTriggersForJob(JobKey jobKey)` Get all of the Triggers that are associated to the given Job.
`Trigger.TriggerState` | `getTriggerState(TriggerKey triggerKey)` Get the current state of the identified ``Trigger``.
`void` | `initialize(ClassLoadHelper loadHelper, SchedulerSignaler signaler)` Called by the QuartzScheduler before the `JobStore` is used, in order to give the it a chance to initialize.
`boolean` | `isClustered()` Whether or not the `JobStore` implementation is clustered.
`void` | `pauseAll()` Pause all triggers - equivalent of calling `pauseTriggerGroup(group)` on every group.
`void` | `pauseJob(JobKey jobKey)` Pause the ``Job`` with the given name - by pausing all of its current `Trigger`s.
`Collection<String>` | `pauseJobs(GroupMatcher<JobKey> groupMatcher)` Pause all of the ``Job`s` in the given group - by pausing all of their `Trigger`s.
`void` | `pauseTrigger(TriggerKey triggerKey)` Pause the ``Trigger`` with the given key.
`Collection<String>` | `pauseTriggers(GroupMatcher<TriggerKey> matcher)` Pause all of the ``Trigger`s` in the given group.
`void` | `releaseAcquiredTrigger(OperableTrigger trigger)` Inform the `JobStore` that the scheduler no longer plans to fire the given `Trigger`, that it had previously acquired (reserved).
`boolean` | `removeCalendar(String calName)` Remove (delete) the ``Calendar`` with the given name.
`boolean` | `removeJob(JobKey jobKey)` Remove (delete) the ``Job`` with the given key, and any ``Trigger`` s that reference it.
`boolean` | `removeJobs(List<JobKey> jobKeys)`
`boolean` | `removeTrigger(TriggerKey triggerKey)` Remove (delete) the ``Trigger`` with the given key.
`boolean` | `removeTriggers(List<TriggerKey> triggerKeys)`
`boolean` | `replaceTrigger(TriggerKey triggerKey, OperableTrigger newTrigger)` Remove (delete) the ``Trigger`` with the given key, and store the new given one - which must be associated with the same job.
`void` | `resumeAll()` Resume (un-pause) all triggers - equivalent of calling `resumeTriggerGroup(group)` on every group.
`void` | `resumeJob(JobKey jobKey)` Resume (un-pause) the ``Job`` with the given key.
`Collection<String>` | `resumeJobs(GroupMatcher<JobKey> matcher)` Resume (un-pause) all of the ``Job`s` in the given group.
`void` | `resumeTrigger(TriggerKey triggerKey)` Resume (un-pause) the ``Trigger`` with the given key.
`Collection<String>` | `resumeTriggers(GroupMatcher<TriggerKey> matcher)` Resume (un-pause) all of the ``Trigger`s` in the given group.
`Calendar` | `retrieveCalendar(String calName)` Retrieve the given ``Trigger``.
`JobDetail` | `retrieveJob(JobKey jobKey)` Retrieve the ``JobDetail`` for the given ``Job``.
`OperableTrigger` | `retrieveTrigger(TriggerKey triggerKey)` Retrieve the given ``Trigger``.
`void` | `schedulerPaused()` Called by the QuartzScheduler to inform the `JobStore` that the scheduler has been paused.
`void` | `schedulerResumed()` Called by the QuartzScheduler to inform the `JobStore` that the scheduler has resumed after being paused.
`void` | `schedulerStarted()` Called by the QuartzScheduler to inform the `JobStore` that the scheduler has started.
`void` | `setInstanceId(String schedInstId)` Inform the `JobStore` of the Scheduler instance's Id, prior to initialize being invoked.
`void` | `setInstanceName(String schedName)` Inform the `JobStore` of the Scheduler instance's name, prior to initialize being invoked.
`void` | `setThreadPoolSize(int poolSize)` Tells the JobStore the pool size used to execute jobs
`void` | `shutdown()` Called by the QuartzScheduler to inform the `JobStore` that it should free up all of it's resources because the scheduler is shutting down.
`void` | `storeCalendar(String name, Calendar calendar, boolean replaceExisting, boolean updateTriggers)` Store the given ``Calendar``.
`void` | `storeJob(JobDetail newJob, boolean replaceExisting)` Store the given ``JobDetail``.
`void` | `storeJobAndTrigger(JobDetail newJob, OperableTrigger newTrigger)` Store the given ``JobDetail`` and ``Trigger``.
`void` | `storeJobsAndTriggers(Map<JobDetail,Set<? extends Trigger>> triggersAndJobs, boolean replace)`
`void` | `storeTrigger(OperableTrigger newTrigger, boolean replaceExisting)` Store the given ``Trigger``.
`boolean` | `supportsPersistence()`
`void` | `triggeredJobComplete(OperableTrigger trigger, JobDetail jobDetail, Trigger.CompletedExecutionInstruction triggerInstCode)` Inform the `JobStore` that the scheduler has completed the firing of the given `Trigger` (and the execution of its associated `Job` completed, threw an exception, or was vetoed), and that the ``JobDataMap`` in the given `JobDetail` should be updated if the `Job` is stateful.
`List<TriggerFiredResult>` | `triggersFired(List<OperableTrigger> triggers)` Inform the `JobStore` that the scheduler is now firing the given `Trigger` (executing its associated `Job`), that it had previously acquired (reserved).

Method Detail

### initialize

    void initialize(ClassLoadHelper loadHelper,
                    SchedulerSignaler signaler)
                    throws SchedulerConfigException

  Called by the QuartzScheduler before the `JobStore` is used, in order to give the it a chance to initialize.

  Throws:
    `SchedulerConfigException`

### schedulerStarted

    void schedulerStarted()
                          throws SchedulerException

  Called by the QuartzScheduler to inform the `JobStore` that the scheduler has started.

  Throws:
    `SchedulerException`

### schedulerPaused

    void schedulerPaused()

  Called by the QuartzScheduler to inform the `JobStore` that the scheduler has been paused.

### schedulerResumed

    void schedulerResumed()

  Called by the QuartzScheduler to inform the `JobStore` that the scheduler has resumed after being paused.

### shutdown

    void shutdown()

  Called by the QuartzScheduler to inform the `JobStore` that it should free up all of it's resources because the scheduler is shutting down.

### supportsPersistence

    boolean supportsPersistence()

### getEstimatedTimeToReleaseAndAcquireTrigger

    long getEstimatedTimeToReleaseAndAcquireTrigger()

  How long (in milliseconds) the `JobStore` implementation estimates that it will take to release a trigger and acquire a new one.

### isClustered

    boolean isClustered()

  Whether or not the `JobStore` implementation is clustered.

### storeJobAndTrigger

    void storeJobAndTrigger(JobDetail newJob,
                            OperableTrigger newTrigger)
                            throws ObjectAlreadyExistsException,
                                   JobPersistenceException

  Store the given ``JobDetail`` and ``Trigger``.

  Parameters:
    `newJob` - The `JobDetail` to be stored.
    `newTrigger` - The `Trigger` to be stored.
  Throws:
    `ObjectAlreadyExistsException` - if a `Job` with the same name/group already exists.
    `JobPersistenceException`

### storeJob

    void storeJob(JobDetail newJob,
                  boolean replaceExisting)
                  throws ObjectAlreadyExistsException,
                         JobPersistenceException

  Store the given ``JobDetail``.

  Parameters:
    `newJob` - The `JobDetail` to be stored.
    `replaceExisting` - If `true`, any `Job` existing in the `JobStore` with the same name & group should be over-written.
  Throws:
    `ObjectAlreadyExistsException` - if a `Job` with the same name/group already exists, and replaceExisting is set to false.
    `JobPersistenceException`

### storeJobsAndTriggers

    void storeJobsAndTriggers(Map<JobDetail,Set<? extends Trigger>> triggersAndJobs,
                              boolean replace)
                              throws ObjectAlreadyExistsException,
                                     JobPersistenceException

  Throws:
    `ObjectAlreadyExistsException`
    `JobPersistenceException`

### removeJob

    boolean removeJob(JobKey jobKey)
                      throws JobPersistenceException

  Remove (delete) the ``Job`` with the given key, and any ``Trigger`` s that reference it.

  If removal of the `Job` results in an empty group, the group should be removed from the `JobStore`'s list of known group names.

  Returns:
    `true` if a `Job` with the given name & group was found and removed from the store.
  Throws:
    `JobPersistenceException`

### removeJobs

    boolean removeJobs(List<JobKey> jobKeys)
                       throws JobPersistenceException

  Throws:
    `JobPersistenceException`

### retrieveJob

    JobDetail retrieveJob(JobKey jobKey)
                          throws JobPersistenceException

  Retrieve the ``JobDetail`` for the given ``Job``.

  Returns:
    The desired `Job`, or null if there is no match.
  Throws:
    `JobPersistenceException`

### storeTrigger

    void storeTrigger(OperableTrigger newTrigger,
                      boolean replaceExisting)
                      throws ObjectAlreadyExistsException,
                             JobPersistenceException

  Store the given ``Trigger``.

  Parameters:
    `newTrigger` - The `Trigger` to be stored.
    `replaceExisting` - If `true`, any `Trigger` existing in the `JobStore` with the same name & group should be over-written.
  Throws:
    `ObjectAlreadyExistsException` - if a `Trigger` with the same name/group already exists, and replaceExisting is set to false.
    `JobPersistenceException`
  See Also:
    `pauseTriggers(org.quartz.impl.matchers.GroupMatcher)`

### removeTrigger

    boolean removeTrigger(TriggerKey triggerKey)
                          throws JobPersistenceException

  Remove (delete) the ``Trigger`` with the given key.

  If removal of the `Trigger` results in an empty group, the group should be removed from the `JobStore`'s list of known group names.

  If removal of the `Trigger` results in an 'orphaned' `Job` that is not 'durable', then the `Job` should be deleted also.

  Returns:
    `true` if a `Trigger` with the given name & group was found and removed from the store.
  Throws:
    `JobPersistenceException`

### removeTriggers

    boolean removeTriggers(List<TriggerKey> triggerKeys)
                           throws JobPersistenceException

  Throws:
    `JobPersistenceException`

### replaceTrigger

    boolean replaceTrigger(TriggerKey triggerKey,
                           OperableTrigger newTrigger)
                           throws JobPersistenceException

  Remove (delete) the ``Trigger`` with the given key, and store the new given one - which must be associated with the same job.

  Parameters:
    `newTrigger` - The new `Trigger` to be stored.
  Returns:
    `true` if a `Trigger` with the given name & group was found and removed from the store.
  Throws:
    `JobPersistenceException`

### retrieveTrigger

    OperableTrigger retrieveTrigger(TriggerKey triggerKey)
                                    throws JobPersistenceException

  Retrieve the given ``Trigger``.

  Returns:
    The desired `Trigger`, or null if there is no match.
  Throws:
    `JobPersistenceException`

### checkExists

    boolean checkExists(JobKey jobKey)
                        throws JobPersistenceException

  Determine whether a `Job` with the given identifier already exists within the scheduler.

  Parameters:
    `jobKey` - the identifier to check for
  Returns:
    true if a Job exists with the given identifier
  Throws:
    `SchedulerException`
    `JobPersistenceException`

### checkExists

    boolean checkExists(TriggerKey triggerKey)
                        throws JobPersistenceException

  Determine whether a `Trigger` with the given identifier already exists within the scheduler.

  Parameters:
    `triggerKey` - the identifier to check for
  Returns:
    true if a Trigger exists with the given identifier
  Throws:
    `SchedulerException`
    `JobPersistenceException`

### clearAllSchedulingData

    void clearAllSchedulingData()
                                throws JobPersistenceException

  Clear (delete!) all scheduling data - all `Job`s, `Trigger`s `Calendar`s.

  Throws:
    `JobPersistenceException`

### storeCalendar

    void storeCalendar(String name,
                       Calendar calendar,
                       boolean replaceExisting,
                       boolean updateTriggers)
                       throws ObjectAlreadyExistsException,
                              JobPersistenceException

  Store the given ``Calendar``.

  Parameters:
    `calendar` - The `Calendar` to be stored.
    `replaceExisting` - If `true`, any `Calendar` existing in the `JobStore` with the same name & group should be over-written.
    `updateTriggers` - If `true`, any `Trigger`s existing in the `JobStore` that reference an existing Calendar with the same name with have their next fire time re-computed with the new `Calendar`.
  Throws:
    `ObjectAlreadyExistsException` - if a `Calendar` with the same name already exists, and replaceExisting is set to false.
    `JobPersistenceException`

### removeCalendar

    boolean removeCalendar(String calName)
                           throws JobPersistenceException

  Remove (delete) the ``Calendar`` with the given name.

  If removal of the `Calendar` would result in `Trigger`s pointing to non-existent calendars, then a `JobPersistenceException` will be thrown.

  *

  Parameters:
    `calName` - The name of the `Calendar` to be removed.
  Returns:
    `true` if a `Calendar` with the given name was found and removed from the store.
  Throws:
    `JobPersistenceException`

### retrieveCalendar

    Calendar retrieveCalendar(String calName)
                              throws JobPersistenceException

  Retrieve the given ``Trigger``.

  Parameters:
    `calName` - The name of the `Calendar` to be retrieved.
  Returns:
    The desired `Calendar`, or null if there is no match.
  Throws:
    `JobPersistenceException`

### getNumberOfJobs

    int getNumberOfJobs()
                        throws JobPersistenceException

  Get the number of ``Job`` s that are stored in the `JobsStore`.

  Throws:
    `JobPersistenceException`

### getNumberOfTriggers

    int getNumberOfTriggers()
                            throws JobPersistenceException

  Get the number of ``Trigger`` s that are stored in the `JobsStore`.

  Throws:
    `JobPersistenceException`

### getNumberOfCalendars

    int getNumberOfCalendars()
                             throws JobPersistenceException

  Get the number of ``Calendar`` s that are stored in the `JobsStore`.

  Throws:
    `JobPersistenceException`

### getJobKeys

    Set<JobKey> getJobKeys(GroupMatcher<JobKey> matcher)
                           throws JobPersistenceException

  Get the keys of all of the ``Job`` s that have the given group name.

  If there are no jobs in the given group name, the result should be an empty collection (not `null`).

  Throws:
    `JobPersistenceException`

### getTriggerKeys

    Set<TriggerKey> getTriggerKeys(GroupMatcher<TriggerKey> matcher)
                                   throws JobPersistenceException

  Get the names of all of the ``Trigger`` s that have the given group name.

  If there are no triggers in the given group name, the result should be a zero-length array (not `null`).

  Throws:
    `JobPersistenceException`

### getJobGroupNames

    List<String> getJobGroupNames()
                                  throws JobPersistenceException

  Get the names of all of the ``Job`` groups.

  If there are no known group names, the result should be a zero-length array (not `null`).

  Throws:
    `JobPersistenceException`

### getTriggerGroupNames

    List<String> getTriggerGroupNames()
                                      throws JobPersistenceException

  Get the names of all of the ``Trigger`` groups.

  If there are no known group names, the result should be a zero-length array (not `null`).

  Throws:
    `JobPersistenceException`

### getCalendarNames

    List<String> getCalendarNames()
                                  throws JobPersistenceException

  Get the names of all of the ``Calendar`` s in the `JobStore`.

  If there are no Calendars in the given group name, the result should be a zero-length array (not `null`).

  Throws:
    `JobPersistenceException`

### getTriggersForJob

    List<OperableTrigger> getTriggersForJob(JobKey jobKey)
                                            throws JobPersistenceException

  Get all of the Triggers that are associated to the given Job.

  If there are no matches, a zero-length array should be returned.

  Throws:
    `JobPersistenceException`

### getTriggerState

    Trigger.TriggerState getTriggerState(TriggerKey triggerKey)
                                         throws JobPersistenceException

  Get the current state of the identified ``Trigger``.

  Throws:
    `JobPersistenceException`
  See Also:
    `Trigger.TriggerState`

### pauseTrigger

    void pauseTrigger(TriggerKey triggerKey)
                      throws JobPersistenceException

  Pause the ``Trigger`` with the given key.

  Throws:
    `JobPersistenceException`
  See Also:
    `resumeTrigger(TriggerKey)`

### pauseTriggers

    Collection<String> pauseTriggers(GroupMatcher<TriggerKey> matcher)
                                     throws JobPersistenceException

  Pause all of the ``Trigger`s` in the given group.

  The JobStore should "remember" that the group is paused, and impose the pause on any new triggers that are added to the group while the group is paused.

  Throws:
    `JobPersistenceException`
  See Also:
    `#resumeTriggerGroup(String)`

### pauseJob

    void pauseJob(JobKey jobKey)
                  throws JobPersistenceException

  Pause the ``Job`` with the given name - by pausing all of its current `Trigger`s.

  Throws:
    `JobPersistenceException`
  See Also:
    `resumeJob(JobKey)`

### pauseJobs

    Collection<String> pauseJobs(GroupMatcher<JobKey> groupMatcher)
                                 throws JobPersistenceException

  Pause all of the ``Job`s` in the given group - by pausing all of their `Trigger`s.

  The JobStore should "remember" that the group is paused, and impose the pause on any new jobs that are added to the group while the group is paused.

  Throws:
    `JobPersistenceException`
  See Also:
    `#resumeJobGroup(String)`

### resumeTrigger

    void resumeTrigger(TriggerKey triggerKey)
                       throws JobPersistenceException

  Resume (un-pause) the ``Trigger`` with the given key.

  If the `Trigger` missed one or more fire-times, then the `Trigger`'s misfire instruction will be applied.

  Throws:
    `JobPersistenceException`
  See Also:
    `pauseTrigger(TriggerKey)`

### resumeTriggers

    Collection<String> resumeTriggers(GroupMatcher<TriggerKey> matcher)
                                      throws JobPersistenceException

  Resume (un-pause) all of the ``Trigger`s` in the given group.

  If any `Trigger` missed one or more fire-times, then the `Trigger`'s misfire instruction will be applied.

  Throws:
    `JobPersistenceException`
  See Also:
    `#pauseTriggers(String)`

### getPausedTriggerGroups

    Set<String> getPausedTriggerGroups()
                                       throws JobPersistenceException

  Throws:
    `JobPersistenceException`

### resumeJob

    void resumeJob(JobKey jobKey)
                   throws JobPersistenceException

  Resume (un-pause) the ``Job`` with the given key.

  If any of the `Job`'s`Trigger` s missed one or more fire-times, then the `Trigger`'s misfire instruction will be applied.

  Throws:
    `JobPersistenceException`
  See Also:
    `pauseJob(JobKey)`

### resumeJobs

    Collection<String> resumeJobs(GroupMatcher<JobKey> matcher)
                                  throws JobPersistenceException

  Resume (un-pause) all of the ``Job`s` in the given group.

  If any of the `Job` s had `Trigger` s that missed one or more fire-times, then the `Trigger`'s misfire instruction will be applied.

  Throws:
    `JobPersistenceException`
  See Also:
    `#pauseJobGroup(String)`

### pauseAll

    void pauseAll()
                  throws JobPersistenceException

  Pause all triggers - equivalent of calling `pauseTriggerGroup(group)` on every group.

  When `resumeAll()` is called (to un-pause), trigger misfire instructions WILL be applied.

  Throws:
    `JobPersistenceException`
  See Also:
    `resumeAll()`, `#pauseTriggers(String)`

### resumeAll

    void resumeAll()
                   throws JobPersistenceException

  Resume (un-pause) all triggers - equivalent of calling `resumeTriggerGroup(group)` on every group.

  If any `Trigger` missed one or more fire-times, then the `Trigger`'s misfire instruction will be applied.

  Throws:
    `JobPersistenceException`
  See Also:
    `pauseAll()`

### acquireNextTriggers

    List<OperableTrigger> acquireNextTriggers(long noLaterThan,
                                              int maxCount,
                                              long timeWindow)
                                              throws JobPersistenceException

  Get a handle to the next trigger to be fired, and mark it as 'reserved' by the calling scheduler.

  Parameters:
    `noLaterThan` - If > 0, the JobStore should only return a Trigger that will fire no later than the time represented in this value as milliseconds.
  Throws:
    `JobPersistenceException`
  See Also:
    `#releaseAcquiredTrigger(Trigger)`

### releaseAcquiredTrigger

    void releaseAcquiredTrigger(OperableTrigger trigger)

  Inform the `JobStore` that the scheduler no longer plans to fire the given `Trigger`, that it had previously acquired (reserved).

### triggersFired

    List<TriggerFiredResult> triggersFired(List<OperableTrigger> triggers)
                                           throws JobPersistenceException

  Inform the `JobStore` that the scheduler is now firing the given `Trigger` (executing its associated `Job`), that it had previously acquired (reserved).

  Returns:
    may return null if all the triggers or their calendars no longer exist, or if the trigger was not successfully put into the 'executing' state. Preference is to return an empty list if none of the triggers could be fired.
  Throws:
    `JobPersistenceException`

### triggeredJobComplete

    void triggeredJobComplete(OperableTrigger trigger,
                              JobDetail jobDetail,
                              Trigger.CompletedExecutionInstruction triggerInstCode)

  Inform the `JobStore` that the scheduler has completed the firing of the given `Trigger` (and the execution of its associated `Job` completed, threw an exception, or was vetoed), and that the ``JobDataMap`` in the given `JobDetail` should be updated if the `Job` is stateful.

### setInstanceId

    void setInstanceId(String schedInstId)

  Inform the `JobStore` of the Scheduler instance's Id, prior to initialize being invoked.

  Since:
    1.7

### setInstanceName

    void setInstanceName(String schedName)

  Inform the `JobStore` of the Scheduler instance's name, prior to initialize being invoked.

  Since:
    1.7

### setThreadPoolSize

    void setThreadPoolSize(int poolSize)

  Tells the JobStore the pool size used to execute jobs

  Parameters:
    `poolSize` - amount of threads allocated for job execution
  Since:
    2.0

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Copyright 2001-2016, Terracotta, Inc.