Skip to content
centminmodPublic
forked from LINBIT/csync2

About

file synchronization tool using librsync and current state databases

Resources

Stars

4 stars

Watchers

1 watching

Forks

 
 

Latest commit

 

History

653 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

About csync2 2.1.1 fork

This Csync2 branch fork https://github.com/centminmod/csync2/tree/2.1 code is based on fork at https://github.com/erlandl4g/csync2 which in turn is forked from https://github.com/Shotaos/csync2 - where both forks are from the same developer, erlandl4g - who had hired and paid 4 developers to make the changes and offered the code improvements as a pull request to official Csync2 repository but never had the code officially merged. In addition, I also added MariaDB MySQL support to accompany 4+ yr old Oracle MySQL and PostgreSQL database support and default sqlite3 support. See below for full details.

About csync

Csync2 is a cluster synchronization tool. It can be used to keep files on multiple hosts in a cluster in sync. Csync2 can handle complex setups with much more than just 2 hosts, handle file deletions and can detect conflicts.

It is expedient for HA-clusters, HPC-clusters, COWs and server farms. If you are looking for a tool to sync your laptop with your workstation, you better have a look at Unison (http://www.cis.upenn.edu/~bcpierce/unison/) too.

The csync2 git tree can be found at https://github.com/LINBIT/csync2/.

Documentation

You should definitely read the documentation before trying to setup csync2, see doc/csync2.adoc

Copyright

  • csync2 - cluster synchronization tool, 2nd generation
  • Copyright © 2004 - 2013 LINBIT Information Technologies GmbH
  • Copyright © 2008 - 2018 LINBIT HA Solutions GmbH
  • see also AUTHORS

License

SPDX-License-Identifier: GPL-2.0-or-later

Mailing List

There is a csync2 mailing list:

http://lists.linbit.com/mailman/listinfo/csync2

It is recommended to subscribe to this list if you are using csync2 in production environments.

What's New In Csync2 2.1.1

1. Atomic File Patching

The atomic file patching feature in csync2 2.1.1 represents a significant advancement in ensuring data consistency and reducing race conditions during file synchronization. This improvement allows csync2 to update files in a single, indivisible operation, encompassing both content changes and metadata modifications (such as ownership, permissions, and timestamps).

The atomic approach utilizes a temporary file for applying changes, followed by an atomic rename operation to replace the original file. This method guarantees that other processes or system interruptions cannot observe or interact with partially updated files, thus maintaining data integrity throughout the sync process. For csync2, this means enhanced reliability in multi-node environments where simultaneous file access is common. It reduces the risk of file corruption or inconsistency that could occur if a synchronization process were interrupted mid-update.

Additionally, by combining multiple operations (content update, ownership change, permission setting, and timestamp modification) into a single atomic action, csync2 potentially reduces I/O operations and improves overall performance, especially for files that undergo frequent changes. However, this feature also introduces new considerations, such as ensuring compatibility across different file systems (particularly networked file systems like NFS) and handling very large files that might exceed available memory. Overall, the atomic file patching feature significantly enhances csync2's robustness and reliability in maintaining synchronized file states across distributed systems.

The "ATOMICPATCH" command is a significant enhancement in csync2 2.1.1, designed to perform file updates in a single, atomic operation. This new command replaces the previous multi-step update process with a unified approach that handles both file content and metadata changes simultaneously.

When invoked, "ATOMICPATCH" takes the following parameters: file key, filename, user ID, group ID, file mode, and modification time (in nanoseconds). This comprehensive set of parameters allows csync2 to update all aspects of a file in one operation.

The command works by first creating a temporary file with the new content and metadata, then using an atomic rename operation to replace the original file. This method ensures that at no point during the update process is the file in an inconsistent state, which is crucial for maintaining data integrity in distributed systems. The atomic nature of this operation means that other processes will either see the old version of the file or the new version, but never an intermediate state. This is particularly important in environments where files might be accessed by multiple nodes or processes simultaneously. The "ATOMICPATCH" command significantly reduces the risk of file corruption or inconsistency that could occur if a synchronization process were interrupted mid-update, making csync2 more robust and reliable in handling file synchronization across distributed systems.

Detailed Implementation:

  • New global flag csync_atomic_patch introduced in csync2.c
  • update.c modifications:
    • In csync_update_file_mod(), replaced multiple separate commands with a single "ATOMICPATCH" command
    • New command format: ATOMICPATCH <key> <filename> <uid> <gid> <mode> <mtime>
  • daemon.c changes:
    • Added new case A_ATOMIC in the command handling switch
    • Implemented csync_dir_update() function for atomic directory updates
  • rsync.c updates:
    • Modified csync_rs_patch() to accept struct stat *atomic_stats
    • Updated clone_ownership_and_permissions() to use atomic stats when available

Technical Implications:

  • Reduces race conditions during file updates
  • Ensures file content and metadata consistency
  • Potential performance impact:
    • Slight increase in memory usage due to holding entire file state
    • Possible reduction in I/O operations by combining updates

Challenges:

  • Backward compatibility with older csync2 versions may be affected
  • Potential issues with file systems that don't support atomic operations

2. Inotify Integration

The inotify_csync.sh script is a powerful addition to csync2 that leverages the inotify system to provide real-time file synchronization. It monitors specified directories for changes and triggers csync2 updates accordingly, offering a more efficient and responsive synchronization process compared to periodic scanning.

Key Components

  1. Inotify Monitoring: Uses inotifywait to watch for file system events in real-time.

  2. Event Queue: Implements a file-based queue system to manage detected changes.

  3. csync2 Integration: Triggers csync2 commands based on detected file system events.

  4. Parallel Processing: Supports parallel updates for multiple peers to improve performance.

Script Configuration

Key variables at the top of the script:

file_events="move,delete,attrib,create,close_write,modify"
queue_file="/path/to/queue.log"
check_interval=0.5
full_sync_interval=$((60*60))
num_lines_until_reset=200000
num_batched_changes_threshold=15000
parallel_updates=1
  • file_events: Types of file system events to monitor.
  • queue_file: Location of the file used to queue detected changes.
  • check_interval: Time between queue checks (in seconds).
  • full_sync_interval: Time between full syncs (in seconds).
  • num_lines_until_reset: Queue size threshold for reset.
  • num_batched_changes_threshold: Number of changes that trigger a full sync.
  • parallel_updates: Enable/disable parallel updates to peers.

Main Functionality

  1. Inotify Monitoring: The script starts an inotifywait process to monitor specified directories:

    inotifywait --monitor --recursive --event $file_events --format "%w%f" "${includes[@]}"
  2. Queue Processing: Detected changes are added to a queue file. The script periodically processes this queue:

    while true
    do
        sleep $check_interval
        process_queue
        check_for_full_sync
    done
  3. csync2 Integration: The script calls csync2 to check and update files:

    csync2 "${csync_opts[@]}" -cr "${csync_files[@]}"  # Check files
    csync2 "${csync_opts[@]}" -u  # Update
  4. Parallel Updates: When enabled, updates to multiple peers are performed in parallel:

    for node in "${nodes[@]}"
    do
        csync2 "${csync_opts[@]}" -u -P "$node" &
    done
    wait

Example Usage

  1. Basic Usage:

    ./inotify_csync.sh -N myhost.example.com

    This starts the script with default settings, using "myhost.example.com" as the hostname.

  2. Custom Configuration:

    ./inotify_csync.sh -N myhost.example.com -c /path/to/custom/csync2.cfg -D /path/to/database

    This uses a custom configuration file and database path.

  3. Verbose Mode:

    ./inotify_csync.sh -N myhost.example.com -v

    Runs the script in verbose mode for more detailed output.

Best Practices and Considerations

  1. Inotify Limits: Be aware of system inotify watch limits. You may need to adjust /proc/sys/fs/inotify/max_user_watches for large directory structures.

  2. Queue Management: The script uses a file-based queue. Ensure the directory containing the queue file has sufficient space and permissions.

  3. Performance Tuning: Adjust check_interval and num_batched_changes_threshold based on your system's characteristics and synchronization needs.

  4. Error Handling: The script includes basic error handling, but consider implementing additional logging or alerting for production environments.

  5. Testing: Thoroughly test the script in a non-production environment, especially when using parallel updates, to ensure it behaves as expected with your specific file system and network configuration.

By using this script, you can significantly enhance csync2's responsiveness to file changes, making it more suitable for scenarios requiring near real-time synchronization across multiple nodes.

Detailed Script Analysis (inotify_csync.sh):

  • Uses inotifywait in monitor mode with configurable event types
  • Implements a queue system using a text file (queue_file)
  • Key variables:
    • check_interval: Time between queue checks
    • full_sync_interval: Time between full syncs
    • num_lines_until_reset: Queue size threshold for reset
    • num_batched_changes_threshold: Threshold for triggering full sync
  • Functions:
    • csync_server_wait(): Ensures server is idle before operations
    • csync_full_sync(): Performs complete sync
    • reset_queue(): Resets the queue file and performs full sync

Technical Considerations:

  • Inotify limitations:
    • Max number of watches (adjustable via /proc/sys/fs/inotify/max_user_watches)
    • Potential for missed events if queue fills up
  • Performance impact:
    • Reduced CPU usage for file checking
    • Increased memory usage for maintaining inotify watches
    • Potential for high I/O if many small changes occur rapidly

Integration with csync2:

  • Uses csync2 commands directly, bypassing the need for periodic scans
  • Utilizes new -P flag for parallel updates
  • Parses csync2.cfg for configuration details

3. Enhanced Timestamp Precision

The enhanced timestamp precision feature in csync2 2.1.1 represents a significant improvement in file synchronization accuracy, particularly for environments with rapidly changing files or where millisecond-level precision is insufficient.

By implementing nanosecond-level timestamp precision across key components of the system (checktxt.c, daemon.c, and update.c), csync2 can now detect and synchronize changes that occur within extremely short time intervals. This enhancement allows for more granular tracking of file modifications, reducing the likelihood of missed updates in high-frequency change scenarios.

The shift from 32-bit to 64-bit integer representation for timestamps not only provides the necessary range for nanosecond precision but also future-proofs the system against the Year 2038 problem. However, this improvement comes with considerations: increased storage requirements for timestamps, potential performance impacts due to more complex comparisons, and possible compatibility issues with older file systems or csync2 versions that may not support such high-precision timestamps. Despite these challenges, the enhanced timestamp precision significantly improves csync2's ability to maintain accurate file synchronization in demanding, fast-paced environments, making it a valuable upgrade for systems requiring utmost accuracy in file state replication.

Implementation Details:

  • checktxt.c:
    • Modified csync_genchecktxt() to use nanosecond precision
    • New timestamp format: mtime=%lld (nanoseconds since epoch)
  • daemon.c:
    • Updated A_SETIME case to use utimensat() instead of utime()
    • Modified timestamp parsing in A_ATOMIC case
  • update.c:
    • Introduced nano_timestamp variable
    • Updated all timestamp comparisons and transmissions to use nanosecond precision

Technical Impact:

  • Improves sync accuracy for rapidly changing files
  • Increases timestamp storage requirements (64-bit integer vs 32-bit)
  • Potential compatibility issues with older file systems or csync2 versions

4. Improved Database Support

Detailed Changes:

  • configure.ac:
    • Added checks for both MySQL and MariaDB
    • Implements dynamic detection of available database systems
  • db_mysql.c:
    • Added conditional compilation for MySQL/MariaDB specific functions
    • Implemented dynamic loading of database libraries using dlopen()
  • New macros and typedefs to handle API differences

Technical Considerations:

  • Improves portability across different database setups
  • Dynamic loading reduces hard dependencies
  • Potential for slight performance overhead due to function pointer usage

5. Automatic Hostname Detection

The automatic hostname detection feature in csync2 2.1.1 introduces a sophisticated algorithm to dynamically identify and set the local hostname, enhancing the system's adaptability in diverse network environments. This feature iterates through all hostnames specified in the csync2 configuration, attempting to resolve and bind to each one using low-level network operations.

By leveraging getaddrinfo() for resolution and attempting to bind() to resolved addresses, the system can accurately determine its identity within the network topology. This approach is particularly beneficial in DHCP environments or systems with complex networking setups, as it eliminates the need for manual hostname configuration.

However, this functionality comes with certain technical implications: it may lead to increased startup times, especially in networks with numerous or hard-to-resolve hostnames, and the binding attempts could potentially trigger security alerts on some systems. Despite these considerations, the automatic hostname detection significantly improves csync2's ease of deployment and reliability across various network configurations, making it more robust and user-friendly in dynamic environments.

Algorithm in csync2.c:

  1. Iterates through all hostnames in csync2 configuration
  2. For each hostname:
    • Calls getaddrinfo() to resolve the hostname
    • Attempts to bind() to each resolved address
    • If successful, sets as local hostname and updates configuration
  3. Falls back to default if no bind succeeds

Technical Implications:

  • May increase startup time, especially in complex networks
  • Potential security implications of binding attempts
  • Improves reliability in DHCP environments

6. Performance Optimizations

csync2 2.1.1 introduces two major performance optimizations that significantly enhance its efficiency and scalability: batched delete operations and parallel updates. The batched delete operations feature, implemented through the batched_dirty_deletes variable in update.c, allows csync2 to accumulate and execute multiple delete operations in a single batch. This approach substantially reduces the number of individual DELETE queries sent to the database, potentially improving transaction handling and reducing lock contention. As a result, csync2 can handle large numbers of file deletions more efficiently, particularly beneficial in scenarios involving extensive file cleanups or reorganizations.

Complementing this, the parallel updates feature, activated via the new -P command-line option, enables csync2 to perform updates on multiple peers simultaneously. This parallelization, coupled with the modification in check.c to skip dirty marking for inactive peers, allows for more efficient utilization of network resources and significantly reduces synchronization times in multi-node setups. The integration of these features with the inotify_csync.sh script further amplifies their benefits, enabling real-time, efficient synchronization across complex distributed environments. While these optimizations greatly enhance performance, they also introduce new considerations for conflict resolution and database management, requiring careful implementation in production environments.

Batched Delete Operations:

  • New global variable batched_dirty_deletes in update.c
  • Modified csync_update() to accumulate deletes and execute in batch
  • Impact on database operations:
    • Reduced number of individual DELETE queries
    • Potential for improved transaction handling

Parallel Updates:

  • New command-line option -P for specifying active peers
  • Modified check.c to skip dirty marking for inactive peers
  • inotify_csync.sh utilizes this for parallel csync2 invocations

Technical Challenges:

  • Increased complexity in conflict resolution
  • Potential for database deadlocks if not carefully managed

7. Debugging and Logging Enhancements

Implementation Details:

New -O flag in csync2.c:

  • Added to the getopt options string: "W:s:Ftp:G:P:C:D:N:O::HBAIXULlSTMRavhcuoimfxrd"
  • Implemented as an optional argument flag (note the double colon ::)
  • Usage: -O[logfile] where logfile is an optional path to the debug log file
  • If no logfile is specified, it defaults to /tmp/csync2_full_log.log
case 'O': 
{
    char *logname = optarg ? optarg : "/tmp/csync2_full_log.log";
    if((debug_file = fopen(logname, "w+")) == NULL) {
        fprintf(stderr, "Could not open full log file:  %s\n", logname);
        exit(1);
    }
}
break;

Modifications to error.c:

  • Added a new global variable FILE *debug_file; to handle the debug log file
  • Updated csync_vdebug function to write to the debug file when enabled:
void csync_vdebug(int lv, const char *fmt, va_list ap)
{
    va_list debug_file_va;
    if (debug_file) {
        va_copy(debug_file_va, ap);
        vfprintf(debug_file, fmt, debug_file_va);
    }

    // Existing debug output logic remains unchanged
    if (csync_debug_level < lv)
        return;
    // ... (rest of the function)
}
  • This change allows for comprehensive logging to a file without altering the existing console output behavior

Enhanced logging in daemon.c:

  • Improved command tracing for better debugging of daemon operations
  • Details of command arguments are now logged, providing more context for each operation

Technical Considerations:

  1. Performance Impact:

    • When -O flag is used, every debug message is written to both the console (if debug level permits) and the log file
    • This can lead to increased I/O operations, potentially impacting performance on systems with slow storage
  2. File Handling:

    • The debug file is opened in w+ mode, which truncates the file if it already exists
    • Developers should be aware that enabling this flag will overwrite any existing log file with the same name
  3. Error Handling:

    • If the specified (or default) log file cannot be opened, the program will exit with an error message
    • This behavior ensures that logging issues are caught early in the execution
  4. Flexibility:

    • The optional argument for -O allows developers to specify custom log file locations, useful for different environments or multiple concurrent debug sessions
  5. Integration with Existing Debug System:

    • The new file logging is integrated with the existing csync_vdebug function, ensuring consistency between file and console logging
  6. Memory Considerations:

    • Usage of va_copy ensures proper handling of variable arguments across multiple uses, preventing potential memory issues

Logging Format and Content:

  • Timestamp prefixing for all log entries
  • Detailed argument logging for each command
  • Performance metrics logging (e.g., operation durations)

Impact on Performance and Storage:

  • Potential for significant log file growth
  • Slight CPU overhead for extensive logging

8. Build System and Compatibility Improvements

Autoconf/Automake Updates:

  • Modified configure.ac to check for newer compiler features
  • Updated Makefile.am for better handling of system-specific quirks

Compiler Warnings and Standards:

  • Added stricter warning flags (e.g., -Wno-format-truncation)
  • Ensured compatibility with C99 and newer standards

Cross-platform Considerations:

  • Improved checks for system-specific headers and libraries
  • Enhanced portability for different Linux distributions and potentially other UNIX-like systems

csync2 2.1.1: Developer's Guide To New Features and Changes

1. Atomic File Patching

Core Implementation Details

New Flag Introduction:

// In csync2.c
int csync_atomic_patch = 1; // Default to enabled

Update Process Modification:

// In update.c
enum connection_response csync_update_file_mod(const char *peername,
               const char *filename, int force, int dry_run)
{
    // ...
    if (S_ISREG(st.st_mode)) {
        if (csync_atomic_patch) {
            conn_printf("ATOMICPATCH %s %s %d %d %d %lld\n",
                url_encode(key), url_encode(filename),
                st.st_uid, st.st_gid, st.st_mode, nano_timestamp);
        } else {
            // Fallback to old method
        }
    }
    // ...
}

Daemon-side Handling:

// In daemon.c
void csync_daemon_session()
{
    // ...
    case A_ATOMIC:
        if (!csync_file_backup(tag[2])) {
            conn_resp(CR_OK_SEND_DATA);
            csync_rs_sig(tag[2]);

            memset(&atomic_stats, 0, sizeof(atomic_stats));
            atomic_stats.st_uid = atoll(tag[3]);
            atomic_stats.st_gid = atoll(tag[4]);
            atomic_stats.st_mode = atoll(tag[5]);
            atomic_stats.st_mtime = atoll(tag[6]);

            if (csync_rs_patch(tag[2], &atomic_stats))
                cmd_error = strerror(errno);
        }
        break;
    // ...
}

Technical Deep Dive

  1. Atomic Operation Mechanism:

    • Uses a temporary file for patching.
    • Applies all changes (content, ownership, permissions, timestamps) to the temp file.
    • Performs an atomic rename operation to replace the original file.
  2. Error Handling:

    • If any step fails, the entire operation is rolled back.
    • Maintains the original file's integrity in case of failure.
  3. Performance Considerations:

    • Slight increase in memory usage due to holding entire file state.
    • Potential I/O performance improvement by reducing the number of system calls.
  4. Challenges:

    • Ensuring atomicity across different file systems (e.g., NFS compatibility).
    • Handling very large files that may exceed available memory.

2. Inotify Integration

Script Architecture

#!/bin/bash
# inotify_csync.sh

# Configuration variables
file_events="move,delete,attrib,create,close_write,modify"
queue_file="/path/to/queue.log"
check_interval=0.5
full_sync_interval=$((60*60))
num_lines_until_reset=200000
num_batched_changes_threshold=15000
parallel_updates=1

# Main monitoring loop
inotifywait --monitor --recursive --event $file_events --format "%w%f" "${includes[@]}" | 
while read -r file
do
    # Process and queue file changes
    echo "$file" >> $queue_file
done &

# Queue processing loop
while true
do
    sleep $check_interval
    process_queue
    check_for_full_sync
done

Key Functions

  1. process_queue():

    • Reads new entries from the queue file.
    • Deduplicates entries.
    • Calls csync2 for checking and updating.
  2. check_for_full_sync():

    • Triggers full sync based on time or queue size.
  3. csync_server_wait():

    • Ensures the csync2 server is idle before operations.

Integration with csync2

  • Uses csync2 command-line interface:
    csync2 "${csync_opts[@]}" -cr "${csync_files[@]}"  # Check files
    csync2 "${csync_opts[@]}" -u  # Update
  • Parallel updates:
    for node in "${nodes[@]}"
    do
        csync2 "${csync_opts[@]}" -u -P "$node" &
    done
    wait

Technical Considerations

  1. Inotify Limits:

    • System-wide watch limit: /proc/sys/fs/inotify/max_user_watches
    • Per-process instance limit: /proc/sys/fs/inotify/max_user_instances
  2. Queue Management:

    • File-based queue for persistence across script restarts.
    • Periodic reset to prevent unbounded growth.
  3. Error Handling:

    • Logging of inotify errors.
    • Fallback to full sync on queue processing failures.
  4. Performance Tuning:

    • Adjustable check_interval for balancing responsiveness and system load.
    • num_batched_changes_threshold for handling large bursts of changes.

3. Enhanced Timestamp Precision

Implementation in Key Components

  1. Checktxt Generation:

    // In checktxt.c
    const char *csync_genchecktxt(const struct stat *st, const char *filename, int ign_mtime)
    {
        // ...
        int64_t timestamp = st->st_mtime * 1000000000 + st->st_mtim.tv_nsec;
        xxprintf(":mtime=%lld", ign_mtime ? 0 : (long long)timestamp);
        // ...
    }
  2. Daemon Handling:

    // In daemon.c
    case A_SETIME:
    {
        struct timespec tsp[2];
        long long timestamp = atoll(tag[3]);
        tsp[0].tv_sec = tsp[1].tv_sec = (int) (timestamp / 1000000000);
        tsp[0].tv_nsec = tsp[1].tv_nsec =  timestamp % 1000000000;
        if(utimensat(0, prefixsubst(tag[2]), tsp, 0))
            cmd_error = strerror(errno);
    }
  3. Update Process:

    // In update.c
    long long nano_timestamp = st.st_mtime * 1000000000 + st.st_mtim.tv_nsec;
    // Use nano_timestamp in all relevant operations

Technical Implications

  1. Storage Impact:

    • Increased size of timestamp data (64-bit vs 32-bit).
    • Potential database schema changes required.
  2. Comparison Logic:

    • Updated file comparison algorithms to handle nanosecond precision.
    • Potential for more accurate conflict detection in rapid update scenarios.
  3. Cross-platform Considerations:

    • Ensuring compatibility with file systems that don't support nanosecond precision.
    • Fallback mechanisms for systems with lower timestamp resolution.

4. Improved Database Support

Dynamic Database Detection and Loading

// In configure.ac
AC_CHECK_PROG([MYSQL_CONFIG], [mysql_config], [mysql_config])
AC_CHECK_PROG([MARIADB_CONFIG], [mariadb_config], [mariadb_config])

AS_IF([test -n "$MYSQL_CONFIG"], [
    // MySQL configuration
], [test -n "$MARIADB_CONFIG"], [
    // MariaDB configuration
], [
    AC_MSG_ERROR([Neither MySQL nor MariaDB found])
])

Database API Abstraction

// In db_mysql.c
static struct db_mysql_fns {
    MYSQL *(*mysql_init_fn) (MYSQL *);
    MYSQL *(*mysql_real_connect_fn) (MYSQL *, const char *, const char *, const char *, const char *, unsigned int, const char *, unsigned long);
    // ... other function pointers
} db_mysql;

static void db_mysql_dlopen(void)
{
    dl_handle = dlopen(LIBMYSQLCLIENT_SO, RTLD_LAZY);
    if (!dl_handle) {
        csync_fatal("Failed to load MySQL/MariaDB library: %s\n", dlerror());
    }
    
    LOOKUP_SYMBOL(dl_handle, mysql_init);
    LOOKUP_SYMBOL(dl_handle, mysql_real_connect);
    // ... load other symbols
}

Technical Considerations

  1. Performance Impact:

    • Minimal overhead from function pointer usage.
    • Potential for optimized library selection based on available features.
  2. Compatibility:

    • Ensures broader compatibility across different database setups.
    • Simplifies maintenance for supporting multiple database systems.
  3. Error Handling:

    • Robust error checking for library loading and function resolution.
    • Graceful fallback options if preferred database system is unavailable.

5. Automatic Hostname Detection

Algorithm Implementation

// In csync2.c
void detect_hostname(void)
{
    struct csync_group *g;
    struct addrinfo hints, *result, *rp;
    int sfd, s;

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;    // Allow IPv4 or IPv6
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;    // For wildcard IP address

    for (g = csync_group; g && !g->myname; g = g->next) {
        for (struct csync_group_host *h = g->host; h; h = h->next) {
            s = getaddrinfo(h->hostname, NULL, &hints, &result);
            if (s != 0) continue;

            for (rp = result; rp != NULL; rp = rp->ai_next) {
                sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
                if (sfd == -1) continue;

                if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) {
                    g->myname = strdup(h->hostname);
                    close(sfd);
                    freeaddrinfo(result);
                    return;
                }
                close(sfd);
            }
            freeaddrinfo(result);
        }
    }
}

Technical Deep Dive

  1. Network Stack Interaction:

    • Uses low-level socket operations to verify bindability.
    • Handles both IPv4 and IPv6 addresses.
  2. Performance Considerations:

    • Potential for increased startup time in complex network environments.
    • Caching mechanism to avoid repeated lookups.
  3. Security Implications:

    • Temporary binding to ports may trigger security software alerts.
    • Ensure proper permissions and firewall configurations.
  4. Error Handling:

    • Graceful fallback to manual configuration if auto-detection fails.
    • Comprehensive logging of the detection process for troubleshooting.

6. Performance Optimizations

Batched Delete Operations

// In update.c
static struct textlist *batched_dirty_deletes;

void csync_update(const char ** patlist, int patnum, int recursive, int dry_run)
{
    // ...
    for (t = tl; t != 0; t = t->next) {
        csync_update_host(t->value, patlist, patnum, recursive, dry_run);

        if (csync_batch_deletes && !dry_run) {
            for (dt = batched_dirty_deletes; dt != 0; dt = dt->next) {
                SQL("Remove dirty-file entry from batch",
                    "DELETE FROM dirty WHERE filename = '%s' "
                    "AND peername = '%s'", url_encode(dt->value),
                    url_encode(t->value));
            }
            textlist_free(batched_dirty_deletes);
            batched_dirty_deletes = NULL;
        }
    }
    // ...
}

Parallel Updates in Script

if (( parallel_updates ))
then
    update_pids=()
    for node in "${nodes[@]}"
    do
        csync2 "${csync_opts[@]}" -ub -P "$node" &
        update_pids+=($!)
    done
    wait "${update_pids[@]}"
else
    csync2 "${csync_opts[@]}" -u
fi

Technical Analysis

  1. Database Optimization:

    • Reduced number of individual DELETE queries.
    • Potential for improved transaction handling and reduced lock contention.
  2. Concurrency Handling:

    • Implement proper locking mechanisms to prevent race conditions.
    • Consider using database-specific features (e.g., MySQL's INSERT ... ON DUPLICATE KEY UPDATE) for further optimization.
  3. Memory Management:

    • Monitor memory usage for large batches of deletes.
    • Implement batch size limits to prevent excessive memory consumption.
  4. Error Recovery:

    • Implement transaction-like behavior for batched operations.
    • Provide rollback capabilities in case of partial failures.

Conclusion

This detailed technical analysis provides a comprehensive overview of the significant changes and enhancements in csync2 2.1.1. The updates touch on various aspects of the system, from low-level file operations to high-level synchronization strategies and database interactions.

Key areas for developers to focus on include:

  1. Understanding the implications of atomic file operations across different file systems.
  2. Optimizing the inotify integration for large-scale deployments.
  3. Ensuring database compatibility and performance with the new dynamic loading system.
  4. Handling increased timestamp precision across all synchronization logic.
  5. Implementing and testing the new parallel update capabilities.

About

file synchronization tool using librsync and current state databases

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages