[cmake-developers] daemon-mode: Infrastructure

Tobias Hunger tobias.hunger at gmail.com
Mon Jun 13 20:00:14 EDT 2016


Hello,

one important piece of feedback from the daemon-mode: Project
structure discussion is that we need a policy to remove old code
again.

So I thought I should write up a bit about the infrastructure and
versioning support of the daemon-mode branch I am working on.

Basic Assumptions:
=================

These are kind of hardcoded into the implementation and hard to change:

* There will always be 1 client talking to a server.
* Client/Server communicate using JSON messages


Implementation Overview:
======================

Basically "daemon-mode" is implemented in the cmServer class. That
class uses libuv to receive requests from a client application and to
react on those requests. There is nothing that stops the cmServer from
also signalling the client about state changes (e.g. CMakeLists.txt
files being changed on disc), but that is not implemented at this
time.

In the constructor of cmServer you can define an arbitrary number of
cmProtocolVersion objects, each with a different version number
(major/minor numbers).

On first connect the cmServer will present the list of supported
protocol versions to the client and the client has to pick one of the
supported versions. The server will call Activate() (do your
initialization here;-) on the cmProtocolVersion object with the
selected version number.

>From that point on the cmProtocolVersion object is responsible for all
further interactions with the client. The cmServer will turn all
incoming messages into cmServerRequest objects and pass those to the
selected cmProtocolVersion's Process(...) method. This method will
return a cmServerResponse object (which can be created from the
cmServerRequest), which the cmServer will send on to the client.


Proposed Versioning:
===================

The protocol version should start at version 1.0.

Any time new functionality is made available to daemon-mode, the minor
version number will be incremented. This includes new commands
becoming available as well as existing commands returning new keys in
addition to sending all the old keys.

Any time a incompatible change (e.g. removal of functionality,
restructuring of responses to requests, etc.) is made, the major
version is incremented and the minor is reset to 0. This includes
removing existing commands or changing the semantics/return types of
keys returned in response to any existing command.

If there was already a matching version bump, then there is no need to
do another till after the next release of cmake made. So two new
functionalities in one development cycle: Still only increase the
minor number by one.


Requesting Protocol Versions:
=========================

Let's assume we are writing a client for cmake-daemon as shipped in
cmake 4.2.4. At that time in the future the protocol version for the
cmake-daemon is at version 1.4 and that is what we test our
application with.

Our client should then request daemon mode to use protocol version 1.4
if available.

If that is not available, then it should just request the highest
minor number for version 1 and use that. That *should* be compatible
with version 1.4.

If there is no more protocol version 1.x supported the client should
abort or at least warn and continue with a higher major version
number.


Implementing new Protocol Versions:
==============================

* minor version bumps: Add a new cmServerProtocol class. Have its
Process(...) method implement the new functionality and then forward
to an instance of the previous version.

The sloppy approach would be to implement the the new functionality in
the previous versions class and just bump its number:-)

* major version bumps: At that point I would copy the existing code of
the previous version into a new cmServerProtocol class and then clean
it up. Then implement the changes in the new class.


Deprecating old Protocol Versions:
============================

I would remove all the code for one major protocol version in one go.
That should be fairly straight forward to do (and the reason why I
suggested to just copy the code into a new major version of the
protocol) and should have little potential for damage.

In general I would suggest keeping old major versions around for at
least three cmake releases, but I would not put hard rules here: If
some old major version does not cost maintenance, then I'd suggest
keeping it longer.

On the other hand, if some changes require a major cmake version bump
(e.g. changing the cmake language in incompatible ways, etc.) so that
major user interaction is required during an update, then I would also
dump all old protocol versions immediately. Such fundamental changes
will probably also reflect deeply in the cmake internal structure,
which will also reflect in the daemon-mode protocol. I do not think it
makes sense to invest heavily into compatibility to old daemon-mode
clients in such an event.


What do you think? Does this make sense?

Best Regards,
Tobias


More information about the cmake-developers mailing list