public class Persistit extends Object
Create and manage the runtime environment for a Persistit™ database. To use Persistit an application
initialize()
methods to set up a configuration
and initialize the memory structures and background threadsExchange
and Transaction
instances to perform work,close()
methods to gracefully release all
memory resources and shut down the background threads.close()
when
finished with it. Persistit's background threads are not daemon threads, and
an application that does not call close
therefore will not exit
normally.
Persistit takes a large variety of configuration properties. These are
specified through the initalize
method.
Modifier and Type | Class and Description |
---|---|
static class |
Persistit.FatalErrorException
An Exception created when Persistit detects a fatal internal error such
as database corruption.
|
Modifier and Type | Field and Description |
---|---|
static boolean |
BIG_ENDIAN
Determines whether multi-byte integers will be written in little- or
big-endian format.
|
static String |
COPYRIGHT
The copyright notice
|
static int |
MAX_POOLED_EXCHANGES
Maximum number of Exchanges that will be held in an internal pool.
|
static String |
VERSION
This version of Persistit
|
Constructor and Description |
---|
Persistit()
Construct a hollow Persistit instance.
|
Persistit(Configuration configuration)
Construct a Persistit instance with the supplied
Configuration and then initialize it. |
Persistit(Properties properties)
Construct a Persistit instance with a
Configuration derived
from the supplied Properties instance. |
Modifier and Type | Method and Description |
---|---|
void |
checkAllVolumes()
Convenience method that performs an integrity check on all open
Volume s and reports detailed results to
System.out . |
CheckpointManager.Checkpoint |
checkpoint()
Force a new Checkpoint and wait for it to be written.
|
void |
checkSuspended()
Waits until updates are no longer suspended.
|
void |
close()
Close the Persistit Journal and all
Volume s. |
void |
close(boolean flush)
Close the Persistit Journal and all
Volume s. |
void |
copyBackPages()
Copy back all pages from the journal to their host Volumes.
|
static String |
copyright()
Returns the copyright notice for this product
|
void |
crash()
Abruptly stop (using
Thread.stop() ) the writer and collector
processes. |
Volume |
createTemporaryVolume()
Create a temporary volume.
|
Volume |
createTemporaryVolume(int pageSize)
Create a temporary volume.
|
boolean |
deleteVolume(String volumeName)
Delete a volume currently loaded volume and remove it from the list
returned by
getVolumes() . |
long |
elapsedTime()
The number of milliseconds since the log was opened.
|
boolean |
flush()
Write all pending updates to the underlying OS file system.
|
void |
force()
Request OS-level file synchronization for all open files managed by
Persistit.
|
AlertMonitor |
getAlertMonitor() |
long |
getAvailableHeap()
Available heap space at the time this Persistit instance was created.
|
CoderManager |
getCoderManager()
Returns the current CoderManager.
|
Configuration |
getConfiguration() |
CheckpointManager.Checkpoint |
getCurrentCheckpoint() |
long |
getCurrentTimestamp() |
JoinPolicy |
getDefaultJoinPolicy() |
SplitPolicy |
getDefaultSplitPolicy() |
Transaction.CommitPolicy |
getDefaultTransactionCommitPolicy()
This property can be configured with the configuration property
"txnpolicy".
|
Exchange |
getExchange(String volumeName,
String treeName,
boolean create)
|
Exchange |
getExchange(Volume volume,
String treeName,
boolean create)
|
com.persistit.JournalManager |
getJournalManager() |
Volume |
getLockVolume() |
LogBase |
getLogBase() |
Management |
getManagement()
Returns an implementation of the
Management interface. |
Object |
getPersistitGuiContainer()
Returns the
java.awt.Container object that contains the
diagnostic GUI, if it is open. |
PersistitLogger |
getPersistitLogger() |
Properties |
getProperties()
Deprecated.
|
String |
getProperty(String key)
Deprecated.
|
RecoveryManager |
getRecoveryManager() |
List<Tree> |
getSelectedTrees(TreeSelector selector)
|
SessionId |
getSessionId()
Return this thread's SessionId.
|
Volume |
getSystemVolume()
Returns the designated system volume.
|
Transaction |
getTransaction()
Get the
Transaction object for the current thread. |
Volume |
getVolume(String name)
Looks up a
Volume by name or path. |
List<Volume> |
getVolumes()
|
void |
initialize()
Initialize Persistit using the
Configuration supplied by the
setConfiguration(Configuration) method or derived from
properties supplied by setProperties(Properties) or
setPropertiesFromFile(String) . |
void |
initialize(Configuration configuration)
Deprecated.
|
void |
initialize(Properties properties)
Deprecated.
|
void |
initialize(String propertiesFileName)
Deprecated.
|
boolean |
isClosed()
Indicates whether this instance of Persistit has been closed.
|
boolean |
isFatal() |
boolean |
isInitialized()
Indicates whether this instance has been initialized.
|
boolean |
isReadRetryEnabled()
Indicates whether Persistit will retry read any operation that fails due
to an IOException.
|
boolean |
isShutdownSuspended()
Indicates whether Persistit will suspend its shutdown activities on
invocation of
close() . |
boolean |
isUpdateSuspended()
Indicates whether Persistit is suspending all updates.
|
Volume |
loadVolume(String vstring)
Look up, load and/or creates a volume based on a String-valued
specification.
|
Volume |
loadVolume(VolumeSpecification volumeSpec)
Look up, load and/or creates a volume based on a
VolumeSpecification . |
static void |
main(String[] args)
Perform various utility functions.
|
void |
releaseExchange(Exchange exchange)
Releases an
Exchange to the internal pool. |
void |
releaseExchange(Exchange exchange,
boolean secure)
Releases an
Exchange to the internal pool. |
void |
setCoderManager(CoderManager coderManager)
|
void |
setConfiguration(Configuration configuration)
Receive the supplied
Configuration which will be used to
control the creation of a functional Persistit within the
initialize() method. |
void |
setDefaultJoinPolicy(JoinPolicy policy)
Replace the current default
SplitPolicy . |
void |
setDefaultSplitPolicy(SplitPolicy policy)
Replace the current default
SplitPolicy . |
void |
setDefaultTransactionCommitPolicy(String policyName)
Set the current default transaction commit property by name.
|
void |
setDefaultTransactionCommitPolicy(Transaction.CommitPolicy policy)
Set the current default transaction commit property.
|
void |
setPersistitLogger(PersistitLogger logger)
Replaces the current logger implementation.
|
void |
setProperties(Properties properties)
Sets a
Configuration derived from the supplied
Properties . |
void |
setPropertiesFromFile(String propertiesFileName)
Sets a
Configuration derived from Properties
read from the supplied file name. |
void |
setSessionId(SessionId sessionId)
Modify this thread's SessionId.
|
void |
setShutdownSuspended(boolean suspended)
Determines whether Persistit will suspend its shutdown activities on
invocation of
close() . |
void |
setUpdateSuspended(boolean suspended)
Controls whether Persistit will suspend all Threads that attempt to
update any Volume.
|
void |
setupGUI(boolean suspendShutdown)
Attempts to open the diagnostic GUI that displays some useful information
about Persistit's internal state.
|
void |
shutdownGUI()
Closes the diagnostic GUI if it previously has been opened.
|
long |
startTime()
The time at which the log was started.
|
String |
substituteProperties(String text,
Properties properties)
Deprecated.
|
String |
transactionReport(int max)
Reports status of the
max longest-running transactions, in
order from oldest to youngest. |
static String |
version()
Returns the version identifier for this version of Persistit™
|
public static final String VERSION
public static final String COPYRIGHT
public static final boolean BIG_ENDIAN
true
in all current
builds.public static final int MAX_POOLED_EXCHANGES
public Persistit()
Configuration
through one of the methods
setConfiguration(Configuration)
,
setProperties(Properties)
or
setPropertiesFromFile(String)
. The instance must then be started
by the initialize()
method.public Persistit(Configuration configuration) throws PersistitException
Configuration
and then initialize it. The code
Persistit db = new Persistit(configuration);
is equivalent to
Persistit db = new Persistit();
db.setConfiguration(configuration);
db.intialize();
configuration
- the ConfigurationPersistitException
setConfiguration(Configuration)
public Persistit(Properties properties) throws PersistitException
Configuration
derived
from the supplied Properties
instance. The code
Persistit db = new Persistit(properties);
is equivalent to
Persistit db = new Persistit();
db.setProperties(properties);
db.intialize();
properties
- the PropertiesPersistitException
setProperties(Properties)
public void setConfiguration(Configuration configuration)
Configuration
which will be used to
control the creation of a functional Persistit
within the
initialize()
method. The configuration may only be set once.configuration
- IllegalStateException
- if the Configuration
has already been setpublic void setPropertiesFromFile(String propertiesFileName) throws PersistitException
Configuration
derived from Properties
read from the supplied file name.propertiesFileName
- path to properties filePersistitException
- if the properties file is invalidIllegalStateException
- if the Configuration
has already been setsetConfiguration(Configuration)
public void setProperties(Properties properties)
Configuration
derived from the supplied
Properties
.properties
- the Properties from which to build a
Configuration
IllegalStateException
- if the Configuration
has already been setsetConfiguration(Configuration)
public void initialize() throws PersistitException
Initialize Persistit using the Configuration
supplied by the
setConfiguration(Configuration)
method or derived from
properties supplied by setProperties(Properties)
or
setPropertiesFromFile(String)
.
If no configuration has been set, this method reverts to its legacy
behavior which is to load a configuration from a default properties file.
The name of this file is supplied by the system property
com.persistit.properties
. If that property is not specified,
the default file path is ./persistit.properties
in the
current working directory. If Persistit has already been initialized,
this method does nothing. This method is thread-safe; if multiple threads
concurrently attempt to invoke this method, one of the threads will
actually perform the initialization and the other threads will do
nothing.
Note that Persistit starts non-daemon threads that will keep a JVM from
exiting until close()
is invoked. This is to ensure that all
pending updates are written before the JVM exit.
PersistitException
IOException
Exception
@Deprecated public void initialize(String propertiesFileName) throws PersistitException
Initialize Persistit using the supplied properties file path. If Persistit has already been initialized, this method does nothing. This method is thread-safe; if multiple threads concurrently attempt to invoke this method, one of the threads will actually perform the initialization and the other threads will do nothing.
Note that Persistit starts non-daemon threads that will keep a JVM from
exiting until close()
is invoked. This is to ensure that all
pending updates are written before the JVM exit.
This method is deprecated. Applications should instead call
setPropertiesFromFile(propertiesFileName);
initialize();
propertiesFileName
- The path to the properties file.PersistitException
IOException
@Deprecated public void initialize(Properties properties) throws PersistitException
Initialize Persistit using the supplied java.util.Properties
instance. Applications can use this method to supply computed Properties
rather than reading them from a file. If Persistit has already been
initialized, this method does nothing. This method is thread-safe; if
multiple threads concurrently attempt to invoke this method, one of the
threads will actually perform the initialization and the other threads
will do nothing.
Note that Persistit starts non-daemon threads that will keep a JVM from
exiting until close()
is invoked. This is to ensure that all
pending updates are written before the JVM exit.
This method is deprecated. Applications should instead call
setProperties(properties);
initialize();
properties
- The Properties
instance from which to build the
configurationPersistitException
IOException
@Deprecated public void initialize(Configuration configuration) throws PersistitException
Initialize Persistit using the supplied Configuration
. If
Persistit has already been initialized, this method does nothing. This
method is thread-safe; if multiple threads concurrently attempt to invoke
this method, one of the threads will actually perform the initialization
and the other threads will do nothing.
Note that Persistit starts non-daemon threads that will keep a JVM from
exiting until close()
is invoked. This is to ensure that all
pending updates are written before the JVM exit.
This method is deprecated. Applications should instead call
setConfiguration(configuration);
initialize();
configuration
- The Configuration
from which to initialize
PersistitPersistitException
IOException
public Exchange getExchange(Volume volume, String treeName, boolean create) throws PersistitException
Returns an Exchange
for the specified Volume
and the Tree
specified by the supplied name. This method
optionally creates a new Tree
. If the create
parameter is false and a Tree
by the specified name does not
exist, this constructor throws a
TreeNotFoundException
.
This method uses an Exchange
from an internal pool if one is
available; otherwise it creates a new Exchange
. When the
application no longer needs the Exchange
returned by this
method, it should return it to the pool by invoking
releaseExchange(com.persistit.Exchange)
so that it can be reused.
volume
- The VolumetreeName
- The tree namecreate
- true
to create a new Tree if one by the specified
name does not already exist.PersistitException
public Exchange getExchange(String volumeName, String treeName, boolean create) throws PersistitException
Returns an Exchange
for the Tree
specified by
treeName within the Volume
specified by volumeName
.
This method optionally creates a new Tree
. If the
create
parameter is false and a Tree
by the
specified name does not exist, this constructor throws a
TreeNotFoundException
.
The volumeNameVolume
. The name matches if either (a) the
Volume
has an optional alias that is equal to the supplied
name, or (b) if the supplied name matches a substring of the
Volume
's pathname. If there is not unique match for the name
you supply, this method throws a
VolumeNotFoundException
.
This method uses an Exchange
from an internal pool if one is
available; otherwise it creates a new Exchange
. When the
application no longer needs the Exchange
returned by this
method, it should return it to the pool by invoking
releaseExchange(com.persistit.Exchange)
so that it can be reused.
volumeName
- The volume name that either matches the alias or a partially
matches the pathname of exactly one open Volume
.treeName
- The tree namecreate
- true
to create a new Tree if one by the specified
name does not already exist.PersistitException
public void releaseExchange(Exchange exchange)
Releases an Exchange
to the internal pool. A subsequent
invocation of getExchange(com.persistit.Volume, java.lang.String, boolean)
may reuse this Exchange
.
An application that gets an Exchange
through the
getExchange(com.persistit.Volume, java.lang.String, boolean)
method should release it through this method.
An attempt to release the Exchange
if it is already in the
pool results in an IllegalStateException
.
This method clears the key and value fields. Use the
releaseExchange(Exchange, boolean)
method to clear all state
information if this Exchange
may subsequently be used by
another untrusted thread.
exchange
- The Exchange
to release to the pool. If
null
, this method returns silently.IllegalStateException
public void releaseExchange(Exchange exchange, boolean secure)
Releases an Exchange
to the internal pool. A subsequent
invocation of getExchange(com.persistit.Volume, java.lang.String, boolean)
may reuse this Exchange
.
An application that gets an Exchange
through the
getExchange(com.persistit.Volume, java.lang.String, boolean)
method should release it through this method.
An attempt to release the Exchange
if it is already in the
pool results in an IllegalStateException
.
This method optionally clears all state information in the
Exchange
so that no residual information in the
Exchange
can be obtained by a different, untrusted thread.
In a closed configuration in which there is only one application, it is
faster to avoid clearing the byte arrays used in representing the state
of this Exchange
by passing false
as the value
of the secure
flag.
exchange
- The Exchange
to release to the pool. If
null
this method returns silently.secure
- true
to clear all state information;
false
to leave the state unchanged.IllegalStateException
public List<Volume> getVolumes()
List
of all Volume
s currently being managed by this
Persistit instance. Volumes are specified by the properties used in
initializing Persistit.public List<Tree> getSelectedTrees(TreeSelector selector) throws PersistitException
List
of Tree
s determined by the supplied
TreeSelector
. This method enumerates all Trees in all open
Volumes and selects those which satisfy the TreeSelector. If the Volume
has a Volume-only selector (no tree pattern was specified), then this
method adds the Volume's directory Tree to the list.selector
- PersistitException
public Volume loadVolume(String vstring) throws PersistitException
VolumeSpecification
for the specification
String format.
If a Volume has already been loaded having the same ID or name, this method returns that Volume. Otherwise it tries to open or create a volume on disk (depending on the volume specification) and returns that.
vstring
- Volume specification stringVolume
PersistitException
public Volume loadVolume(VolumeSpecification volumeSpec) throws PersistitException
VolumeSpecification
. If a Volume has already been
loaded having the same ID or name, this method returns that Volume.
Otherwise it tries to open or create a volume on disk (depending on the
volume specification) and returns that.volumeSpec
- The VolumeSpecificationVolume
PersistitException
public Volume createTemporaryVolume() throws PersistitException
tmpvolpagesize
. The default value is determined by
the BufferPool
having the largest page size.
The backing store file for a temporary volume is created in the directory
specified by the configuration property tmpvoldir
, or if
unspecified, the system temporary directory..Volume
.PersistitException
public Volume createTemporaryVolume(int pageSize) throws PersistitException
tmpvoldir
, or if
unspecified, the system temporary directory.pageSize
- The page size for the volume. Must be one of 1024, 2048, 4096,
8192 or 16384, and the volume will be usable only if there are
buffers of the specified size in the BufferPool
.Volume
.PersistitException
public boolean deleteVolume(String volumeName) throws PersistitException
getVolumes()
.volumeName
- the Volume to deletetrue
if the volume was previously loaded and has
been successfully deleted.PersistitException
public Management getManagement()
Management
interface. This
implementation is a singleton; the first invocation of this method will
create an instance; subsequent invocations will return the same instance.Management
from
which system management services can be obtained.public static String copyright()
public static String version()
public long startTime()
public long elapsedTime()
public Configuration getConfiguration()
@Deprecated public Properties getProperties()
@Deprecated public String getProperty(String key)
@Deprecated public String substituteProperties(String text, Properties properties)
public Volume getVolume(String name)
Looks up a Volume
by name or path. The supplied name must match
only one of the open volumes. If it matches none of the volumes, or if
there are multiple volumes with matching names, then this method returns
null
.
The supplied name can match a volume in one of two ways:
name
- Name that identifies a volume by matching either its alias (if
it has one) or a substring of its file name.Volume
, or null if there is no unique
open Volume that matches the supplied partialName
.public Volume getSystemVolume() throws VolumeNotFoundException
Returns the designated system volume. The system volume contains the
class index and other structural information. It is specified by the
sysvolume
property with a default value of "_system".
This method handles a configuration with exactly one volume in a special
way. If the sysvolume
property is unspecified and there is
exactly one volume, then this method returns that volume volume as the
system volume even if its name does not match the default
sysvolume
property. This eliminates the need to specify a
system volume property for configurations having only one volume.
Volume
VolumeNotFoundException
- if the volume was not foundpublic Volume getLockVolume() throws PersistitException
PersistitException
public SplitPolicy getDefaultSplitPolicy()
SplitPolicy
that will by applied by default to newly
created or allocated Exchange
s.public JoinPolicy getDefaultJoinPolicy()
JoinPolicy
that will by applied by default to newly
created or allocated Exchange
s.public void setDefaultSplitPolicy(SplitPolicy policy)
SplitPolicy
.policy
- The JoinPolicy
that will by applied by default to
newly created or allocated Exchange
s.public void setDefaultJoinPolicy(JoinPolicy policy)
SplitPolicy
.policy
- The JoinPolicy
that will by applied by default to
newly created or allocated Exchange
s.public boolean isInitialized()
true
if this Persistit has been initialized.public boolean isClosed()
true
if Persistit has been closed.public boolean isReadRetryEnabled()
true
, Persistit will repeatedly retry the read
operation until the timeout value for the current operation expires. By
default this property is true
. Use the
com.persistit.readretry property to disable it.true
to retry a read operation that fails due to an
IOException.public CheckpointManager.Checkpoint getCurrentCheckpoint()
PersistitInterruptedException
public CheckpointManager.Checkpoint checkpoint() throws PersistitException
null
.PersistitInterruptedException
PersistitException
public void copyBackPages() throws Exception
Exception
public boolean isFatal()
public String transactionReport(int max)
max
longest-running transactions, in
order from oldest to youngest.max
- max
longest-running transactions, in
order from oldest to youngest, reported as a String with one line
per transaction.public void close() throws PersistitException
Close the Persistit Journal and all Volume
s. This method is
equivalent to close(true)
.
public void close(boolean flush) throws PersistitException
Close the Persistit Journal and all Volume
s. This method does
nothing and returns false
if Persistit is currently not in
the initialized state. This method is threadsafe; if multiple threads
concurrently attempt to close Persistit, only one close operation will
actually take effect.
The flush
determines whether this method will pause to flush
all pending updates to disk before shutting down the system. If
flush
is true
and many updated pages need to be
written, the shutdown process may take a significant amount of time.
However, upon restarting the system, all updates initiated before the
call to this method will be reflected in the B-Tree database. This is the
normal mode of operation.
When flush
is false this method returns quickly, but without
writing remaining dirty pages to disk. The result after restarting
Persistit will be valid, internally consistent B-Trees; however, recently
applied updates may be missing.
Note that Persistit starts non-daemon threads that will keep a JVM from
exiting until you close Persistit. This is to ensure that all pending
updates are written before the JVM exits. Therefore the recommended
pattern for initializing, using and then closing Persistit is:
This pattern ensures that Persistit is closed properly and
all threads terminated even if the application code throws an exception
or error.
try
{
Persistit.initialize();
... do work
}
finally
{
Persisit.close();
}
flush
- true
to ensure all dirty pages are written to
disk before shutdown completes; false
to enable
fast (but incomplete) shutdown.PersistitException
IOException
PersistitException
IOException
public void crash()
Thread.stop()
) the writer and collector
processes. This method should be used only by tests.public boolean flush() throws PersistitException
PersistitException
IOException
public void force() throws PersistitException
flush()
to
ensure (within the capabilities of the host operating system) that all
database updates have actually been written to disk.IOException
PersistitException
public void checkSuspended() throws PersistitInterruptedException
setUpdateSuspended(boolean)
method controls whether update operations are
currently suspended.PersistitInterruptedException
public SessionId getSessionId()
public void setSessionId(SessionId sessionId)
sessionId
- public Transaction getTransaction()
Transaction
object for the current thread. The
Transaction
object lasts for the life of the thread. See
Transaction
for more information on how to use
Persistit's transaction facilities.Transaction
object.public Transaction.CommitPolicy getDefaultTransactionCommitPolicy()
public void setDefaultTransactionCommitPolicy(Transaction.CommitPolicy policy)
Transaction.commit()
. Note that
Transaction.commit(CommitPolicy)
permits control on a
per-transaction basis. The supplied policy value may not be
null
.policy
- The policy.public void setDefaultTransactionCommitPolicy(String policyName)
Transaction.commit()
. Note
that Transaction.commit(CommitPolicy)
permits control on a
per-transaction basis. The supplied policy value must be one of "HARD",
"GROUP" or "SOFT".policyName
- The policy name: "SOFT", "HARD" or "GROUP"public long getCurrentTimestamp()
public Object getPersistitGuiContainer()
java.awt.Container
object that contains the
diagnostic GUI, if it is open. Otherwise this method returns null.
The caller must cast the returned Object to Container. Persistit is
designed to avoid loading Swing or AWT classes in the event no GUI is
desired in order to minimize memory usage and startup time.java.awt.Container
, or
null if no diagnostic UI is open.public void setCoderManager(CoderManager coderManager)
coderManager
- public CoderManager getCoderManager()
CoderManager
.public LogBase getLogBase()
public long getAvailableHeap()
MemoryUsage.getMax()
method of
MemoryMXBean.getHeapMemoryUsage()
at the time this Persistit
instance was created, i.e., before allocation of buffer pools and other
data structures.public RecoveryManager getRecoveryManager()
public com.persistit.JournalManager getJournalManager()
public AlertMonitor getAlertMonitor()
public void setPersistitLogger(PersistitLogger logger)
logger
- The new logger implementationDefaultPersistitLogger
,
com.persistit.logging.JDK14LoggingAdapter
,
com.persistit.logging.Log4JAdapter
public PersistitLogger getPersistitLogger()
public void checkAllVolumes() throws PersistitException
Volume
s and reports detailed results to
System.out
.PersistitException
public void setupGUI(boolean suspendShutdown) throws IllegalAccessException, InstantiationException, ClassNotFoundException, RemoteException
suspendShutdown
- If true
, sets the shutdown suspend flag. Setting
this flag suspends the close()
method to permit
continued use of the diagnostic GUI.ClassNotFoundException
IllegalAccessException
InstantiationException
RemoteException
public void shutdownGUI()
public boolean isShutdownSuspended()
close()
. This flag is intended for use by management
tools that need to keep Persistit open even when the application has
requested it to close so that the final state of the Persistit
environment can be examined.true
if Persistit will wait when attempting to
close; false
if the close
operation
will not be suspended.public void setShutdownSuspended(boolean suspended)
close()
. This flag is intended for use by management
tools that need to keep Persistit open even when the application has
requested it to close so that the final state of the Persistit
environment can be examined.suspended
- true
to specify that Persistit will wait when
attempting to close; otherwise false
.public boolean isUpdateSuspended()
true
if all updates are suspended; otherwise
false
.public void setUpdateSuspended(boolean suspended)
suspended
- true
to suspend all updates; false
to enable updates.public static void main(String[] args) throws Exception
args
- Exception
Copyright © 2025 Open Identity Platform Community. All rights reserved.