Home Documentation Tracker Download

Configuration

Introduction

CloudStore can be configured using multiple properties-files. Many settings can be specified on multiple levels:

  • globally (per user)
  • per directory
  • per file

The more specific level can override individual settings otherwise inherited from the parent's configuration.

Every property file is optional. If it does not exist, all settings are inherited. If it does exist, only those properties contained in the file are overriden. All properties not contained in the file are still inherited. Inheritance is thus applicable on every individual property.

Creations, modifications and deletions of properties files are detected during runtime (pretty immediately). Note, that this detection is based on the files' timestamps. Since most file systems have a granularity of 1 second (some even 2) for the last-modified-timestamp, multiple modifications in the same second might not be detected.

Global configuration

The global configuration is named cloudstore.properties and it is normally located in ${user.home}/.cloudstore/ but this path might be overridden using the system property cloudstore.configDir or the environment variable cloudstore_configDir. The system property has higher priority and thus overrides the environment variable (if both are set).

Configuration per directory or per file

Additionally, every directory can optionally contain the following files:

  1. .cloudstore.properties
  2. .cloudstore.local.properties
  3. cloudstore.properties (deprecated!)
  4. .${anyFileName}.cloudstore.properties (deprecated!)
  5. ${anyFileName}.cloudstore.properties (deprecated!)

The files 1. and 2. are applicable to the entire directory and all sub-directories and files in it.

The file 2. is excluded from the synchronisation.

The file 3. is deprecated and will be removed, soon, because it is bad for performance to test for the existence of so many files. And there’s no necessity for it.

The files 3. and 4. are applicable only to the file ${anyFileName}. Thus, if you want to set special behaviour for the file example.db only, you can create the file .example.db.cloudstore.properties in the same directory. This is not practical and therefore it’s now deprecated, too. We may add a replacement working with name patterns (or regular expressions) applying to multiple files, but at the moment, this is not yet planned. Please let us know, if you use this feature and need it. Otherwise we’re just going to drop this without a replacement.

Configuration settings

The following property keys can be used to configure the behaviour of CloudStore:

ignore[SSS].namePattern or ignore[SSS].nameRegex

Files (or directories) can be ignored by specifying so-called ignore-rules. In every configuration file, zero or more such rules can be specified. Multiple rules are differentiated using an alphanumeric identifier inbetween square brackets, like in the following example:

ignore[backup-file].namePattern = *.bak
ignore[25af5db5].nameRegex = [a-z]\d*\.jpg
ignore[25af5db5].enabled = false
ignore[Xe3k-4Ldp].namePattern = ~*

If a file matches an ignore-rule (that is enabled), this file is neither synchronised nor touched in any other way by CloudStore.

Each ignore-rule has the following properties:

namePattern

A rule like “ignore[99].namePattern” specifies a shell pattern, supporting the wild-cards '*' and '?' as well as ranges like '[axz]' or '[a-z]'.

'*' means zero or more arbitrary characters.

'?' matches exactly one arbitrary character.

'[acg]' matches exactly one character being 'a', 'c' or 'g'. It does not match 'b'!

'[a-d]' matches exactly one character that is one of 'a', 'b', 'c' or 'd'.

If a simple shell pattern is not powerful enough to formulate an ignore-rule, you might want to use a regular expression instead (see below).

Note that the pattern “*.jpg” matches “TREE.JPG”, too, if case-sensitivity is not explicitly enabled (see below).

nameRegex

A rule like “ignore[99].nameRegex” specifies a regular expression matching the entire non-qualified file name.

If both “ignore[99].namePattern” and “ignore[99].nameRegex” are specified, the “namePattern” is ignored. The property “nameRegex” has a higher priority overruling “namePattern”.

Note, that it is not sufficient, if the file name contains a part matching this pattern. The entire file name must be matched. For example, the rule “tree\.jpg” does not match the file name “large_tree.jpg”. Using '^' (start) or '$' (end) is thus not necessary.

'.*\.bak' matches every file whose name ends on “.bak”. Please note that you must escape the dot (i.e. write “\.”), if you really mean the dot, because otherwise “.” (without the escaping “\”) is a meta-character matching every possible character.

caseSensitive

By default, every pattern or reg-ex is case-insensitive. This means, for example the pattern “*.jpg” matches the file “TREE.JPG”, too. If you do not want this, you must enable the “caseSensitive” property by specifying “ignore[99].caseSensitive=true”.

enabled

By default, every ignore-rule is enabled. Obviously, it does not make much sense to declare a disabled rule, in the first place. However, it is a common situation that you might want to disable a rule in a sub-directory that would otherwise be inherited from the parent-directory.

In this case, simply add the following to your sub-directory’s cloudstore.properties:

ignore[99].enabled=false

Of course, you likely have to replace “99” by the index of the rule you want to disable.

fileWriteStrategy

This strategy controls how and when a destination file is written. There are the following possible values:

  • directAfterTransfer (default)
  • directDuringTransfer
  • replaceAfterTransfer

So, if you want to switch to the strategy replaceAfterTransfer, you have to write the following into one of the .cloudstore.properties files:

fileWriteStrategy = replaceAfterTransfer

And here's what these strategies actually mean:

directAfterTransfer

Write directly into the destination file after all blocks have been transferred. During transfer, the destination file is not touched.

This strategy requires as much temporary space in the destination file system as blocks are transferred: The maximum total space requirement is thus twice the file size (old file + all blocks).

This is the default strategy (since CloudStore version 0.9.3).

directDuringTransfer

Write each block directly into the destination file immediately when it was transferred. Don't wait for all other blocks.

In contrast to directAfterTransfer this may leave the destination file in an inconsistent state for hours or even days - as long as the transfer takes.

However, this strategy requires the least space in the file system: Only once the file size. There are no temporary files involved and thus no additional temporary space is required.

replaceAfterTransfer

Similar to directAfterTransfer, but write a new file and then switch the files (delete the old file and rename the new file).

This strategy is the safest concerning consistency, but requires the most temporary space in the destination file system: The maximum total space requirement is a bit more than twice the file size (old file + blocks not yet written to new file + partial new file). Because the blocks are immediately deleted when written to the (partial) new file and the new file is growing while blocks are deleted (it doesn't have the final size immediately), the required space is not 3 times the size, but - as said - only a bit more than twice the size.

socket.connectTimeout

This is the maximum time in milliseconds allowed for establishing a socket connection. If the TCP handshake is not done within this time, an exception is thrown.

The default value is "60000" (1 minute).

This property can only be set in the global configuration (in ${user.home}/.cloudstore/cloudstore.properties).

It is possible to override the setting using the system property cloudstore.socket.connectTimeout.

socket.readTimeout

This is the maximum time in milliseconds the socket waits for incoming data. Thus, the server must be capable of processing and replying within this time.

Note, though, that there are long-running operations, which the server cannot guarantee to be done in a short time (e.g. re-indexing an extremely huge repository). For these, the server will throw a DeferredCompletionException which is transferred to the client instead of the real response. The client can (and should) then repeat the request.

How long the server waits before throwing this DeferredCompletionException, is configurable via the deferrableExecutor.timeout (see below). The socket.readTimeout must be longer than this deferrableExecutor.timeout!

The default value is "300000" (5 minutes).

This property can only be set in the global configuration (in ${user.home}/.cloudstore/cloudstore.properties).

It is possible to override the setting using the system property cloudstore.socket.readTimeout.

deferrableExecutor.timeout

TODO document this!

deferrableExecutor.expiryPeriod

TODO document this!

transientRepoPassword.validityPeriod

TODO document this!

The default value is "3600000" (1 hour).

transientRepoPassword.renewalPeriod

TODO document this!

The default value is "1800000" (30 minutes).

transientRepoPassword.earlyRenewalPeriod

TODO document this!

The default value is "900000" (15 minutes).

transientRepoPassword.expiryTimerPeriod

TODO document this!

The default value is "60000" (1 minute).

updater.downgrade

TODO document this!

updater.enabled

Controls whether the updater is enabled. The updater periodically checks the version on the server and compares it with the version installed locally. If the server's version is newer, it performs an automatic online-update.

The default value is "true".

It is highly recommended to keep this default value, but if you want to make sure that your CloudStore installation never connects to our servers (some people don't like an application to phone home), you can set this to "false".

updater.force

TODO document this!

updater.remoteVersionCache.validityPeriod

TODO document this!

server.securePort

TODO document this!

ldap.url

URL of a server used for LDAP-based authentication.

The default value is ldap://localhost:389.

ldap.bindDnTemplate[${index}]

${index} inside the name of the property is just an integer, which tells in which order templates should be used. First index has to be 0, and all templates have to have consecutive indexes.

Every template should contain one or more of ${login} template variables, which will be replaced with userName, provided by user during authentication. See also LDAP First variant.

Example template: ldap.bindDnTemplate[0] = cn=${login}+sn=secret,ou=users,dc=example,dc=com

ldap.query

LDAP search filter. Every query should contain one or more of ${login} template variables, which will be replaced with userName, provided by user during authentication. Queries are executed as a call to method DirContext#search. During this call ldap.query is used as "filter" parameter, ldap.queryDn as "name" and SUBTREE_SCOPE is added to SearchControls. See also LDAP Second variant.

ldap.queryDn

Base DN for queries. See ldap.query.

ldap.adminDn

DN of technical user, which is used to create a context for execution of LDAP queries in LDAP Second variant.

Documentation
About
Releases