CVS Improvement for Remote Development – Exhibit A

Abstract

This document discusses the redesign of CVS to support multiple repository servers slaved to a single primary server that accepts write requests.  Writes to the primary will be pushed to secondaries as quickly as possible.

Introduction

CVS easily supports multiple read-only repositories, but not multiple write repositories.   The locking scheme used by CVS prevents multiple write repositories from cooperating easily.

When dealing with distributed environments, where some groups of developers may be connected to the network via slow links, it becomes useful to provide groups of developers behind slow network connections with a “mirror”, or “read-only”, CVS repository to speed up the common day-to-day development tasks that CVS is used for but which only require read access to the repository.  This could also be useful to divide up a large group of developers into smaller groups to reduce the loading on individual servers.

To avoid having to train developers to manually specify a separate write repository for write operations, it would be useful if the secondary repository servers had some way to refer a CVS client to the primary server for write operations, or to act as a proxy for the write operations.

This paper proposes a method of having secondary repositories become transparent proxies for a primary repository server upon receiving write operation requests.  To support keeping the secondary repositories up to date, this method will be used in conjunction with an rsync data push after completion of each write request on the primary.

Additional Requirements

Configuration should be as simple as possible.

If secondary servers become out of date for any reason, resynchronizing with the primary repository should be a one step process.

Queued push requests to push new data to the secondaries should not clog the network.

Write requests should introduce as few new delays into the write process as possible.

Secondary repository servers should stay as closely synchronized with the primary server as possible.  This includes updating a secondary that just served as a proxy before releasing its client since otherwise the client may find its workspace out of sync with its read repository.

Regression tests should be provided to insure that these new features are not broken by future work on CVS.

Implementation

Configuration

All rysnc processes, whether push or pull, will lock the primary before any secondaries to avoid deadlock.  In the case of updates from a secondary to a tertiary, the server “closest” to the primary will always be locked first.

Configuration of Secondary Repository Servers

Secondary repository servers will need, initially, a copy of the primary repository.

Secondary repository servers will need to know how to talk to the primary repository.  This should be a simple matter of setting a CVSROOT string attached to an option in the CVSROOT/config file.

Secondary repository servers will need to be set up in such a way as to allow the data push from the primary.  This will probably simply involve setting up an SSH server daemon on each secondary and an account which has write privileges to the entire repository on each secondary and installing the rsync & cvslock applications on each secondary machine.

Secondary servers will need to be configured to pull data from the primary before releasing the client via the CVSROOT/postproxy file.

Primary Repository Server Configuration

The primary repository servers will need to have a single SSH private key available to any account the CVS server may run under.  This SSH key should allow access to any secondary CVS server via an account which has write access to the entire CVS repository on each secondary.

The CVSROOT/loginfo file in the primary repository will need to be configured to push changes to secondaries on commit.  To queue updates, cvslock should be used to lock a single, arbitrary, “update” directory with every commit.  This will allow only a single rsync process to run on any secondary at any given time and avoid over-utilization of bandwidth.

There should exist a script that can be run to resynchronize the entire repository of each secondary server in the event that synchronization is lost since unsynchronized secondaries could prevent commits. 

The primary server will intuit its status as the primary by noting that its hostname is the one specified in CVSROOT/config as the primary.  Thus, all the secondary repositories may be configured and reconfigured by simply configuring or reconfiguring the primary repository since the primary will know to ignore secondary configuration options.

New scripting hooks will be needed to synchronize files after tag, admin, and the watch family of operations.

Secondary repository servers will also need to be set up to pull updates from the primary following a proxy event.  This will require an SSH server daemon on the primary similar to the secondary SSH server daemon specified in the previous paragraph.

Authentication
Secondaries will authenticate client connections to the primary server using the same method and authentication tokens used to authenticate to it.

CVS Server Modifications
Only modifications to the behavior of the CVS secondary servers are necessary, other than knowing to ignore secondary configuration options in CVSROOT/config and the addition of the extra scripting hooks to allow for file synchronization after tag, admin, and watch commands.  The primary could continue running a stock CVS without problems using this design if it could ignore unknown configuration options and pull updates could be relied upon.

When a CVS server discovers that it is configured as a secondary, it will only record client communication streams, with the exception of a few requests, like the “expand-modules” request, until it discovers whether the command request will require writing.  If the command will not require writing, then the secondary will rewind the communication stream and process the stream itself.  If the command does require writing, then the secondary will open a connection to the server, replay the communication stream from the client, then turn itself into a transparent proxy for the client-primary connection.  These modifications will require that most of the request handlers in src/server.c become dual-mode and that the command handlers each be altered to either launch the playback processor or the connection to the primary server.

Several new scripting hooks will need to be added:
Hook File Name	Description	
CVSROOT/prewriteproxy	Called when the secondary receives a write request from the client, just prior to becoming a write proxy.  Can be passed the CVSROOT of the primary.	
CVSROOT/postwriteproxy	Called by the secondary when the primary closes the connection, prior to closing the connection to the client and releasing it.  Can be passed the CVSROOT of the primary and a list of updated directories.  May also want to know what command was executed to decide whether to pull CVSROOT/val-tags if it is decided that it is impractical to pull this file every time.	
CVSROOT/posttag	Can be passed info similar to taginfo.  Can be used to push files updated after a tag to secondaries.	
CVSROOT/postadmin	Passed at least a list of directories updated.  Can be used to push files updated after an admin command to secondaries.	
CVSROOT/postwatch	Passed at least a list of directories updated.  Can be used to push CVS/fileattr files updated after a watch or edit command to secondaries.	

Tests
Most of the existing CVS test suite should usable, with minor modifications, to test a secondary/primary configuration.  The steps involved will be to set up two repositories, with the secondary configured to access the primary repository via a :fork: method and a copy-back routine set up in CVSROOT/loginfo.  Most of the tests will then need to be modified to account for the different paths that will be generated in status messages from the client and server.  The existing tests that modify the CVSROOT/config or CVSROOT/loginfo files will either need to be skipped or modified to insure that they do not interfere with the secondary/primary configuration.

Tests are covered in more detail in the Test Plan document.

Documentation
Documentation requirements to have these changes accepted as part of the main CVS source distribution should be minimal.