3.4.1 Parametric Generation of Initial States
Explicit-state model checkers like Maude are typically quite expressive but only analyze the system from a single initial configuration. To increase coverage, we would like to model check system models for all possible configurations satisfying certain bounds, for example having j transactions and k clients. Despite the wealth of Maude applications, we are not aware of any work doing such comprehensive model checking in Maude. We therefore present a general technique in Maude for model checking a system from a range of different initial configurations.
Specifically, we introduce a new operator init so there is a one-step rewrite init(params) −→ c0 for each possible initial configuration c0 satisfying the given parameter requirements,
and declare a sort for sets of configurations:
sort ConfigSet . subsort Configuration < ConfigSet .
op empty : -> ConfigSet .
op _;_ : ConfigSet ConfigSet -> ConfigSet [assoc comm id: empty] .
We define a function
op initAux : s1 ... sn sn+1 ... sn+m -> ConfigSet .
such that s1 ... sn are the sorts for the user-specified parameters params, and sn+1 ...
sn+m those for the auxiliary parameters params0, and then initAux(params,params0) gen-
erates all possible initial states for such parameters. We also add the following rewrite rule to our model:
var C : Configuration . var CS : ConfigSet .
init’s parameters specify the number of each of the following parameters: read-only, write- only, and read-write transactions; operations for each type of transaction; clients; servers; keys; and replicas per key.
Here we only illustrate how to generate replicas, and how to replicate keys. The entire specification is given at https://github.com/siliunobi/cat.
We start by generating the replica table and key-variable pairs. keyVars consists of “;”- separated key-variable pairs < k1, var1 > ; ... ; < kn, varn >, each of which has a key k
and the associated local variable var. The function kvars extracts KEYS key-variable pairs from keyVars:
--- generate table and key-var pairs:
crl initAux(RTX,WTX,RWTX,ROP,WOP,RWOP,CLS,SVS,KEYS,RF,none)
=> $initAux(RTX,WTX,RWTX,ROP,WOP,RWOP,CLS,SVS,KVARS,genKeyVarSet(KVARS),RF, < 0 : Table | table : initTable(KVARS) >)
if KVARS := kvars(KEYS,keyVars) .
The function initTable initializes the replica table for each key with its replicas of nil:
--- initialize table with generated keys: op initTable : KeyVars -> ReplicaTable .
op $initTable : KeyVars ReplicaTable -> ReplicaTable . eq initTable(KVARS) = $initTable(KVARS,[emptyTable]) . eq $initTable((< K,VAR > ; KVARS),[KEYREPLICAS]) =
$initTable(KVARS,[sites(K,nil) ;; KEYREPLICAS]) . eq $initTable(noKeyVar,[KEYREPLICAS]) = [KEYREPLICAS] .
We now generate replicas, assign the keys to them, and update the replica table accord- ingly.
Example 3.12. Walter replicas are generated with the attributes in Example 3.1:
--- generate Walter replicas:
rl $initAux(RTX,WTX,RWTX,ROP,WOP,RWOP,CLS,s PARS,KVARS,KS,RF,C) => $initAux(RTX,WTX,RWTX,ROP,WOP,RWOP,CLS,PARS,KVARS,KS,RF,C
< s PARS : Walter-Replica | executing : none, committed : none, aborted : none, decided : empty, store : empty, sqn : 0, locked : empty, votes : empty, ... >) .
crl $initAux(RTX,WTX,RWTX,ROP,WOP,RWOP,CLS,0,(< K,VAR > ; KVARS),KS,s RF, < RID : Walter-Replica | store : VS >
< 0 : Table | table : [sites(K,RIDS) ;; KEYREPLICAS] > C)
=> $initAux(RTX,WTX,RWTX,ROP,WOP,RWOP,CLS,0,(< K,VAR > ; KVARS),KS,RF, < RID : Walter-Replica | store : (VS,K |-> (< [0],version(0,0) >)) > < 0 : Table | table : [sites(K,RIDS RID) ;; KEYREPLICAS] > C)
if not $hasMapping(VS,K) .
Note that, to assign a key to a replica, we nondeterministically add a replica RID to key K’s replicating sites. Once the key has been assigned to replication factor replicas, we continue to the next key by resetting the replication factor to rf:
--- next key
rl $initAux(RTX,WTX,RWTX,ROP,WOP,RWOP,CLS,0,(< K,VAR > ; KVARS),KS,0,C) => $initAux(RTX,WTX,RWTX,ROP,WOP,RWOP,CLS,0,KVARS,KS,rf,C) .
3.4.2 The CAT Tool
We have implemented the Consistency Analysis Tool (CAT) that automates the new method for model checking consistency properties explained in this chapter. CAT takes as input:
• A Maude model of the DTS specified as explained in Section 3.1.
• The desired number of each of the following initial state parameters: read-only, write- only, and read-write transactions; operations for each type of transaction; clients; servers; keys; and replicas per key. The tool analyzes the desired property for all initial states having the desired number of each of these parameters.
• The consistency property to be analyzed.
Given these inputs, CAT performs the following steps:
1. adds the monitoring mechanism to the user-provided system model;
2. generates all possible initial states with the user-provided numbers of items for the different parameters; and
3. executes the following command to search, from all generated initial states, for one reachable final state where the consistency property does not hold:
search [1] init =>! C:Configuration
< M:Oid : Monitor | log: LOG:Log clock: N:Nat > such that not consistency-property(LOG:Log) .
where the underlined functions are parametric, and are instantiated by the user inputs; e.g., consistency-property is replaced by the corresponding function rc, psi, nmsi, . . . , or ser, depending on which property to analyze.
CAT outputs either “No solution,” meaning that all runs from all the given initial states satisfy the desired consistency property, or a counterexample (in Maude at the moment) showing a behavior that violates the property.
Table 3.1: Model Checking Results w.r.t. Consistency Properties. “X”, “×”, and “-” refer to satisfying or violating the property, and “not applicable”, respectively.
Maude Model LOC Consistency Property
RC RA CS UA NMSI PSI SI SER SSER
RAMP-F [58] 330 X X × × - - × × × RAMP-F+1PW [57] 302 X X × × - - × × × RAMP-F+FC [57] 305 X X × × - - × × × RAMP-F¬2PC [57] 320 X × × × - - × × × RAMP-S [58] 255 X X × × - - × × × RAMP-S+1PW [57] 237 X X × × - - × × × RAMP-S¬2PC [57] 248 X × × × - - × × × Faster [57] 300 X × × × - - × × × ROLA [59] 411 X X X X - - × × × Jessy [60] 413 X X X X X × × × × Walter [61] 830 X X X X X X × × × P-Store [74] 438 X X X X X X X X × NO WAIT (Chapter 7) 600 X X X X - - X X ×
We have applied our tool to 13 Maude models of state-of-the-art DTSs (different variants of RAMP and Walter, ROLA, Jessy, P-Store, and NO WAIT) against all nine properties (three case studies, namely RAMP, Walter, and ROLA, will be presented in detail in Chapter 4, 5, and 6, respectively). Table 3.1 summarizes our experience with CAT: all model checking results are as expected. It is worth remarking that our automatic analysis found all the violations of properties that the respective systems should violate. There are also some cases where model checking is not applicable (“-” in Table 3.1): some system models do not include a mechanism for committing a transaction on remote servers (i.e., no commit time on any remote server is recorded by the monitor). Thus, model checking NMSI or PSI is not applicable.
We have performed our analysis with different initial states, with up to 4 transactions, 4 operations per transaction, 2 clients, 2 servers, 2 keys, and 2 replicas per key. Each analysis command took about 10 minutes (in the worst case) to execute on a 2.9 GHz Intel 4-Core i7-3520M CPU with 3.6 GB of memory.
Data Availability. The system models, properties specifications, and tool implementation are available at https://github.com/siliunobi/cat.