https://github.com/centminmod/centminmod-csync2
https://github.com/centminmod/centminmod-csync2
Last synced: 5 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/centminmod/centminmod-csync2
- Owner: centminmod
- Created: 2024-09-13T15:35:16.000Z (almost 2 years ago)
- Default Branch: master
- Last Pushed: 2024-09-24T11:40:04.000Z (almost 2 years ago)
- Last Synced: 2025-02-13T06:47:01.088Z (over 1 year ago)
- Language: Shell
- Size: 126 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme-csync2-2.1.1-whats-new.md
Awesome Lists containing this project
README
* [csync 2.1.1 RPM Background](#csync-211-rpm-background)
* [What's New In csync2 2.1.1 Enhancements](#whats-new-in-csync2-211-enhancements)
* [csync2 2.1.1: Developer's Guide To New Features and Changes](#csync2-211-developers-guide-to-new-features-and-changes)
# csync 2.1.1 RPM Background
* csync2 is not available as YUM RPM packages for RHEL/CentOS/AlmaLinux/Rocky Linux EL8 and EL9 versions.
* [Official csync2 release](https://github.com/LINBIT/csync2) is still on csync2 2.0 dated May 7, 2015 with official csync2 master branch on csync2 2.1.0rc1 dated September 19, 2020.
* Built own csync2 2.0, 2.1.0 and 2.1.1 YUM RPMs for EL8 and EL9 distributions for my [Centmin Mod LEMP stack](https://centminmod.com) usage where:
* csync2 2.0 RPM is based on official csync2 release.
* csync2 2.1.0 RPM is based on official csync2 master branch 2.1.0rc1 with code modifications for additional MariaDB MySQL support to accompany 4+ yr old Oracle MySQL and PostgreSQL database support and default sqlite3 support. Also built a separate alternative RPM which is built against a newer [sqlite 3.46.1](https://sqlite.org/changes.html) source code based custom RPM instead of EL8/EL9 default sqlite 3.26 and sqlite 3.34 respective version.
* csync2 2.1.1 RPM is based on forked csync2 code from https://github.com/erlandl4g/csync2 which in turn is forked from https://github.com/Shotaos/ - where both forks are from the same developer, [erlandl4g](https://github.com/erlandl4g) - who had [hired and paid 4 developers to make the changes](https://github.com/LINBIT/csync2/pull/36) and offered the code improvements as a pull request to official Csync2 repository but never had the code officially merged. Kept the modifications for additional MariaDB MySQL support to accompany 4+ yr old Oracle MySQL and PostgreSQL database support and default sqlite3 support. Also built a separate alternative RPM which is built against a newer [sqlite 3.46.1](https://sqlite.org/changes.html) source code based custom RPM instead of EL8/EL9 default sqlite 3.26 and sqlite 3.34 respective version.
# What's New In csync2 2.1.1 Enhancements
## 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 `
- `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:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
for node in "${nodes[@]}"
do
csync2 "${csync_opts[@]}" -u -P "$node" &
done
wait
```
### Example Usage
1. Basic Usage:
```bash
./inotify_csync.sh -N myhost.example.com
```
This starts the script with default settings, using "myhost.example.com" as the hostname.
2. Custom Configuration:
```bash
./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:
```bash
./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`
```c
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:
```c
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:
```c
// In csync2.c
int csync_atomic_patch = 1; // Default to enabled
```
#### Update Process Modification:
```c
// 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:
```c
// 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
```bash
#!/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:
```bash
csync2 "${csync_opts[@]}" -cr "${csync_files[@]}" # Check files
csync2 "${csync_opts[@]}" -u # Update
```
- Parallel updates:
```bash
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**:
```c
// 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**:
```c
// 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**:
```c
// 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
```c
// 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
```c
// 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
```c
// 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
```c
// 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
```bash
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.