├── jepsen.atomic ├── nodes ├── atomic-server │ ├── test_server.properties │ ├── README.md │ ├── control.sh │ ├── .gitignore │ ├── stop.sh │ ├── project.clj │ ├── CHANGELOG.md │ ├── src │ │ └── atomic_server │ │ │ └── core.clj │ └── LICENSE ├── run_test.sh ├── .gitignore ├── CHANGELOG.md ├── project.clj ├── control.clj ├── LICENSE └── src │ └── jepsen │ └── atomic.clj ├── .github └── workflows │ └── cloud_code_scan.yml └── README.md /jepsen.atomic/nodes: -------------------------------------------------------------------------------- 1 | jraft.host1 2 | jraft.host2 3 | jraft.host3 4 | jraft.host4 5 | jraft.host5 6 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/test_server.properties: -------------------------------------------------------------------------------- 1 | groupId=atomic 2 | dataPath=/home/admin/atomic-server/data 3 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/README.md: -------------------------------------------------------------------------------- 1 | # atomic-server 2 | 3 | Atomic server project 4 | 5 | `lein run [confFile]` 6 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/control.sh: -------------------------------------------------------------------------------- 1 | nohup java -Xmx512m -Xms512m -jar target/atomic-server-0.1.0-SNAPSHOT-standalone.jar $@ >> atomic.log 2>&1 & 2 | -------------------------------------------------------------------------------- /jepsen.atomic/run_test.sh: -------------------------------------------------------------------------------- 1 | unset SSH_AUTH_SOCK 2 | lein run test --username {user_name} --nodes-file ./nodes --ssh-private-key {ssh_key_path} $@ 3 | -------------------------------------------------------------------------------- /jepsen.atomic/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /.nrepl-port 10 | .hgignore 11 | .hg/ 12 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /.nrepl-port 10 | .hgignore 11 | .hg/ 12 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | pid=`ps -ef |grep atomic-server |grep java |awk -F' ' '{print $2}'` 3 | if [ "$pid" != "" ] 4 | then 5 | echo "kill $pid" 6 | kill $pid 7 | fi 8 | echo "Done!" 9 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/project.clj: -------------------------------------------------------------------------------- 1 | (require 'cemerick.pomegranate.aether) 2 | 3 | (cemerick.pomegranate.aether/register-wagon-factory! 4 | "http" #(org.apache.maven.wagon.providers.http.HttpWagon.)) 5 | 6 | (defproject atomic-server "0.1.0-SNAPSHOT" 7 | :description "atomic-server jepsen test" 8 | :url "" 9 | :license {:name "Eclipse Public License" 10 | :url "http://www.eclipse.org/legal/epl-v10.html"} 11 | :main atomic-server.core 12 | :plugins [[lein-libdir "0.1.1"]] 13 | :dependencies [[org.clojure/clojure "1.9.0"] 14 | [com.alipay.sofa/hessian "3.3.6"] 15 | [com.alipay.sofa/jraft-test "1.2.3"]]) 16 | -------------------------------------------------------------------------------- /.github/workflows/cloud_code_scan.yml: -------------------------------------------------------------------------------- 1 | name: Alipay Cloud Devops Codescan 2 | on: 3 | pull_request_target: 4 | jobs: 5 | stc: # Code security scanning 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: codeScan 9 | uses: layotto/alipay-cloud-devops-codescan@main 10 | with: 11 | parent_uid: ${{ secrets.ALI_PID }} 12 | private_key: ${{ secrets.ALI_PK }} 13 | scan_type: stc 14 | sca: # Open source compliance scanning 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: codeScan 18 | uses: layotto/alipay-cloud-devops-codescan@main 19 | with: 20 | parent_uid: ${{ secrets.ALI_PID }} 21 | private_key: ${{ secrets.ALI_PK }} 22 | scan_type: sca 23 | -------------------------------------------------------------------------------- /jepsen.atomic/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). 3 | 4 | ## [Unreleased] 5 | ### Changed 6 | - Add a new arity to `make-widget-async` to provide a different widget shape. 7 | 8 | ## [0.1.1] - 2018-04-25 9 | ### Changed 10 | - Documentation on how to make the widgets. 11 | 12 | ### Removed 13 | - `make-widget-sync` - we're all async, all the time. 14 | 15 | ### Fixed 16 | - Fixed widget maker to keep working when daylight savings switches over. 17 | 18 | ## 0.1.0 - 2018-04-25 19 | ### Added 20 | - Files from the new template. 21 | - Widget maker public API - `make-widget-sync`. 22 | 23 | [Unreleased]: https://github.com/your-name/jepsen.atomic/compare/0.1.1...HEAD 24 | [0.1.1]: https://github.com/your-name/jepsen.atomic/compare/0.1.0...0.1.1 25 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). 3 | 4 | ## [Unreleased] 5 | ### Changed 6 | - Add a new arity to `make-widget-async` to provide a different widget shape. 7 | 8 | ## [0.1.1] - 2018-04-25 9 | ### Changed 10 | - Documentation on how to make the widgets. 11 | 12 | ### Removed 13 | - `make-widget-sync` - we're all async, all the time. 14 | 15 | ### Fixed 16 | - Fixed widget maker to keep working when daylight savings switches over. 17 | 18 | ## 0.1.0 - 2018-04-25 19 | ### Added 20 | - Files from the new template. 21 | - Widget maker public API - `make-widget-sync`. 22 | 23 | [Unreleased]: https://github.com/your-name/atomic-server/compare/0.1.1...HEAD 24 | [0.1.1]: https://github.com/your-name/atomic-server/compare/0.1.0...0.1.1 25 | -------------------------------------------------------------------------------- /jepsen.atomic/project.clj: -------------------------------------------------------------------------------- 1 | (require 'cemerick.pomegranate.aether) 2 | (cemerick.pomegranate.aether/register-wagon-factory! 3 | "http" #(org.apache.maven.wagon.providers.http.HttpWagon.)) 4 | 5 | (defproject jepsen.atomic "0.1.0-SNAPSHOT" 6 | :description "atimic jepsen test" 7 | :url "" 8 | :license {:name "Eclipse Public License" 9 | :url "http://www.eclipse.org/legal/epl-v10.html"} 10 | :main jepsen.atomic 11 | :jvm-opts ["-Xms6g" "-Xmx6g" "-server" "-XX:+UseG1GC"] 12 | :dependencies [[org.clojure/clojure "1.9.0"] 13 | [jepsen "0.1.8"] 14 | [clj-ssh "0.5.14"] 15 | [cider/cider-nrepl "0.17.0-SNAPSHOT"] 16 | [org.clojure/tools.nrepl "0.2.13" :exclusions [org.clojure/clojure]] 17 | [net.java.dev.jna/jna "4.5.1"] 18 | [com.alipay.sofa/hessian "3.3.6"] 19 | [com.alipay.sofa/jraft-test "1.2.3"]]) 20 | -------------------------------------------------------------------------------- /jepsen.atomic/control.clj: -------------------------------------------------------------------------------- 1 | (defcluster :jraft 2 | :clients [{:host "jraft.host1" :user "admin"} 3 | {:host "jraft.host2" :user "admin"} 4 | {:host "jraft.host3" :user "admin"} 5 | {:host "jraft.host4" :user "admin"} 6 | {:host "jraft.host5" :user "admin"}]) 7 | 8 | (deftask :date "echo date on cluster" [] 9 | (ssh "date")) 10 | 11 | (deftask :build [] 12 | (local 13 | (run 14 | (cd "atomic-server" 15 | (run 16 | "lein clean ; lein uberjar")))) 17 | (local (run "rm atomic-server.tar.gz; tar zcvf atomic-server.tar.gz atomic-server/target atomic-server/control.sh atomic-server/stop.sh atomic-server/test_server.properties"))) 18 | 19 | 20 | (deftask :deploy [] 21 | (scp "atomic-server.tar.gz" "/home/admin/") 22 | (ssh 23 | (run 24 | (cd "/home/admin" 25 | (run "rm -rf atomic-server/") 26 | (run "tar zxvf atomic-server.tar.gz"))))) 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jepsen.atomic 2 | 3 | A Clojure library designed to test jraft-test atomic server consistence. 4 | 5 | ## Usage 6 | 7 | Edit `nodes` file: 8 | 9 | ``` 10 | jraft.host1 11 | jraft.host2 12 | jraft.host4 13 | jraft.host5 14 | ``` 15 | 16 | Every node should install [jepsen](https://github.com/jepsen-io/jepsen). 17 | 18 | Deploy the atomic-server with [clojure-control](https://github.com/killme2008/clojure-control): 19 | 20 | ``` 21 | control run jraft build 22 | control run jraft deploy 23 | ``` 24 | 25 | Run the test: 26 | 27 | ``` 28 | bash run_test.sh --testfn 29 | ``` 30 | 31 | Valid test include: 32 | 33 | * configuration-test: remove and add a random node. 34 | * bridge-test: weaving the network into happy little intersecting majority rings 35 | * pause-test: pausing random node with SIGSTOP/SIGCONT. 36 | * crash-test: killing random nodes and restarting them. 37 | * partition-test: Cuts the network into randomly chosen halves. 38 | * partition-majority-test: Cuts the network into randomly majority groups. 39 | 40 | 41 | Other options: 42 | 43 | * `--time-limit 120`: test time limit 44 | * `--concurrency 10`: test concurrency 45 | 46 | 47 | Watch the report at [http://localhost:8080](http://localhost:8080). 48 | 49 | 50 | ## License 51 | 52 | Copyright © 2018 alipay.com 53 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/src/atomic_server/core.clj: -------------------------------------------------------------------------------- 1 | (ns atomic-server.core 2 | (:gen-class) 3 | (:import [com.alipay.sofa.jraft.test.atomic.server AtomicServer] 4 | [com.alipay.sofa.jraft.option CliOptions] 5 | [com.alipay.sofa.jraft 6 | JRaftUtils 7 | CliService 8 | Status 9 | RaftServiceFactory])) 10 | 11 | (defonce group-id "atomic_0") 12 | 13 | (defn- ^CliService get-cli-service [] 14 | (RaftServiceFactory/createAndInitCliService (CliOptions.))) 15 | 16 | (defn leave [node conf] 17 | (let [cli (get-cli-service)] 18 | (let [^Status status (.removePeer cli 19 | group-id 20 | (JRaftUtils/getConfiguration conf) 21 | (JRaftUtils/getPeerId node))] 22 | (when-not (.isOk status) 23 | (println "Leave node failed." {:node node :conf conf :status status})) 24 | (System/exit 0)))) 25 | 26 | (defn join [node conf] 27 | (let [cli (get-cli-service)] 28 | (let [^Status status (.addPeer cli 29 | group-id 30 | (JRaftUtils/getConfiguration conf) 31 | (JRaftUtils/getPeerId node))] 32 | (when-not (.isOk status) 33 | (println "Join node failed." {:node node :conf conf :status status})) 34 | (System/exit 0)))) 35 | 36 | (defn -main [& [cmd & rest]] 37 | (when (empty? cmd) 38 | (throw (ex-info "empty cmd" {:cmd cmd}))) 39 | (case cmd 40 | "start" (AtomicServer/start (first rest)) 41 | "leave" (leave (first rest) (second rest)) 42 | "join" (join (first rest) (second rest)) 43 | (throw (ex-info "Unknown cmd" {:cmd cmd})))) 44 | -------------------------------------------------------------------------------- /jepsen.atomic/LICENSE: -------------------------------------------------------------------------------- 1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 4 | 5 | 1. DEFINITIONS 6 | 7 | "Contribution" means: 8 | 9 | a) in the case of the initial Contributor, the initial code and 10 | documentation distributed under this Agreement, and 11 | 12 | b) in the case of each subsequent Contributor: 13 | 14 | i) changes to the Program, and 15 | 16 | ii) additions to the Program; 17 | 18 | where such changes and/or additions to the Program originate from and are 19 | distributed by that particular Contributor. A Contribution 'originates' from 20 | a Contributor if it was added to the Program by such Contributor itself or 21 | anyone acting on such Contributor's behalf. Contributions do not include 22 | additions to the Program which: (i) are separate modules of software 23 | distributed in conjunction with the Program under their own license 24 | agreement, and (ii) are not derivative works of the Program. 25 | 26 | "Contributor" means any person or entity that distributes the Program. 27 | 28 | "Licensed Patents" mean patent claims licensable by a Contributor which are 29 | necessarily infringed by the use or sale of its Contribution alone or when 30 | combined with the Program. 31 | 32 | "Program" means the Contributions distributed in accordance with this 33 | Agreement. 34 | 35 | "Recipient" means anyone who receives the Program under this Agreement, 36 | including all Contributors. 37 | 38 | 2. GRANT OF RIGHTS 39 | 40 | a) Subject to the terms of this Agreement, each Contributor hereby grants 41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 42 | reproduce, prepare derivative works of, publicly display, publicly perform, 43 | distribute and sublicense the Contribution of such Contributor, if any, and 44 | such derivative works, in source code and object code form. 45 | 46 | b) Subject to the terms of this Agreement, each Contributor hereby grants 47 | Recipient a non-exclusive, worldwide, royalty-free patent license under 48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 49 | transfer the Contribution of such Contributor, if any, in source code and 50 | object code form. This patent license shall apply to the combination of the 51 | Contribution and the Program if, at the time the Contribution is added by the 52 | Contributor, such addition of the Contribution causes such combination to be 53 | covered by the Licensed Patents. The patent license shall not apply to any 54 | other combinations which include the Contribution. No hardware per se is 55 | licensed hereunder. 56 | 57 | c) Recipient understands that although each Contributor grants the licenses 58 | to its Contributions set forth herein, no assurances are provided by any 59 | Contributor that the Program does not infringe the patent or other 60 | intellectual property rights of any other entity. Each Contributor disclaims 61 | any liability to Recipient for claims brought by any other entity based on 62 | infringement of intellectual property rights or otherwise. As a condition to 63 | exercising the rights and licenses granted hereunder, each Recipient hereby 64 | assumes sole responsibility to secure any other intellectual property rights 65 | needed, if any. For example, if a third party patent license is required to 66 | allow Recipient to distribute the Program, it is Recipient's responsibility 67 | to acquire that license before distributing the Program. 68 | 69 | d) Each Contributor represents that to its knowledge it has sufficient 70 | copyright rights in its Contribution, if any, to grant the copyright license 71 | set forth in this Agreement. 72 | 73 | 3. REQUIREMENTS 74 | 75 | A Contributor may choose to distribute the Program in object code form under 76 | its own license agreement, provided that: 77 | 78 | a) it complies with the terms and conditions of this Agreement; and 79 | 80 | b) its license agreement: 81 | 82 | i) effectively disclaims on behalf of all Contributors all warranties and 83 | conditions, express and implied, including warranties or conditions of title 84 | and non-infringement, and implied warranties or conditions of merchantability 85 | and fitness for a particular purpose; 86 | 87 | ii) effectively excludes on behalf of all Contributors all liability for 88 | damages, including direct, indirect, special, incidental and consequential 89 | damages, such as lost profits; 90 | 91 | iii) states that any provisions which differ from this Agreement are offered 92 | by that Contributor alone and not by any other party; and 93 | 94 | iv) states that source code for the Program is available from such 95 | Contributor, and informs licensees how to obtain it in a reasonable manner on 96 | or through a medium customarily used for software exchange. 97 | 98 | When the Program is made available in source code form: 99 | 100 | a) it must be made available under this Agreement; and 101 | 102 | b) a copy of this Agreement must be included with each copy of the Program. 103 | 104 | Contributors may not remove or alter any copyright notices contained within 105 | the Program. 106 | 107 | Each Contributor must identify itself as the originator of its Contribution, 108 | if any, in a manner that reasonably allows subsequent Recipients to identify 109 | the originator of the Contribution. 110 | 111 | 4. COMMERCIAL DISTRIBUTION 112 | 113 | Commercial distributors of software may accept certain responsibilities with 114 | respect to end users, business partners and the like. While this license is 115 | intended to facilitate the commercial use of the Program, the Contributor who 116 | includes the Program in a commercial product offering should do so in a 117 | manner which does not create potential liability for other Contributors. 118 | Therefore, if a Contributor includes the Program in a commercial product 119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend 120 | and indemnify every other Contributor ("Indemnified Contributor") against any 121 | losses, damages and costs (collectively "Losses") arising from claims, 122 | lawsuits and other legal actions brought by a third party against the 123 | Indemnified Contributor to the extent caused by the acts or omissions of such 124 | Commercial Contributor in connection with its distribution of the Program in 125 | a commercial product offering. The obligations in this section do not apply 126 | to any claims or Losses relating to any actual or alleged intellectual 127 | property infringement. In order to qualify, an Indemnified Contributor must: 128 | a) promptly notify the Commercial Contributor in writing of such claim, and 129 | b) allow the Commercial Contributor to control, and cooperate with the 130 | Commercial Contributor in, the defense and any related settlement 131 | negotiations. The Indemnified Contributor may participate in any such claim 132 | at its own expense. 133 | 134 | For example, a Contributor might include the Program in a commercial product 135 | offering, Product X. That Contributor is then a Commercial Contributor. If 136 | that Commercial Contributor then makes performance claims, or offers 137 | warranties related to Product X, those performance claims and warranties are 138 | such Commercial Contributor's responsibility alone. Under this section, the 139 | Commercial Contributor would have to defend claims against the other 140 | Contributors related to those performance claims and warranties, and if a 141 | court requires any other Contributor to pay any damages as a result, the 142 | Commercial Contributor must pay those damages. 143 | 144 | 5. NO WARRANTY 145 | 146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON 147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER 148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR 149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A 150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the 151 | appropriateness of using and distributing the Program and assumes all risks 152 | associated with its exercise of rights under this Agreement , including but 153 | not limited to the risks and costs of program errors, compliance with 154 | applicable laws, damage to or loss of data, programs or equipment, and 155 | unavailability or interruption of operations. 156 | 157 | 6. DISCLAIMER OF LIABILITY 158 | 159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 166 | OF SUCH DAMAGES. 167 | 168 | 7. GENERAL 169 | 170 | If any provision of this Agreement is invalid or unenforceable under 171 | applicable law, it shall not affect the validity or enforceability of the 172 | remainder of the terms of this Agreement, and without further action by the 173 | parties hereto, such provision shall be reformed to the minimum extent 174 | necessary to make such provision valid and enforceable. 175 | 176 | If Recipient institutes patent litigation against any entity (including a 177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 178 | (excluding combinations of the Program with other software or hardware) 179 | infringes such Recipient's patent(s), then such Recipient's rights granted 180 | under Section 2(b) shall terminate as of the date such litigation is filed. 181 | 182 | All Recipient's rights under this Agreement shall terminate if it fails to 183 | comply with any of the material terms or conditions of this Agreement and 184 | does not cure such failure in a reasonable period of time after becoming 185 | aware of such noncompliance. If all Recipient's rights under this Agreement 186 | terminate, Recipient agrees to cease use and distribution of the Program as 187 | soon as reasonably practicable. However, Recipient's obligations under this 188 | Agreement and any licenses granted by Recipient relating to the Program shall 189 | continue and survive. 190 | 191 | Everyone is permitted to copy and distribute copies of this Agreement, but in 192 | order to avoid inconsistency the Agreement is copyrighted and may only be 193 | modified in the following manner. The Agreement Steward reserves the right to 194 | publish new versions (including revisions) of this Agreement from time to 195 | time. No one other than the Agreement Steward has the right to modify this 196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 197 | Eclipse Foundation may assign the responsibility to serve as the Agreement 198 | Steward to a suitable separate entity. Each new version of the Agreement will 199 | be given a distinguishing version number. The Program (including 200 | Contributions) may always be distributed subject to the version of the 201 | Agreement under which it was received. In addition, after a new version of 202 | the Agreement is published, Contributor may elect to distribute the Program 203 | (including its Contributions) under the new version. Except as expressly 204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 205 | licenses to the intellectual property of any Contributor under this 206 | Agreement, whether expressly, by implication, estoppel or otherwise. All 207 | rights in the Program not expressly granted under this Agreement are 208 | reserved. 209 | 210 | This Agreement is governed by the laws of the State of New York and the 211 | intellectual property laws of the United States of America. No party to this 212 | Agreement will bring a legal action under this Agreement more than one year 213 | after the cause of action arose. Each party waives its rights to a jury trial 214 | in any resulting litigation. 215 | -------------------------------------------------------------------------------- /jepsen.atomic/atomic-server/LICENSE: -------------------------------------------------------------------------------- 1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 4 | 5 | 1. DEFINITIONS 6 | 7 | "Contribution" means: 8 | 9 | a) in the case of the initial Contributor, the initial code and 10 | documentation distributed under this Agreement, and 11 | 12 | b) in the case of each subsequent Contributor: 13 | 14 | i) changes to the Program, and 15 | 16 | ii) additions to the Program; 17 | 18 | where such changes and/or additions to the Program originate from and are 19 | distributed by that particular Contributor. A Contribution 'originates' from 20 | a Contributor if it was added to the Program by such Contributor itself or 21 | anyone acting on such Contributor's behalf. Contributions do not include 22 | additions to the Program which: (i) are separate modules of software 23 | distributed in conjunction with the Program under their own license 24 | agreement, and (ii) are not derivative works of the Program. 25 | 26 | "Contributor" means any person or entity that distributes the Program. 27 | 28 | "Licensed Patents" mean patent claims licensable by a Contributor which are 29 | necessarily infringed by the use or sale of its Contribution alone or when 30 | combined with the Program. 31 | 32 | "Program" means the Contributions distributed in accordance with this 33 | Agreement. 34 | 35 | "Recipient" means anyone who receives the Program under this Agreement, 36 | including all Contributors. 37 | 38 | 2. GRANT OF RIGHTS 39 | 40 | a) Subject to the terms of this Agreement, each Contributor hereby grants 41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 42 | reproduce, prepare derivative works of, publicly display, publicly perform, 43 | distribute and sublicense the Contribution of such Contributor, if any, and 44 | such derivative works, in source code and object code form. 45 | 46 | b) Subject to the terms of this Agreement, each Contributor hereby grants 47 | Recipient a non-exclusive, worldwide, royalty-free patent license under 48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 49 | transfer the Contribution of such Contributor, if any, in source code and 50 | object code form. This patent license shall apply to the combination of the 51 | Contribution and the Program if, at the time the Contribution is added by the 52 | Contributor, such addition of the Contribution causes such combination to be 53 | covered by the Licensed Patents. The patent license shall not apply to any 54 | other combinations which include the Contribution. No hardware per se is 55 | licensed hereunder. 56 | 57 | c) Recipient understands that although each Contributor grants the licenses 58 | to its Contributions set forth herein, no assurances are provided by any 59 | Contributor that the Program does not infringe the patent or other 60 | intellectual property rights of any other entity. Each Contributor disclaims 61 | any liability to Recipient for claims brought by any other entity based on 62 | infringement of intellectual property rights or otherwise. As a condition to 63 | exercising the rights and licenses granted hereunder, each Recipient hereby 64 | assumes sole responsibility to secure any other intellectual property rights 65 | needed, if any. For example, if a third party patent license is required to 66 | allow Recipient to distribute the Program, it is Recipient's responsibility 67 | to acquire that license before distributing the Program. 68 | 69 | d) Each Contributor represents that to its knowledge it has sufficient 70 | copyright rights in its Contribution, if any, to grant the copyright license 71 | set forth in this Agreement. 72 | 73 | 3. REQUIREMENTS 74 | 75 | A Contributor may choose to distribute the Program in object code form under 76 | its own license agreement, provided that: 77 | 78 | a) it complies with the terms and conditions of this Agreement; and 79 | 80 | b) its license agreement: 81 | 82 | i) effectively disclaims on behalf of all Contributors all warranties and 83 | conditions, express and implied, including warranties or conditions of title 84 | and non-infringement, and implied warranties or conditions of merchantability 85 | and fitness for a particular purpose; 86 | 87 | ii) effectively excludes on behalf of all Contributors all liability for 88 | damages, including direct, indirect, special, incidental and consequential 89 | damages, such as lost profits; 90 | 91 | iii) states that any provisions which differ from this Agreement are offered 92 | by that Contributor alone and not by any other party; and 93 | 94 | iv) states that source code for the Program is available from such 95 | Contributor, and informs licensees how to obtain it in a reasonable manner on 96 | or through a medium customarily used for software exchange. 97 | 98 | When the Program is made available in source code form: 99 | 100 | a) it must be made available under this Agreement; and 101 | 102 | b) a copy of this Agreement must be included with each copy of the Program. 103 | 104 | Contributors may not remove or alter any copyright notices contained within 105 | the Program. 106 | 107 | Each Contributor must identify itself as the originator of its Contribution, 108 | if any, in a manner that reasonably allows subsequent Recipients to identify 109 | the originator of the Contribution. 110 | 111 | 4. COMMERCIAL DISTRIBUTION 112 | 113 | Commercial distributors of software may accept certain responsibilities with 114 | respect to end users, business partners and the like. While this license is 115 | intended to facilitate the commercial use of the Program, the Contributor who 116 | includes the Program in a commercial product offering should do so in a 117 | manner which does not create potential liability for other Contributors. 118 | Therefore, if a Contributor includes the Program in a commercial product 119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend 120 | and indemnify every other Contributor ("Indemnified Contributor") against any 121 | losses, damages and costs (collectively "Losses") arising from claims, 122 | lawsuits and other legal actions brought by a third party against the 123 | Indemnified Contributor to the extent caused by the acts or omissions of such 124 | Commercial Contributor in connection with its distribution of the Program in 125 | a commercial product offering. The obligations in this section do not apply 126 | to any claims or Losses relating to any actual or alleged intellectual 127 | property infringement. In order to qualify, an Indemnified Contributor must: 128 | a) promptly notify the Commercial Contributor in writing of such claim, and 129 | b) allow the Commercial Contributor to control, and cooperate with the 130 | Commercial Contributor in, the defense and any related settlement 131 | negotiations. The Indemnified Contributor may participate in any such claim 132 | at its own expense. 133 | 134 | For example, a Contributor might include the Program in a commercial product 135 | offering, Product X. That Contributor is then a Commercial Contributor. If 136 | that Commercial Contributor then makes performance claims, or offers 137 | warranties related to Product X, those performance claims and warranties are 138 | such Commercial Contributor's responsibility alone. Under this section, the 139 | Commercial Contributor would have to defend claims against the other 140 | Contributors related to those performance claims and warranties, and if a 141 | court requires any other Contributor to pay any damages as a result, the 142 | Commercial Contributor must pay those damages. 143 | 144 | 5. NO WARRANTY 145 | 146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON 147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER 148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR 149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A 150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the 151 | appropriateness of using and distributing the Program and assumes all risks 152 | associated with its exercise of rights under this Agreement , including but 153 | not limited to the risks and costs of program errors, compliance with 154 | applicable laws, damage to or loss of data, programs or equipment, and 155 | unavailability or interruption of operations. 156 | 157 | 6. DISCLAIMER OF LIABILITY 158 | 159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 166 | OF SUCH DAMAGES. 167 | 168 | 7. GENERAL 169 | 170 | If any provision of this Agreement is invalid or unenforceable under 171 | applicable law, it shall not affect the validity or enforceability of the 172 | remainder of the terms of this Agreement, and without further action by the 173 | parties hereto, such provision shall be reformed to the minimum extent 174 | necessary to make such provision valid and enforceable. 175 | 176 | If Recipient institutes patent litigation against any entity (including a 177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 178 | (excluding combinations of the Program with other software or hardware) 179 | infringes such Recipient's patent(s), then such Recipient's rights granted 180 | under Section 2(b) shall terminate as of the date such litigation is filed. 181 | 182 | All Recipient's rights under this Agreement shall terminate if it fails to 183 | comply with any of the material terms or conditions of this Agreement and 184 | does not cure such failure in a reasonable period of time after becoming 185 | aware of such noncompliance. If all Recipient's rights under this Agreement 186 | terminate, Recipient agrees to cease use and distribution of the Program as 187 | soon as reasonably practicable. However, Recipient's obligations under this 188 | Agreement and any licenses granted by Recipient relating to the Program shall 189 | continue and survive. 190 | 191 | Everyone is permitted to copy and distribute copies of this Agreement, but in 192 | order to avoid inconsistency the Agreement is copyrighted and may only be 193 | modified in the following manner. The Agreement Steward reserves the right to 194 | publish new versions (including revisions) of this Agreement from time to 195 | time. No one other than the Agreement Steward has the right to modify this 196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 197 | Eclipse Foundation may assign the responsibility to serve as the Agreement 198 | Steward to a suitable separate entity. Each new version of the Agreement will 199 | be given a distinguishing version number. The Program (including 200 | Contributions) may always be distributed subject to the version of the 201 | Agreement under which it was received. In addition, after a new version of 202 | the Agreement is published, Contributor may elect to distribute the Program 203 | (including its Contributions) under the new version. Except as expressly 204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 205 | licenses to the intellectual property of any Contributor under this 206 | Agreement, whether expressly, by implication, estoppel or otherwise. All 207 | rights in the Program not expressly granted under this Agreement are 208 | reserved. 209 | 210 | This Agreement is governed by the laws of the State of New York and the 211 | intellectual property laws of the United States of America. No party to this 212 | Agreement will bring a legal action under this Agreement more than one year 213 | after the cause of action arose. Each party waives its rights to a jury trial 214 | in any resulting litigation. 215 | -------------------------------------------------------------------------------- /jepsen.atomic/src/jepsen/atomic.clj: -------------------------------------------------------------------------------- 1 | (ns jepsen.atomic 2 | (:import [com.alipay.sofa.jraft.test.atomic.client AtomicClient] 3 | [com.alipay.sofa.jraft.test.atomic KeyNotFoundException] 4 | [com.alipay.sofa.jraft.entity PeerId] 5 | [knossos.model Model] 6 | [com.alipay.sofa.jraft JRaftUtils]) 7 | (:require [clojure.tools.cli :refer [parse-opts]]) 8 | (:require [clojure.tools.logging :refer :all] 9 | [clojure.string :as cstr] 10 | [jepsen.checker.timeline :as timeline] 11 | [jepsen 12 | [nemesis :as nemesis] 13 | [checker :as checker] 14 | [independent :as independent] 15 | [cli :as cli] 16 | [client :as client] 17 | [control :as c] 18 | [db :as db] 19 | [generator :as gen] 20 | [tests :as tests]] 21 | [knossos.model :as model] 22 | [jepsen.control.util :as cu] 23 | [jepsen.os :as os])) 24 | 25 | (defonce atomic-path "/home/admin/atomic-server") 26 | (defonce atomic-bin "java") 27 | (defonce atomic-port 8609) 28 | (defonce atomic-control "control.sh") 29 | (defonce atomic-stop "stop.sh") 30 | 31 | (defn peer-str [node] 32 | (str node ":" atomic-port)) 33 | 34 | (defn initial-cluster 35 | "Constructs an initial cluster string for a test, like 36 | \"foo:8609,bar:8609,...\"" 37 | [test] 38 | (->> (:nodes test) 39 | (map (fn [node] 40 | (peer-str node))) 41 | (cstr/join ","))) 42 | 43 | (defn- ^PeerId peer [node] 44 | (PeerId. node atomic-port)) 45 | 46 | (defn start! [node] 47 | (info "Start" node) 48 | (c/cd atomic-path 49 | (c/exec :sh 50 | atomic-control 51 | "start" 52 | "server.properties"))) 53 | 54 | (defn stop! [node] 55 | (info "Stop" node) 56 | (c/cd atomic-path 57 | (c/exec :sh 58 | atomic-stop))) 59 | 60 | (defn join! [node test] 61 | (let [conf (->> test 62 | :nodes 63 | (remove #(= node %)) 64 | (map peer-str) 65 | (cstr/join ",")) 66 | node (peer-str node)] 67 | (info "Join" node) 68 | (c/cd atomic-path 69 | (c/exec :sh 70 | atomic-control 71 | "join" 72 | node 73 | conf) 74 | (c/exec :sleep 5)))) 75 | 76 | (defn leave! [node test] 77 | (let [conf (initial-cluster test) 78 | node (peer-str node)] 79 | (info "Join" node) 80 | (c/cd atomic-path 81 | (c/exec :sh 82 | atomic-control 83 | "leave" 84 | node 85 | conf) 86 | (c/exec :sleep 5)))) 87 | 88 | ;;DB 89 | (defn db 90 | "Atomic DB for a particular version." 91 | [version] 92 | (reify db/DB 93 | (setup! [_ test node] 94 | (c/cd atomic-path 95 | (c/exec* "cp test_server.properties server.properties")) 96 | (c/cd atomic-path 97 | (info (c/exec* 98 | "echo serverAddress=`hostname`:8609 >> server.properties")) 99 | (info (c/exec* 100 | (format "echo %s >> server.properties" 101 | (str "conf=" (initial-cluster test))))) 102 | (info (c/exec* 103 | (format "echo totalSlots=%d >> server.properties" 104 | (:slots test))))) 105 | (start! node) 106 | (Thread/sleep 10000)) 107 | 108 | (teardown! [_ test node] 109 | (stop! node) 110 | (Thread/sleep 5000) 111 | (c/cd atomic-path 112 | (c/exec :rm 113 | :-rf 114 | "data/"))))) 115 | 116 | ;;client 117 | (defn r [_ _] {:type :invoke, :f :read, :value nil}) 118 | (defn w [_ _] {:type :invoke, :f :write, :value (rand-int 5)}) 119 | (defn cas [_ _] {:type :invoke, :f :cas, :value [(rand-int 5) (rand-int 5)]}) 120 | 121 | (defonce read-from-quorum? (atom false)) 122 | 123 | (defn- read 124 | "Get counter from atomic server by key." 125 | [client key] 126 | (try 127 | (-> client 128 | :conn 129 | (.get key @read-from-quorum?)) 130 | (catch KeyNotFoundException _ 131 | 0))) 132 | 133 | (defn- write 134 | "write a key/value to atomic server" 135 | [client key value] 136 | (when-not (-> client 137 | :conn 138 | (.set key value)) 139 | (throw (ex-info "Fail to set" {:key key :value value})))) 140 | 141 | (defn- compare-and-set 142 | "Compare and set value for key" 143 | [client key old new] 144 | (-> client 145 | :conn 146 | (.compareAndSet key old new))) 147 | 148 | (defn- add-and-get 149 | [client key delta] 150 | (-> client 151 | :conn 152 | (.addAndGet key delta))) 153 | 154 | (defn- create-client0 [test] 155 | (doto (AtomicClient. "atomic" 156 | (JRaftUtils/getConfiguration (initial-cluster test))) 157 | (.start))) 158 | 159 | (def create-client (memoize create-client0)) 160 | 161 | (defrecord Client [conn] 162 | client/Client 163 | (open! [this test node] 164 | (-> this 165 | (assoc :node node) 166 | (assoc :conn (create-client test)))) 167 | (setup! [this test]) 168 | (invoke! [this test op] 169 | (let [[kk v] (:value op) 170 | k (str kk) 171 | crash (if (= :read (:f op)) :fail :info)] 172 | (try 173 | (case (:f op) 174 | :read (assoc op :type :ok :value (independent/tuple kk (read this k))) 175 | :write (do 176 | (write this k v) 177 | (assoc op :type :ok)) 178 | :cas (let [[old new] v] 179 | (assoc op :type (if (compare-and-set this k old new) 180 | :ok 181 | :fail)))) 182 | (catch Exception e 183 | (let [^String msg (.getMessage e)] 184 | (cond 185 | (and msg (.contains msg "TIMEOUT")) (assoc op :type crash, :error :timeout) 186 | :else 187 | (assoc op :type crash :error (.getMessage e)))))))) 188 | 189 | (teardown! [this test]) 190 | 191 | (close! [this test] 192 | #_(-> this 193 | :conn 194 | (.shutdown)) 195 | )) 196 | 197 | 198 | (defrecord SingleKeyClient [k conn] 199 | client/Client 200 | (open! [this test node] 201 | (-> this 202 | (assoc :node node) 203 | (assoc :conn (create-client test)))) 204 | (setup! [this test]) 205 | (invoke! [this test op] 206 | (let [v (:value op) 207 | crash (if (= :read (:f op)) :fail :info)] 208 | (try 209 | (case (:f op) 210 | :read (assoc op :type :ok :value (read this k)) 211 | :write (do 212 | (write this k v) 213 | (assoc op :type :ok)) 214 | :cas (let [[old new] v] 215 | (assoc op :type (if (compare-and-set this k old new) 216 | :ok 217 | :fail)))) 218 | (catch Exception e 219 | (let [^String msg (.getMessage e)] 220 | (cond 221 | (and msg (.contains msg "TIMEOUT")) (assoc op :type crash, :error :timeout) 222 | (and msg (.contains msg "Create connection failed")) (assoc op :type crash :error :disconnected) 223 | :else 224 | (assoc op :type crash :error (.getMessage e)))))))) 225 | 226 | (teardown! [this test]) 227 | 228 | (close! [this test] 229 | #_(-> this 230 | :conn 231 | (.shutdown)) 232 | )) 233 | 234 | 235 | (defn mostly-small-nonempty-subset 236 | "Returns a subset of the given collection, with a logarithmically decreasing 237 | probability of selecting more elements. Always selects at least one element. 238 | 239 | (->> #(mostly-small-nonempty-subset [1 2 3 4 5]) 240 | repeatedly 241 | (map count) 242 | (take 10000) 243 | frequencies 244 | sort) 245 | ; => ([1 3824] [2 2340] [3 1595] [4 1266] [5 975])" 246 | [xs] 247 | (-> xs 248 | count 249 | inc 250 | Math/log 251 | rand 252 | Math/exp 253 | long 254 | (take (shuffle xs)))) 255 | 256 | (def crash-nemesis 257 | "A nemesis that crashes a random subset of nodes." 258 | (nemesis/node-start-stopper 259 | mostly-small-nonempty-subset 260 | (fn start [test node] (stop! node) [:killed node]) 261 | (fn stop [test node] (start! node) [:restarted node]))) 262 | 263 | (def configuration-nemesis 264 | "A nemesis that add/remove a random node." 265 | (nemesis/node-start-stopper 266 | rand-nth 267 | (fn start [test node] (leave! node test) [:removed node]) 268 | (fn stop [test node] (join! node test) [:added node]))) 269 | 270 | (defn rand-key 271 | "Generate a random integer key." 272 | [] 273 | (rand-int 100)) 274 | 275 | (defn atomic-test 276 | "Defaults for testing atomic." 277 | [name opts] 278 | (merge tests/noop-test 279 | {:name name 280 | :os os/noop 281 | :db (db "0.0.1") 282 | :client (Client. nil) 283 | :model (model/cas-register 0) 284 | :checker (checker/compose 285 | {:perf (checker/perf) 286 | :indep (independent/checker 287 | (checker/compose 288 | {:timeline (timeline/html) 289 | :linear (checker/linearizable)}))}) 290 | } 291 | opts)) 292 | 293 | (defn create-test 294 | "A generic create test." 295 | [name opts] 296 | (atomic-test (str "atomic." name) 297 | opts)) 298 | 299 | (defn recover 300 | "A generator which stops the nemesis and allows some time for recovery." 301 | [] 302 | (gen/nemesis 303 | (gen/phases 304 | (gen/once {:type :info, :f :stop}) 305 | (gen/sleep 20)))) 306 | 307 | (defn read-once 308 | "A generator which reads exactly once." 309 | [] 310 | (gen/clients 311 | (gen/once {:type :invoke, :f :read}))) 312 | 313 | (defn partition-test 314 | "Cuts the network into randomly chosen halves." 315 | [opts] 316 | (create-test "partition" 317 | (merge opts 318 | {:nemesis (nemesis/partition-random-halves) 319 | :generator (->> (independent/concurrent-generator 320 | (:concurrency opts 5) 321 | (range) 322 | (fn [k] 323 | (->> (gen/mix [r w cas]) 324 | (gen/stagger (/ (:rate opts))) 325 | (gen/limit (:ops-per-key opts))))) 326 | (gen/nemesis 327 | (gen/seq (cycle [(gen/sleep 5) 328 | {:type :info, :f :start} 329 | (gen/sleep 5) 330 | {:type :info, :f :stop}]))) 331 | (gen/time-limit (:time-limit opts)))}))) 332 | 333 | (defn crash-test 334 | "killing random nodes and restarting them." 335 | [opts] 336 | (create-test "crash" 337 | (merge opts 338 | {:nemesis crash-nemesis 339 | :client (SingleKeyClient. "a" nil) 340 | :checker (checker/compose 341 | {:perf (checker/perf) 342 | :linear (checker/linearizable) 343 | :timeline (timeline/html)}) 344 | :generator (gen/phases 345 | (->> gen/cas 346 | (gen/stagger 1/10) 347 | (gen/delay 1/10) 348 | (gen/nemesis 349 | (gen/seq 350 | (cycle [(gen/sleep 10) 351 | {:type :info :f :start} 352 | (gen/sleep 10) 353 | {:type :info :f :stop}]))) 354 | (gen/time-limit 120)) 355 | (recover) 356 | (read-once))}))) 357 | 358 | (defn pause-test 359 | "pausing random node with SIGSTOP/SIGCONT." 360 | [opts] 361 | (create-test "pause" 362 | (merge 363 | {:nemesis (nemesis/hammer-time atomic-bin) 364 | :client (SingleKeyClient. "a" nil) 365 | :checker (checker/compose 366 | {:perf (checker/perf) 367 | :linear (checker/linearizable) 368 | :timeline (timeline/html)}) 369 | :generator (gen/phases 370 | (->> gen/cas 371 | (gen/stagger 1/10) 372 | (gen/delay 1/10) 373 | (gen/nemesis 374 | (gen/seq 375 | (cycle [(gen/sleep 10) 376 | {:type :info :f :start} 377 | (gen/sleep 10) 378 | {:type :info :f :stop}]))) 379 | (gen/time-limit 120)) 380 | (recover) 381 | (read-once))} 382 | opts))) 383 | 384 | 385 | (defn bridge-test 386 | "weaving the network into happy little intersecting majority rings" 387 | [opts] 388 | (create-test "bridge" 389 | (merge 390 | {:nemesis (nemesis/partitioner (comp nemesis/bridge shuffle)) 391 | :client (SingleKeyClient. "a" nil) 392 | :checker (checker/compose 393 | {:perf (checker/perf) 394 | :linear (checker/linearizable) 395 | :timeline (timeline/html)}) 396 | :generator (gen/phases 397 | (->> gen/cas 398 | (gen/stagger 1/10) 399 | (gen/delay 1/10) 400 | (gen/nemesis 401 | (gen/seq 402 | (cycle [(gen/sleep 10) 403 | {:type :info :f :start} 404 | (gen/sleep 10) 405 | {:type :info :f :stop}]))) 406 | (gen/time-limit 120)) 407 | (recover) 408 | (read-once))} 409 | opts))) 410 | 411 | (defn partition-majority-test 412 | "Cuts the network into randomly majority groups." 413 | [opts] 414 | (create-test "partition-majority" 415 | (merge 416 | {:nemesis (nemesis/partition-majorities-ring) 417 | :client (SingleKeyClient. "a" nil) 418 | :checker (checker/compose 419 | {:perf (checker/perf) 420 | :linear (checker/linearizable) 421 | :timeline (timeline/html)}) 422 | :generator (gen/phases 423 | (->> gen/cas 424 | (gen/stagger 1/10) 425 | (gen/delay 1/10) 426 | (gen/nemesis 427 | (gen/seq 428 | (cycle [(gen/sleep 10) 429 | {:type :info :f :start} 430 | (gen/sleep 10) 431 | {:type :info :f :stop}]))) 432 | (gen/time-limit 120)) 433 | (recover) 434 | (read-once))} 435 | opts))) 436 | 437 | (defn configuration-test 438 | "remove and add a random node." 439 | [opts] 440 | (create-test "configuration" 441 | (merge {:nemesis configuration-nemesis 442 | :client (SingleKeyClient. "a" nil) 443 | :checker (checker/compose 444 | {:perf (checker/perf) 445 | :linear (checker/linearizable) 446 | :timeline (timeline/html)}) 447 | :generator (gen/phases 448 | (->> gen/cas 449 | (gen/stagger 1/10) 450 | (gen/delay 1/10) 451 | (gen/nemesis 452 | (gen/seq 453 | (cycle [(gen/sleep 10) 454 | {:type :info :f :start} 455 | (gen/sleep 10) 456 | {:type :info :f :stop}]))) 457 | (gen/time-limit 120)) 458 | (recover) 459 | (read-once))} 460 | opts))) 461 | 462 | 463 | (defn- parse-long [s] 464 | (Long/parseLong s)) 465 | 466 | (defn- parse-boolean [s] 467 | (Boolean/parseBoolean s)) 468 | 469 | (def cli-opts 470 | "Additional command line options." 471 | [["-s" "--slots SLOTS" "Number of atomic server ranges." 472 | :default 1 473 | :parse-fn parse-long 474 | :validate [pos? "Must be a positive number"]] 475 | ["-q" "--quorum BOOL" "Whether to read from quorum." 476 | :default false 477 | :parse-fn parse-boolean 478 | :validate [boolean? "Must be a boolean value."]] 479 | ["-r" "--rate HZ" "Approximate number of requests per second, per thread." 480 | :default 10 481 | :parse-fn read-string 482 | :validate [#(and (number? %) (pos? %)) "Must be a positive number"]] 483 | [nil "--ops-per-key NUM" "Maximum number of operations on any given key." 484 | :default 100 485 | :parse-fn parse-long 486 | :validate [pos? "Must be a positive integer."]]]) 487 | 488 | (def fn-opts 489 | [[nil "--testfn TEST" "Test function name."]]) 490 | 491 | (defn -main 492 | "Handles command line arguments. Can either run a test, or a web server for 493 | browsing results." 494 | [& args] 495 | (ns jepsen.atomic) 496 | (let [opts (parse-opts args (concat fn-opts cli-opts) :no-defaults true) 497 | test-fn (if-let [tfs (->> opts :options :testfn)] 498 | (->> tfs symbol (resolve)) 499 | partition-test)] 500 | (when (->> opts :options :quorum) 501 | (info "Use read from quorum for test.") 502 | (reset! read-from-quorum? true)) 503 | (info "Begin to test" test-fn) 504 | (cli/run! (merge (cli/single-test-cmd {:test-fn test-fn 505 | :opt-spec (conj cli-opts 506 | [nil "--testfn TEST" "Test function name." 507 | :default ""] 508 | )}) 509 | (cli/serve-cmd)) 510 | args))) 511 | --------------------------------------------------------------------------------