Skip to content

Store Swiftlet

Overview

The Store Swiftlet provides the persistent and non-persistent message storage for all queues in the SwiftMQ router. It manages the underlying page database (page.db), transaction log, swap files for non-persistent queues, and durable subscriber state. The Store Swiftlet ensures message durability, transactional integrity, and supports backup and maintenance operations.

Features

Persistent Store for Queues

The Store Swiftlet maintains a page-based database (page.db) to persistently store messages for all queues configured with persistent delivery. Each queue is mapped to a dedicated index within the page database, ensuring fast access and isolation. The persistent store supports transactional operations, including commit and rollback, to guarantee message durability and atomicity. The underlying storage is optimized for high throughput and crash recovery, with a root index mapping queue names to their respective storage areas. During startup, the Store Swiftlet performs recovery by replaying the transaction log and running a consistency check on the page database.

Page Database Management

The page database is organized into fixed-size pages, with configurable page size and initial number of pages. The Store Swiftlet can compact or resize the database on startup, based on configuration and scan results. The consistency of the database is checked during startup, and any inconsistencies are corrected if possible.

Transactional Message Operations

All message operations (insert, remove, update delivery count) are performed within transactions. The Store Swiftlet provides read and write transactions, supporting both local and XA (2PC) transactions. Transactions are logged to the transaction log before being committed to the page database, ensuring durability and atomicity.

Configuration Example:

<swiftlet name="sys$store">
  <database path="data/page.db" initial-db-size-pages="51200"/>
</swiftlet>

Transaction Log and Recovery

The Store Swiftlet maintains a transaction log (transaction.log) to record all changes to the persistent store. This log enables crash recovery by replaying committed transactions and rolling back incomplete ones. The log is periodically checkpointed, flushing all changes to disk and truncating the log to reduce disk usage. The checkpoint interval is determined by the configured checkpoint size. The transaction log can be configured to force a disk sync on each write for maximum durability, at the cost of performance.

XA Transaction Support

The Store Swiftlet supports distributed (XA/2PC) transactions by maintaining a prepared log (xa.log or in-queue) that records the state of prepared transactions. This ensures that prepared transactions can be recovered and completed after a crash.

Consistency Checking

During recovery, the Store Swiftlet performs a consistency check on the persistent store. If inconsistencies are found, the store attempts to correct them, possibly resulting in data loss. Administrators are advised to enable force-sync for the transaction log to minimize the risk of inconsistency.

Configuration Example:

<swiftlet name="sys$store">
  <transaction-log path="data/transaction.log" checkpoint-size="209715200" force-sync="true"/>
</swiftlet>

Cache Management

To optimize performance, the Store Swiftlet uses an in-memory cache for database pages. The cache size is configurable with minimum and maximum page counts. The cache manager employs an LRU eviction policy for unpinned pages and flushes dirty pages to disk during checkpoints or when the cache is full. The cache ensures that frequently accessed data is kept in memory for fast operations, while maintaining consistency with the persistent store.

Dynamic Cache Sizing

The minimum and maximum cache sizes can be configured independently. The Store Swiftlet enforces that the minimum size is less than or equal to the maximum, and will reject invalid configurations.

Configuration Example:

<swiftlet name="sys$store">
  <cache min-size="2048" max-size="4096"/>
</swiftlet>

Non-Persistent Store (Swap Files)

For queues configured with non-persistent delivery, the Store Swiftlet uses swap files to temporarily store messages that do not fit in memory. Swap files are created in a configurable directory, with a configurable roll-over size to limit file growth. When a swap file reaches its roll-over size, a new file is created. Swap files are automatically deleted when the queue is closed or the router shuts down.

Swap File Management

Swap files are managed per queue and are automatically cleaned up. The roll-over size determines the maximum size of each swap file before a new one is created.

Configuration Example:

<swiftlet name="sys$store">
  <swap path="data/swap" roll-over-size="20971520"/>
</swiftlet>

Durable Subscriber Store

The Store Swiftlet manages the state of durable topic subscribers by storing their subscription information (client ID, durable name, topic, selector, noLocal flag) in files within a configurable directory. Each durable subscription is mapped to a file named using the pattern $.durable. This ensures that durable subscriptions survive router restarts and can be recovered reliably.

Durable Subscription File Naming

Durable subscription state is stored in files named $.durable in the configured directory. These files are managed automatically by the Store Swiftlet.

Configuration Example:

<swiftlet name="sys$store">
  <durable-subscriber path="data/durables"/>
</swiftlet>

Backup and Restore

The Store Swiftlet provides an integrated backup mechanism to create consistent snapshots of the persistent store, including the page database, transaction log, and durable subscriber files. Backups are stored as save sets in a configurable directory, with automatic retention of a configurable number of backup generations. Backups are performed in a coordinated manner, ensuring a checkpoint is taken before files are copied for consistency. The backup process can be triggered manually via the CLI or scheduled as a job.

Backup Path and Generations

The backup path specifies where save sets are stored. The number of generations determines how many backup sets are retained; older backups are automatically deleted.

Backup Job Integration

Backup operations can be triggered manually or scheduled via the sys$scheduler Swiftlet. The Store Swiftlet registers a 'Backup' job for this purpose.

Configuration Example:

<swiftlet name="sys$store">
  <backup path="backups" keep-generations="5"/>
</swiftlet>

Maintenance Operations: Shrink and Scan

The Store Swiftlet supports maintenance operations to optimize storage and recommend configuration changes. The shrink operation compacts the page database by reclaiming unused pages, reducing disk usage. The scan operation analyzes message sizes in the database and recommends an optimal page size for performance. Both operations are coordinated with checkpoints to ensure consistency and can be triggered manually or scheduled as jobs.

Shrink Job

The 'Shrink' job compacts the page database, removing unused pages and reducing file size. This can be triggered manually or scheduled.

Scan Job

The 'Scan' job analyzes the distribution of message sizes in the database and updates the recommended page size. This helps administrators tune the store for optimal performance.

Configuration Example:

<swiftlet name="sys$store"/>

Automatic Store Conversion and Compaction

On startup, the Store Swiftlet can automatically resize or compact the page database if the recommended page size differs from the current size or if compaction is enabled. This process involves spooling messages out, resizing or compacting the database, and spooling messages back in, ensuring minimal downtime and optimal storage layout.

Page Size Recommendation

The recommended page size is updated based on scan results and can be used to trigger automatic resizing on startup if configured.

Configuration Example:

<swiftlet name="sys$store">
  <database perform-resize-on-startup="true"/>
</swiftlet>

Internal Queue Naming

  • <clientId>$<durableName> — Queue name pattern for durable topic subscriptions; state stored as $.durable files.
  • sys$prepared — Internal queue used for in-memory prepared transaction log (PreparedLogQueue) when XA transactions are enabled.

Configuration Guide

Configuring Persistent Store with Custom Page Size and Cache

Use this scenario to optimize the persistent store for high-throughput workloads by increasing the page size and cache size. This reduces disk I/O and improves performance for large messages.

  1. Set the desired page size and initial database size in the database entity.
  2. Increase the cache min-size and max-size for more in-memory pages.
  3. Restart the router for changes to take effect.
<swiftlet name="sys$store">
  <database page-size-current="4096" initial-db-size-pages="65536"/>
  <cache min-size="4096" max-size="8192"/>
</swiftlet>

Enabling Force Sync on Transaction Log for Maximum Durability

Enable force-sync to ensure that every transaction log write is flushed to disk, minimizing the risk of data loss in case of a crash. This is recommended for critical production environments where durability is paramount.

  1. Set force-sync to true in the transaction-log entity.
  2. Restart the router to apply the setting.
<swiftlet name="sys$store">
  <transaction-log force-sync="true"/>
</swiftlet>

Configuring and Scheduling Automatic Backups

Set up the Store Swiftlet to keep regular backups of the persistent store, retaining a specific number of backup generations. This ensures recoverability in case of hardware failure or data corruption.

  1. Set the backup path and keep-generations in the backup entity.
  2. Schedule the 'Backup' job via the sys$scheduler Swiftlet if desired.
<swiftlet name="sys$store">
  <backup path="/mnt/backups/swiftmq" keep-generations="7"/>
</swiftlet>

Optimizing Swap File Usage for Non-Persistent Queues

Increase the swap file roll-over size to accommodate larger volumes of non-persistent messages without frequent file creation. Useful for high-throughput, non-persistent workloads.

  1. Set the roll-over-size property in the swap entity to the desired value.
  2. Restart the router to apply the change.
<swiftlet name="sys$store">
  <swap roll-over-size="52428800"/>
</swiftlet>

CLI Commands

backup

Description: Perform Backup Now

Usage: backup

shrink

Description: Perform Shrink Now

Usage: shrink

scan

Description: Scan page.db

Usage: scan

Scheduler Jobs

Backup

Description: Performs a Backup of the persistent Store

Scan

Description: Scans page.db and recommends a new page size

Shrink

Description: Performs a Shrink of the page.db

Configuration Reference

The top-level entity in routerconfig.xml is <swiftlet name="sys$store">.

<backup> Entity

Backup Settings

This is a fixed child entity of <swiftlet name="sys$store">.

Parameter Type Default Mandatory Reboot Required Description
path String Yes No Root Path for Backup Save Sets
keep-generations Integer 3 No No Number of Generations to keep (min: 1)
<swiftlet name="sys$store">
  <backup path="..." keep-generations="..."/>
</swiftlet>

<database> Entity

Database Settings

This is a fixed child entity of <swiftlet name="sys$store">.

Parameter Type Default Mandatory Reboot Required Description
path String Yes Yes Path of the Database (page.db)
initial-db-size-pages Integer 25600 No Yes Initial Size of the Database in Pages (min: 10)
size-collect-interval Long 1000 No No Interval to collect the Usage
page-size-current Integer 2048 No No Current Size of the Database Pages
page-size-recommended Integer 2048 No No Recommended Size of the Database Pages
page-size-max Integer 32768 No No Maximum Page Size (min: 2048)
perform-compact-on-startup Boolean false No No Perform a compact of the page.db on startup if current page size is equal to recommended page size
perform-resize-on-startup Boolean false No No Perform a page resize on startup if the recommended size is greater than the current page size
<swiftlet name="sys$store">
  <database path="..." initial-db-size-pages="..." size-collect-interval="..." page-size-current="..." page-size-recommended="..." page-size-max="..." perform-compact-on-startup="..." perform-resize-on-startup="..."/>
</swiftlet>

<cache> Entity

Cache Settings

This is a fixed child entity of <swiftlet name="sys$store">.

Parameter Type Default Mandatory Reboot Required Description
min-size Integer 1024 No Yes Min. Size (Pages) (min: 512)
max-size Integer 2048 No Yes Max. Size (Pages) (min: 512)
<swiftlet name="sys$store">
  <cache min-size="..." max-size="..."/>
</swiftlet>

<transaction-log> Entity

Transaction Log Settings

This is a fixed child entity of <swiftlet name="sys$store">.

Parameter Type Default Mandatory Reboot Required Description
path String Yes Yes Path of the Transaction Log (transaction.log)
checkpoint-size Long 104857600 No Yes Size at which a Checkpoint is performed (min: 1048576)
force-sync Boolean false No Yes Force a sync with the disk
<swiftlet name="sys$store">
  <transaction-log path="..." checkpoint-size="..." force-sync="..."/>
</swiftlet>

<swap> Entity

Swap Settings

This is a fixed child entity of <swiftlet name="sys$store">.

Parameter Type Default Mandatory Reboot Required Description
path String Yes Yes Path of Swap Files
roll-over-size Long 10485760 No Yes Roll Over Size (min: 1048576)
<swiftlet name="sys$store">
  <swap path="..." roll-over-size="..."/>
</swiftlet>

<durable-subscriber> Entity

Durable Subscriber Settings

This is a fixed child entity of <swiftlet name="sys$store">.

Parameter Type Default Mandatory Reboot Required Description
path String Yes Yes Path of Durable Subscriber Files
<swiftlet name="sys$store">
  <durable-subscriber path="..."/>
</swiftlet>

Changelog

13.2.1 (2026-02-19)

  • PageInputStream: fixed boundary condition

13.2.0 (2025-11-03)

  • Modified StableStore