However, that is not the real meaning of continuous. The real continuous approach comes from Multics,
the machine that was never supposed to shut down and that used
controlled, transparent change. The
developers understood the only constant is change and that migration
for hardware, software, and function
during system operation is necessary.
Therefore, the ability to change was
designed from the very beginning.
Software in particular must be written to evolve as changes happen, using a weakly typed high-level language
and, in older programs, a good macro
assembler. No direct references are allowed to anything if they can be avoided. Every data structure is designed
for expansion and self-identifying
as to version. Every code segment is
made self-identifying by the compiler or other construction procedure.
Code and data are changeable on a
and as few as possible copies of anything are kept, so single copies could
be dynamically updated as necessary.
The most important thing is to
manage interface changes. Even in
the Multics days, it was easy to forget
to change every single instance of an
interface. Today, with distributed programs, changing all possible copies of
an interface at once is going to be insanely difficult, if not flat-out impossible.
Who Does it Right?
BBN Technologies was the first company to perform continuous controlled change when they built the
ARPANET backbone in 1969. They
placed a 1-bit version number in every packet. If it changed from 0 to 1,
it meant that the IMP (router) was to
switch to a new version of its software
and set the bit to 1 on every outgoing
packet. This allowed the entire ARPANET to switch easily to new versions
of the software without interrupting
its operation. That was very important
to the pre-TCP Internet, as it was quite
experimental and suffered a considerable amount of change.
With Multics, the developers did
all of these good things, the most important of which was the discipline
used with data structures: if an interface took more than one parameter,
not like hardware
which is the
return of the item
to its original
an item away from
its original state.
all the parameters were versioned by
placing them in a structure with a version number. The caller set the version, and the recipient checked it. If it
was completely obsolete, it was flatly
rejected. If it was not quite current,
it was processed differently, by being upgraded on input and probably
downgraded on return.
This meant that many different
versions of a program or kernel module could exist simultaneously, while
upgrades took place at the user’s convenience. It also meant that upgrades
could happen automatically and that
multiple sites, multiple suppliers,
and networks didn’t cause problems.
An example of a structure used by
a U.S.-based warehousing company
(translated to C from Multics PL/1)
is illustrated in the accompanying
box. The company bought a Canadian
competitor and needed to add inter-country transfers, initially from three
of its warehouses in border cities.
This, in turn, required the state field
to split into two parts:
char country _ code[ 4]
char state _ province[ 4];
To identify this, the company incremented the version number from 1.0
to 2.0 and arranged for the server to
support both types. New clients used
version 2.0 structures and were able
to ship to Canada. Old ones continued
to use version 1.0 structures. When
the server received a type 1 structure,
it used an “updater” subroutine that
copied the data into a type 2 structure
and set the country code to U.S.
In a more modern language, you
would add a new subclass with a constructor that supports a country code,
and update your new clients to use it.
The process is this:
Update the server. 1.
Change the clients that run in 2.
the three border-state warehouses.
Now they can move items from U.S. to
Deploy updated clients to those 3.
Canadian locations needing to move
Update all of the U.S.-based cli- 4.
ents at their leisure.
Using this approach, there is never
a need to stop the whole system, only
the individual copies, and that can be