├── .gitignore ├── .mailmap ├── .travis.yml ├── .travis └── build-packages ├── CONTRIBUTING.md ├── LICENSE-GNU_AGPLv3.txt ├── README.md ├── main ├── .docker │ ├── run-postgres.sh │ ├── run-replication-postgres.sh │ ├── setup-postgres.sh │ ├── setup-replication.sh │ ├── torodb-postgres.yml │ └── torodb-replication-postgres.yml ├── pom.xml └── src │ ├── main │ ├── assembly │ │ └── assembly.xml │ ├── docker │ │ └── assembly.xml │ ├── java │ │ └── com │ │ │ └── torodb │ │ │ └── standalone │ │ │ ├── CliConfig.java │ │ │ ├── CliConfigUtils.java │ │ │ ├── Main.java │ │ │ └── config │ │ │ ├── jackson │ │ │ ├── BackendDeserializer.java │ │ │ └── BackendSerializer.java │ │ │ └── model │ │ │ ├── Config.java │ │ │ ├── backend │ │ │ ├── Backend.java │ │ │ ├── derby │ │ │ │ └── Derby.java │ │ │ └── postgres │ │ │ │ └── Postgres.java │ │ │ └── protocol │ │ │ ├── Protocol.java │ │ │ └── mongo │ │ │ ├── Mongo.java │ │ │ ├── Replication.java │ │ │ └── ShardReplication.java │ ├── profiles │ │ ├── dev │ │ │ └── log4j2.xml │ │ └── prod │ │ │ └── log4j2.xml │ └── resources │ │ ├── CliMessages.properties │ │ ├── ConfigMessages.properties │ │ ├── ValidationMessages.properties │ │ └── application.conf │ └── test │ ├── java │ └── com │ │ └── torodb │ │ └── standalone │ │ └── config │ │ ├── ByteArrayConsole.java │ │ └── ConfigTest.java │ └── resources │ ├── test-parse-with-empty-yaml.yml │ ├── test-parse-with-wrong-yaml.yml │ ├── test-parse-with-xml.xml │ ├── test-parse-with-yaml-using-derby.yml │ ├── test-parse-with-yaml-using-double-backend.yml │ ├── test-parse-with-yaml-using-empty-protocol.yml │ ├── test-parse-with-yaml-using-password.yml │ └── test-parse-with-yaml.yml ├── pom.xml ├── reporting └── pom.xml └── service ├── .docker ├── run-postgres.sh ├── run-replication-postgres.sh ├── setup-postgres.sh ├── setup-replication.sh ├── torodb-postgres.yml └── torodb-replication-postgres.yml ├── pom.xml └── src ├── main └── java │ └── com │ └── torodb │ └── standalone │ ├── ServerConfig.java │ └── ServerService.java └── test ├── java └── com │ └── torodb │ └── standalone │ ├── ServerServiceIT.java │ ├── ServerServiceTest.java │ └── utils │ ├── ClientSupplier.java │ ├── ClientSupplierExtension.java │ ├── DefaultClientSupplier.java │ ├── RequireClientSupplier.java │ └── ServerTestInstance.java └── resources └── log4j2.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | dependency-reduced-pom.xml 8 | buildNumber.properties 9 | .mvn/timing.properties 10 | **/.idea/ 11 | *.iml 12 | **/nbproject/** 13 | **/nbactions.xml 14 | **/nb-configuration.xml 15 | /bin/ 16 | .project 17 | .classpath 18 | .settings/ 19 | .checkstyle 20 | hs_err*.log 21 | /documentation/static 22 | /documentation/site 23 | .DS_Store 24 | .factorypath -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Álvaro Hernández Tortosa 2 | Matteo Melli 3 | Matteo Melli 4 | Gonzalo Ortiz Jaureguizar 5 | Gonzalo Ortiz Jaureguizar 6 | Gonzalo Ortiz Jaureguizar 7 | Jerónimo López 8 | Jerónimo López 9 | Jerónimo López 10 | Yeray Darias 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: required 3 | dist: trusty 4 | jdk: oraclejdk8 5 | 6 | before_install: 7 | - wget https://archive.apache.org/dist/maven/maven-3/3.2.2/binaries/apache-maven-3.2.2-bin.tar.gz 8 | - tar xf apache-maven-3.2.2-bin.tar.gz 9 | - export M2_HOME=$PWD/apache-maven-3.2.2 10 | - export PATH=$M2_HOME/bin:$PATH 11 | #Required to use Codacy 12 | - sudo apt-get install jq 13 | - wget -O ~/codacy-coverage-reporter-assembly-latest.jar $(curl https://api.github.com/repos/codacy/codacy-coverage-reporter/releases/latest | jq -r .assets[0].browser_download_url) 14 | 15 | addons: 16 | apt: 17 | packages: 18 | - oracle-java8-installer 19 | 20 | cache: 21 | directories: 22 | - $HOME/.m2/repository 23 | 24 | before_cache: 25 | - rm -f $HOME/.m2/repository/com/torodb 26 | 27 | before_script: 28 | - export GIT_BRANCH=$TRAVIS_BRANCH 29 | 30 | script: mvn -Psafer -Pintegration -B -e -T 1C -Dcheckstyle.consoleOutput=false --update-snapshots verify 31 | 32 | after_success: 33 | - | 34 | if [ "$TRAVIS_EVENT_TYPE" != cron ] && [ "$TRAVIS_REPO_SLUG" == torodb/testing-tools ] 35 | then 36 | # Upload reports to Codecov 37 | bash <(curl -s https://codecov.io/bash) || echo 'Codecov did not collect coverage reports'; 38 | # Upload reports to Codacy 39 | java -cp ~/codacy-coverage-reporter-assembly-latest.jar com.codacy.CodacyCoverageReporter -l Java -r reporting/target/site/jacoco-aggregate/jacoco.xml || echo 'Codacy report fail' 40 | else 41 | echo 'Skipping a metrics reports because this branch is not permitted' 42 | fi -------------------------------------------------------------------------------- /.travis/build-packages: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e +x +v +o history 4 | 5 | function finish { 6 | rm -f ~/.aws/config 7 | 8 | if [ -f ~/.m2/settings.xml ] 9 | then 10 | rm ~/.m2/settings.xml 11 | fi 12 | if [ -f ~/.m2/settings.xml.bak ] 13 | then 14 | mv ~/.m2/settings.xml.bak ~/.m2/settings.xml 15 | fi 16 | 17 | if [ -f ~/.ssh/id_rsa ] 18 | then 19 | rm -f ~/.ssh/id_rsa 20 | fi 21 | if [ -f ~/.ssh/id_rsa.bak ] 22 | then 23 | mv ~/.ssh/id_rsa.bak ~/.ssh/id_rsa 24 | fi 25 | if [ -f ~/.ssh/id_rsa.pub ] 26 | then 27 | rm -f ~/.ssh/id_rsa.pub 28 | fi 29 | if [ -f ~/.ssh/id_rsa.pub.bak ] 30 | then 31 | mv ~/.ssh/id_rsa.pub.bak ~/.ssh/id_rsa.pub 32 | fi 33 | 34 | if [ -f ~/.ssh/sign ] 35 | then 36 | rm -f ~/.ssh/sign 37 | fi 38 | if [ -f ~/.ssh/sign.bak ] 39 | then 40 | mv ~/.ssh/sign.bak ~/.ssh/sign 41 | fi 42 | if [ -f ~/.ssh/sign.pub ] 43 | then 44 | rm -f ~/.ssh/sign.pub 45 | fi 46 | if [ -f ~/.ssh/sign.pub.bak ] 47 | then 48 | mv ~/.ssh/sign.pub.bak ~/.ssh/sign.pub 49 | fi 50 | 51 | gpg --delete-secret-key --batch --yes "$launchpad_sign_public_key_fingerprint" || true 52 | gpg --delete-key --batch --yes "$launchpad_sign_public_key_fingerprint" || true 53 | 54 | rm -f ~/.config/copr 55 | } 56 | 57 | trap finish SIGINT SIGTERM EXIT 58 | 59 | 60 | echo "Building binary package" 61 | 62 | mkdir -p ~/.aws 63 | echo " 64 | [default] 65 | aws_access_key_id=$aws_access_key_id 66 | aws_secret_access_key=$aws_secret_access_key 67 | region=eu-west-1 68 | output=json 69 | " > ~/.aws/config 70 | 71 | set -x 72 | mvn package -f stampede/main/pom.xml -P assembler -Ds3.push=true -DskipTests 73 | set +x 74 | 75 | 76 | echo "Building docker package" 77 | 78 | mkdir -p ~/.m2 79 | if [ -f ~/.m2/settings.xml ] 80 | then 81 | mv ~/.m2/settings.xml ~/.m2/settings.xml.bak 82 | fi 83 | echo " 84 | 85 | 86 | 87 | docker.io 88 | $docker_username 89 | $docker_password 90 | 91 | 92 | 93 | " > ~/.m2/settings.xml 94 | 95 | set -x 96 | mvn package -f stampede/main/pom.xml -P docker -Ddocker.skip.push=false -DskipTests 97 | set +x 98 | 99 | 100 | echo "Building deb package" 101 | 102 | if [ -f ~/.ssh/id_rsa ] 103 | then 104 | mv ~/.ssh/id_rsa ~/.ssh/id_rsa.bak 105 | fi 106 | if [ -f ~/.ssh/id_rsa.pub ] 107 | then 108 | mv ~/.ssh/id_rsa.pub ~/.ssh/id_rsa.pub.bak 109 | fi 110 | 111 | echo "$launchpad_private_key" > ~/.ssh/id_rsa 112 | echo "$launchpad_public_key" > ~/.ssh/id_rsa.pub 113 | chmod 600 ~/.ssh/id_rsa 114 | chmod 644 ~/.ssh/id_rsa.pub 115 | 116 | echo "$launchpad_sign_private_key" > ~/.ssh/sign 117 | echo "$launchpad_sign_public_key" > ~/.ssh/sign.pub 118 | chmod 600 ~/.ssh/sign 119 | chmod 644 ~/.ssh/sign.pub 120 | 121 | gpg --import ~/.ssh/sign.pub 122 | gpg --import ~/.ssh/sign 123 | echo "$(echo "$launchpad_sign_public_key_fingerprint"|tr -d '[:space:]'):6:"|gpg --import-ownertrust 124 | 125 | echo " 126 | [8kdata-release] 127 | fqdn = ppa.launchpad.net 128 | method = ftp 129 | incoming = ~8kdata/ubuntu/ppa/ 130 | login = anonymous 131 | allow_unsigned_uploads = 0 132 | 133 | [8kdata-devel] 134 | fqdn = ppa.launchpad.net 135 | method = ftp 136 | incoming = ~8kdata/ubuntu/ppa-dev/ 137 | login = anonymous 138 | allow_unsigned_uploads = 0 139 | " > ~/.dput.cf 140 | 141 | set -x 142 | mvn package -f stampede/main/pom.xml -P deb -Dlaunchpad.push=true -DskipTests -Dpackage.name=torodb-stampede 143 | mvn package -f stampede/main/pom.xml -P deb -Dlaunchpad.push=true -DskipTests -Dpackage.name=torodb-stampede-postgres 144 | set +x 145 | 146 | 147 | echo "Building snap package" 148 | 149 | set -x 150 | mvn package -f stampede/main/pom.xml -P snap -Dlaunchpad.push=true -DskipTests -Dpackage.name=torodb-stampede 151 | mvn package -f stampede/main/pom.xml -P snap -Dlaunchpad.push=true -DskipTests -Dpackage.name=torodb-stampede-postgres 152 | set +x 153 | 154 | 155 | echo "Building rpm package" 156 | 157 | mkdir -p ~/.config 158 | echo " 159 | [copr-cli] 160 | login = $copr_login 161 | username = $copr_user 162 | token = $copr_token 163 | copr_url = https://copr.fedorainfracloud.org 164 | " > ~/.config/copr 165 | 166 | set -x 167 | mvn package -f stampede/main/pom.xml -P rpm -Dcopr.push=true -DskipTests -Dpackage.name=torodb-stampede 168 | mvn package -f stampede/main/pom.xml -P rpm -Dcopr.push=true -DskipTests -Dpackage.name=torodb-stampede-postgres 169 | set +x 170 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to ToroDB 2 | ======================= 3 | 4 | ToroDB is open source, and as such we welcome any external contribution, in 5 | the form of feedback, testing, resources, documentation and, of course, code. 6 | Pull requests are always welcome. 7 | 8 | Please observe the following rules when contributing to ToroDB: 9 | 10 | * Post to [ToroDB's developer mailing list][1] with any question or 11 | improvements about the source code, to keep the discussion organized within 12 | the mailing list. 13 | 14 | * Contact us at toro at ToroDB dot com before sending a pull request, to have 15 | a contributor agreement signed with us. This is a requirement for your pull 16 | request to be merged upstream. 17 | 18 | * Changes and pull requests should be performed from the ``devel`` branch, 19 | instead of ``master``. Please adhere as much as possible to the apparent 20 | style of the code you are editing. 21 | 22 | 23 | [1]: https://groups.google.com/forum/#!forum/torodb-dev 24 | -------------------------------------------------------------------------------- /LICENSE-GNU_AGPLv3.txt: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ToroDB 2 | ====== 3 | 4 | ToroDB is an open source project that turns your RDBMS into a 5 | MongoDB-compatible server, supporting the MongoDB query API and 6 | MongoDB's replication, but storing your data into a reliable and trusted 7 | ACID database. ToroDB currently supports PostgreSQL as a backend, but 8 | others will be added in the future. 9 | 10 | ToroDB natively implements the MongoDB protocol, so you can use it with 11 | MongoDB tools and drivers, and features a document-to-relational mapping 12 | algorithm that transforms the JSON documents into relational tables. 13 | ToroDB also offers a native SQL layer and automatic data normalization 14 | and partitioning based on JSON documents' implicit schema. 15 | 16 | ToroDB follows a RERO (Release Early, Release Often) policy. Current version is 17 | considered a "developer preview" and hence is not suitable for 18 | production use. Use at your own risk. However, any feedback, 19 | contributions, help and/or patches are very welcome. Please join the 20 | [torodb-dev][8] mailing list for further discussion. 21 | 22 | For more information, please see [ToroDB's website][1], this 23 | [latest presentation][7] or this [video recording of a presentation][11] about 24 | ToroDB. 25 | 26 | ## Requisites 27 | 28 | ToroDB is written in Java and requires: 29 | 30 | * A suitable JRE, version 7 or higher. It has been mainly tested with Oracle JRE 8. 31 | * A [PostgreSQL][2] database, version 9.4 or higher. [Download][9]. 32 | 33 | 34 | ## Download/Installation 35 | 36 | ### Download the compiled file 37 | 38 | You may download the latest version (v. 0.40-alpha2) of ToroDB from 39 | [the release page](https://github.com/torodb/torodb/releases/latest) on the 40 | following packaging formats: 41 | * [tar.bz2](https://github.com/torodb/torodb/releases/download/v0.40-alpha2/torodb.tar.bz2) 42 | * [zip](https://github.com/torodb/torodb/releases/download/v0.40-alpha2/torodb.zip) 43 | 44 | See below for instructions on how to run it. 45 | 46 | You can also find binary files on [ToroDB's maven repository][3]. 47 | 48 | 49 | ### Compile and install from sources 50 | 51 | To get the latest version, you may compile ToroDB yourself. All the project is written in Java and managed with Maven, so you need a javac and maven. 52 | 53 | ToroDB is based on the [Mongo Wire Protocol library][5] (mongowp), which is another library built by [8Kdata][6] to help construct programs that speak the MongoDB protocol. You may also compile this library yourself, or let maven download it from the repository automatically. 54 | 55 | Just run `mvn package -P assembler` on the root directory and execute it from 56 | `torodb/target/appassembler/bin` or choose your prefered packaging format from 57 | `torodb/target/dist/`. 58 | 59 | ### Compile and create docker image 60 | 61 | To build the docker image the first time run `mvn package -P docker,assembler -Ddocker.skipbase=false` on the root directory. 62 | 63 | Next time you will be able to build the torodb docker image running `mvn package -P docker,assembler`. 64 | 65 | To run docker containers of ToroDB with PostgreSQL backend just run `mvn docker:run -P docker,assembler -pl :standalone`. You will have now ToroDB running on port 27018 and will be able to watch created table connection to PostgreSQL on port 15432 (user: postgres, password: postgres, database: torod). 66 | 67 | ## Running ToroDB 68 | 69 | ToroDB needs either a configuration file or some command-line parameters 70 | to run. But it can also run without any of them if you follow some 71 | conventions. 72 | 73 | Before running ToroDB it is necessary to configure the RDBMS with the 74 | ToroDB user that will be responsible to create namespaces, required data 75 | types, tables and indexes. 76 | 77 | Create user torodb (this is default user name, see ToroDB configuration 78 | to use a different name): 79 | 80 | =# CREATE USER torodb WITH SUPERUSER PASSWORD ''; 81 | 82 | Create the database torod (this is default database name, see ToroDB 83 | configuration to use a different name): 84 | 85 | =# CREATE DATABASE torod OWNER torodb; 86 | 87 | The script $TOROHOME/bin/torodb (or torodb.bat) will run ToroDB. ToroDB can be 88 | configured by a configuration file written in YAML or XML formats by 89 | passing arguments -c or -x, respectively, to the script 90 | $TOROHOME/bin/torodb. For example, to run ToroDB with configuration file 91 | torodb.yml, run: 92 | 93 | $ $TOROHOME/bin/torodb -c torodb.yml 94 | 95 | To print default configuration script in YAML or XML format use the 96 | arguments -l an -lx respectively. For example to generate default YAML 97 | configuration file: 98 | 99 | $ $TOROHOME/bin/torodb -l > torodb.yml 100 | 101 | ToroDB connects to the backend database using user torodb (that has been 102 | created in previous step). By default ToroDB reads the file 103 | $HOME/.toropass (file path can be configured in the configuration), if 104 | it exists, that stores the password in PostgreSQL's [.pgpass][4] syntax. The 105 | password can also be specified in clear text in the configuration file or 106 | will be asked at the prompt if the argument -W is issued. 107 | 108 | To get general help, pass --help argument: 109 | 110 | $ $TOROHOME/bin/torodb --help 111 | 112 | Use --help-param to get help on all available parameters of the 113 | configuration file: 114 | 115 | $ $TOROHOME/bin/torodb --help-param 116 | 117 | If you setup a .toropass, use torodb as the user and torod as the 118 | database, ToroDB will run without a configuration file (with the rest of 119 | the configuration values with their respective defaults). 120 | 121 | Once ToroDB is running, connect to it with a normal MongoDB client, 122 | like: 123 | 124 | $ mongo localhost:27018/torod 125 | 126 | 127 | ## Are you a developer? Want to contribute? Questions about the source code? 128 | 129 | Please see [CONTRIBUTING][10]. 130 | 131 | ## Code QA 132 | * Master branch: 133 | [![Build Status](https://travis-ci.org/torodb/server.svg?branch=master)](https://travis-ci.org/torodb/server) 134 | [![Codacy Badge](https://api.codacy.com/project/badge/grade/ba76a3307733492c97c0dfc13beae2c0?branch=master)](https://www.codacy.com/app/torodb/server?utm_source=github.com&utm_medium=referral&utm_content=torodb/server&utm_campaign=Badge_Grade) 135 | [![Codacy Coverage](https://api.codacy.com/project/badge/coverage/ba76a3307733492c97c0dfc13beae2c0?branch=master)](https://www.codacy.com/app/torodb/server?utm_source=github.com&utm_medium=referral&utm_content=torodb/server&utm_campaign=Badge_Grade) 136 | * Devel branch: 137 | [![Build Status](https://travis-ci.org/torodb/server.svg?branch=devel)](https://travis-ci.org/torodb/server) 138 | [![Codacy Badge](https://api.codacy.com/project/badge/grade/ba76a3307733492c97c0dfc13beae2c0?branch=devel)](https://www.codacy.com/app/torodb/server?utm_source=github.com&utm_medium=referral&utm_content=torodb/server&utm_campaign=Badge_Grade) 139 | [![Codacy Coverage](https://api.codacy.com/project/badge/coverage/ba76a3307733492c97c0dfc13beae2c0?branch=devel)](https://www.codacy.com/app/torodb/server?utm_source=github.com&utm_medium=referral&utm_content=torodb/server&utm_campaign=Badge_Grade) 140 | 141 | [1]: http://www.torodb.com 142 | [2]: http://www.postgresql.org 143 | [3]: https://oss.sonatype.org/content/groups/public/com/torodb/torodb/ 144 | [4]: http://www.postgresql.org/docs/9.4/static/libpq-pgpass.html 145 | [5]: https://github.com/8kdata/mongowp 146 | [6]: http://www.8kdata.com 147 | [7]: http://www.slideshare.net/8kdata/torodb-internals-how-to-create-a-nosql-database-on-top-of-sql-55275036 148 | [8]: https://groups.google.com/forum/#!forum/torodb-dev 149 | [9]: http://www.postgresql.org/download/ 150 | [10]: https://github.com/torodb/torodb/blob/master/CONTRIBUTING.md 151 | [11]: https://www.youtube.com/watch?v=C2XuOhLrblo 152 | -------------------------------------------------------------------------------- /main/.docker/run-postgres.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./setup-postgres.sh 4 | 5 | ./toro_dist/bin/torodb -c ./torodb-postgres.yml -l 6 | ./toro_dist/bin/torodb -c ./torodb-postgres.yml 7 | -------------------------------------------------------------------------------- /main/.docker/run-replication-postgres.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./setup-postgres.sh 4 | ./setup-replication.sh 5 | 6 | ./toro_dist/bin/torodb -c ./torodb-replication-postgres.yml -l 7 | ./toro_dist/bin/torodb -c ./torodb-replication-postgres.yml 8 | -------------------------------------------------------------------------------- /main/.docker/setup-postgres.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo -n "Waiting PostgreSQL..." 6 | POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-}" 7 | echo "postgres:5432:*:postgres:$POSTGRES_PASSWORD" > ~/.pgpass 8 | chmod 400 ~/.pgpass 9 | max_seconds=15 10 | while ! /usr/bin/psql -h postgres -U postgres -c "SELECT 1" > /dev/null 2>&1 11 | do 12 | sleep 1 13 | echo -n . 14 | max_seconds=$((max_seconds-1)) 15 | if [ "$max_seconds" -le 0 ] 16 | then 17 | echo timeout 18 | exit 1 19 | fi 20 | done 21 | echo ok 22 | 23 | echo -n "Setting up PostgreSQL..." 24 | TORODB_PASSWORD="${TORODB_PASSWORD:-trustme}" 25 | echo "postgres:5432:torod:torodb:$TORODB_PASSWORD" > ~/.toropass 26 | chown 400 ~/.toropass 27 | /usr/bin/psql -h postgres -U postgres -c "CREATE USER torodb PASSWORD '$TORODB_PASSWORD'" 28 | /usr/bin/psql -h postgres -U postgres -c "CREATE DATABASE torod OWNER torodb" 29 | echo ok 30 | 31 | rm ~/.pgpass 32 | POSTGRES_PASSWORD= 33 | TORODB_PASSWORD= 34 | -------------------------------------------------------------------------------- /main/.docker/setup-replication.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo -n "Waiting MongoDB..." 6 | max_seconds=15 7 | while ! /opt/mongodb/bin/mongo mongo:27017/local --eval true > /dev/null 2>&1 8 | do 9 | sleep 1 10 | echo -n . 11 | max_seconds=$((max_seconds-1)) 12 | if [ "$max_seconds" -le 0 ] 13 | then 14 | echo timeout 15 | exit 1 16 | fi 17 | done 18 | echo ok 19 | 20 | echo -n "Setting up MongoDB..." 21 | /opt/mongodb/bin/mongo mongo:27017/local --eval 'rs.initiate({_id:"rs1",members:[{_id:0,host:"localhost:27017"}]})' > /dev/null 2>&1 22 | max_seconds=15 23 | while ! /opt/mongodb/bin/mongo mongo:27017/local --eval 'assert(db.isMaster().ismaster)' > /dev/null 2>&1 24 | do 25 | sleep 1 26 | echo -n . 27 | max_seconds=$((max_seconds-1)) 28 | if [ "$max_seconds" -le 0 ] 29 | then 30 | echo timeout 31 | exit 1 32 | fi 33 | done 34 | echo ok 35 | -------------------------------------------------------------------------------- /main/.docker/torodb-postgres.yml: -------------------------------------------------------------------------------- 1 | --- 2 | generic: 3 | logLevel: INFO 4 | connectionPoolSize: 30 5 | reservedReadPoolSize: 10 6 | connectionPoolTimeout: 10000 7 | protocol: 8 | mongo: 9 | net: 10 | bindIp: localhost 11 | port: 27018 12 | cursorTimeout: 600000 13 | backend: 14 | postgres: 15 | host: postgres 16 | port: 5432 17 | database: torod 18 | user: torodb 19 | toropassFile: /root/.toropass 20 | applicationName: toro 21 | -------------------------------------------------------------------------------- /main/.docker/torodb-replication-postgres.yml: -------------------------------------------------------------------------------- 1 | --- 2 | generic: 3 | logLevel: INFO 4 | connectionPoolSize: 30 5 | reservedReadPoolSize: 10 6 | connectionPoolTimeout: 10000 7 | protocol: 8 | mongo: 9 | net: 10 | bindIp: localhost 11 | port: 27018 12 | cursorTimeout: 600000 13 | replication: 14 | - replSetName: rs1 15 | syncSource: mongo:27017 16 | backend: 17 | postgres: 18 | host: postgres 19 | port: 5432 20 | database: torod 21 | user: torodb 22 | toropassFile: /root/.toropass 23 | applicationName: toro 24 | -------------------------------------------------------------------------------- /main/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.torodb.server 6 | server-pom 7 | 0.50.2-SNAPSHOT 8 | 9 | 10 | server-main 11 | 12 | ToroDB: Server main 13 | ToroDB Server main project. Contains executable class and CLI parsing. 14 | 15 | 16 | src/main/profiles/dev 17 | 18 | 19 | 20 | 21 | com.torodb.engine 22 | packaging-utils 23 | 24 | 25 | com.torodb.engine.backend 26 | backend-postgresql 27 | 28 | 29 | com.torodb.engine.backend 30 | backend-derby 31 | 32 | 33 | ${project.groupId} 34 | server-service 35 | ${project.version} 36 | 37 | 38 | 39 | org.glassfish 40 | javax.json 41 | 42 | 43 | com.google.inject 44 | guice 45 | 46 | 47 | javax.validation 48 | validation-api 49 | 50 | 51 | org.hibernate 52 | hibernate-validator 53 | 54 | 55 | org.glassfish 56 | javax.el 57 | 58 | 59 | com.google.code.findbugs 60 | jsr305 61 | 62 | 63 | com.google.code.findbugs 64 | annotations 65 | 66 | 67 | commons-configuration 68 | commons-configuration 69 | 70 | 71 | commons-logging 72 | commons-logging 73 | 74 | 75 | 76 | 77 | javax.inject 78 | javax.inject 79 | 80 | 81 | org.apache.logging.log4j 82 | log4j-slf4j-impl 83 | 84 | 85 | org.apache.logging.log4j 86 | log4j-core 87 | 88 | 89 | com.typesafe.akka 90 | akka-slf4j_2.12 91 | 92 | 93 | 94 | junit 95 | junit 96 | test 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-surefire-plugin 107 | 108 | 109 | integration-tests 110 | integration-test 111 | 112 | 113 | ${torodbIntegrationConfigYml} 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | src/main/resources 125 | true 126 | 127 | 128 | ${profiles.resources} 129 | 130 | 131 | 132 | 133 | 134 | 135 | assembler 136 | 137 | true 138 | 139 | 140 | 141 | 142 | org.apache.maven.plugins 143 | maven-assembly-plugin 144 | 2.2-beta-5 145 | 146 | 147 | src/main/assembly/assembly.xml 148 | 149 | torodb-${project.version} 150 | ${project.build.directory}/dist 151 | 152 | 153 | 154 | package 155 | 156 | assembly 157 | 158 | 159 | 160 | 161 | 162 | org.codehaus.mojo 163 | appassembler-maven-plugin 164 | 1.10 165 | 166 | 167 | 168 | com.torodb.standalone.Main 169 | torodb 170 | 171 | 172 | 173 | 174 | 175 | assemble 176 | package 177 | 178 | assemble 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | docker 189 | 190 | java:8-jre 191 | postgres 192 | torodb 193 | 194 | 195 | 196 | 197 | org.codehaus.mojo 198 | appassembler-maven-plugin 199 | 1.10 200 | 201 | 202 | 203 | com.torodb.standalone.Main 204 | torodb 205 | 206 | 207 | 208 | 209 | 210 | assemble 211 | package 212 | 213 | assemble 214 | 215 | 216 | 217 | 218 | 219 | io.fabric8 220 | docker-maven-plugin 221 | true 222 | 223 | 224 | docker-base 225 | package 226 | 227 | build-nofork 228 | start 229 | 230 | 231 | 232 | 233 | torodb-base 234 | 235 | ${docker.javaimage} 236 | try 237 | true 238 | 239 | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv D68FA50FEA312927 240 | echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.2 multiverse" > /etc/apt/sources.list.d/mongodb-org-3.2.list 241 | apt-get update 242 | apt-get -y install netcat postgresql-client python-pip mongodb-org-shell mongodb-org-tools 243 | pip install awscli 244 | apt-get clean 245 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 246 | 247 | 248 | 249 | 250 | base image generated 251 | 252 | 253 | /bin/bash 254 | -c 255 | 256 | > generated; 257 | echo base image generated; 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | docker-build 267 | package 268 | 269 | build-nofork 270 | 271 | 272 | 273 | 274 | postgres 275 | postgres:9.5 276 | 277 | 278 | ${docker.postgres.password} 279 | 280 | 281 | 15432:5432 282 | 283 | 284 | postgres 285 | true 286 | blue 287 | 288 | 289 | 290 | 291 | torodb 292 | torodb/server 293 | 294 | torodb-base 295 | 296 | ${project.version} 297 | 298 | 299 | dir 300 | assembly.xml 301 | 302 | 303 | 304 | 305 | ${docker.postgres.password} 306 | ${docker.torodb.password} 307 | 308 | 309 | postgres:postgres 310 | 311 | 312 | 27018:27018 313 | 314 | 315 | torodb 316 | true 317 | white 318 | 319 | /maven 320 | ./run-postgres.sh 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | prod 333 | 334 | src/main/profiles/prod 335 | 336 | 337 | 338 | 339 | 340 | 341 | -------------------------------------------------------------------------------- /main/src/main/assembly/assembly.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | tar.bz2 7 | zip 8 | 9 | 10 | 11 | target/appassembler/bin 12 | bin 13 | 14 | *.bat 15 | 16 | 0755 17 | 0755 18 | 19 | 20 | target/appassembler/bin 21 | bin 22 | 23 | *.bat 24 | 25 | 0755 26 | 0644 27 | 28 | 29 | target/appassembler/repo 30 | repo 31 | 0755 32 | 0644 33 | 34 | 35 | -------------------------------------------------------------------------------- /main/src/main/docker/assembly.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | tar 7 | 8 | 9 | 10 | target/appassembler/bin 11 | toro_dist/bin 12 | 13 | *.bat 14 | 15 | 0755 16 | 0755 17 | 18 | 19 | target/appassembler/repo 20 | toro_dist/repo 21 | 0755 22 | 0644 23 | 24 | 25 | .docker/ 26 | 27 | *.sh 28 | 29 | . 30 | 0755 31 | 0755 32 | 33 | 34 | .docker/ 35 | . 36 | 37 | *.sh 38 | 39 | 0755 40 | 0644 41 | 42 | 43 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/CliConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone; 19 | 20 | import com.beust.jcommander.IValueValidator; 21 | import com.beust.jcommander.Parameter; 22 | import com.beust.jcommander.ParameterException; 23 | import com.beust.jcommander.converters.IParameterSplitter; 24 | import com.torodb.packaging.config.model.backend.BackendImplementation; 25 | import com.torodb.standalone.config.model.backend.Backend; 26 | 27 | import java.io.FileInputStream; 28 | import java.io.InputStream; 29 | import java.util.ArrayList; 30 | import java.util.Arrays; 31 | import java.util.List; 32 | import java.util.Locale; 33 | 34 | public class CliConfig { 35 | 36 | @Parameter(names = {"-h", "--help"}, descriptionKey = "help") 37 | private boolean help = false; 38 | @Parameter(names = {"-l", "--print-config"}, descriptionKey = "print-config") 39 | private boolean printConfig = false; 40 | @Parameter(names = {"-lx", "--print-xml-config"}, descriptionKey = "print-xml-config") 41 | private boolean printXmlConfig = false; 42 | @Parameter(names = {"-hp", "--help-param"}, descriptionKey = "help-param") 43 | private boolean helpParam = false; 44 | @Parameter(names = {"-c", "--conf"}, descriptionKey = "conf") 45 | private String confFile; 46 | @Parameter(names = {"-x", "--xml-conf"}, descriptionKey = "xml-conf") 47 | private String xmlConfFile; 48 | @Parameter(names = {"-W", "--ask-for-password"}, descriptionKey = "ask-for-password") 49 | private boolean askForPassword = false; 50 | @Parameter(names = {"-b", "--backend"}, descriptionKey = "backend", validateValueWith = 51 | BackendValueValidator.class) 52 | private String backend; 53 | @Parameter(names = {"-p", "--param"}, descriptionKey = "param", validateValueWith = 54 | ParamValueValidator.class, 55 | splitter = NoParameterSplitter.class) 56 | private List params; 57 | 58 | public boolean isHelp() { 59 | return help; 60 | } 61 | 62 | public boolean isPrintConfig() { 63 | return printConfig; 64 | } 65 | 66 | public boolean isPrintXmlConfig() { 67 | return printXmlConfig; 68 | } 69 | 70 | public String getConfFile() { 71 | return confFile; 72 | } 73 | 74 | public boolean hasConfFile() { 75 | return confFile != null; 76 | } 77 | 78 | public InputStream getConfInputStream() throws Exception { 79 | return new FileInputStream(confFile); 80 | } 81 | 82 | public String getXmlConfFile() { 83 | return xmlConfFile; 84 | } 85 | 86 | public boolean hasXmlConfFile() { 87 | return xmlConfFile != null; 88 | } 89 | 90 | public InputStream getXmlConfInputStream() throws Exception { 91 | return new FileInputStream(xmlConfFile); 92 | } 93 | 94 | public boolean isHelpParam() { 95 | return helpParam; 96 | } 97 | 98 | public boolean isAskForPassword() { 99 | return askForPassword; 100 | } 101 | 102 | public List getParams() { 103 | return params; 104 | } 105 | 106 | public String getBackend() { 107 | return backend; 108 | } 109 | 110 | public static class ParamValueValidator implements IValueValidator> { 111 | 112 | @Override 113 | public void validate(String name, List value) throws ParameterException { 114 | for (String param : value) { 115 | if (param.indexOf('=') == -1) { 116 | throw new ParameterException("Wrong parameter format: " + param); 117 | } 118 | } 119 | } 120 | } 121 | 122 | public static Class getBackendClass(String backend) { 123 | backend = backend.toLowerCase(Locale.US); 124 | 125 | for (Class backendClass : Backend.BACKEND_CLASSES.values()) { 126 | String backendClassLabel = backendClass.getSimpleName().toLowerCase(Locale.US); 127 | if (backend.equals(backendClassLabel)) { 128 | return backendClass; 129 | } 130 | } 131 | 132 | return null; 133 | } 134 | 135 | public static class BackendValueValidator implements IValueValidator { 136 | 137 | @Override 138 | public void validate(String name, String value) throws ParameterException { 139 | if (value != null && getBackendClass(value) == null) { 140 | List possibleValues = new ArrayList<>(); 141 | Iterable> backendClasses = Backend.BACKEND_CLASSES 142 | .values(); 143 | for (Class backendClass : backendClasses) { 144 | possibleValues.add(backendClass.getSimpleName().toLowerCase(Locale.US)); 145 | } 146 | throw new ParameterException("Unknown backend: " + value + " (possible values are: " 147 | + possibleValues + ")"); 148 | } 149 | } 150 | } 151 | 152 | public static class NoParameterSplitter implements IParameterSplitter { 153 | 154 | @Override 155 | public List split(String value) { 156 | return Arrays.asList(new String[]{value}); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/CliConfigUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone; 19 | 20 | import static com.torodb.packaging.config.util.ConfigUtils.validateBean; 21 | 22 | import com.fasterxml.jackson.core.JsonParseException; 23 | import com.fasterxml.jackson.core.JsonProcessingException; 24 | import com.fasterxml.jackson.databind.JsonMappingException; 25 | import com.fasterxml.jackson.databind.ObjectMapper; 26 | import com.fasterxml.jackson.databind.node.ObjectNode; 27 | import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; 28 | import com.torodb.packaging.config.util.ConfigUtils; 29 | import com.torodb.standalone.config.model.Config; 30 | 31 | import java.io.FileNotFoundException; 32 | import java.io.IOException; 33 | import java.io.InputStream; 34 | 35 | /** 36 | * 37 | */ 38 | public class CliConfigUtils { 39 | 40 | private CliConfigUtils() { 41 | } 42 | 43 | public static Config readConfig(CliConfig cliConfig) throws FileNotFoundException, 44 | JsonProcessingException, 45 | IOException, JsonParseException, IllegalArgumentException, Exception { 46 | try { 47 | return uncatchedReadConfig(cliConfig); 48 | } catch (JsonMappingException jsonMappingException) { 49 | throw ConfigUtils.transformJsonMappingException(jsonMappingException); 50 | } 51 | } 52 | 53 | private static Config uncatchedReadConfig(final CliConfig cliConfig) throws Exception { 54 | ObjectMapper objectMapper = ConfigUtils.mapper(true); 55 | 56 | Config defaultConfig = new Config(); 57 | if (cliConfig.getBackend() != null) { 58 | defaultConfig.getBackend().setBackendImplementation( 59 | CliConfig.getBackendClass(cliConfig.getBackend()).newInstance()); 60 | } 61 | ObjectNode configNode = (ObjectNode) objectMapper.valueToTree(defaultConfig); 62 | 63 | if (cliConfig.hasConfFile() || cliConfig.hasXmlConfFile()) { 64 | ObjectMapper mapper = null; 65 | InputStream inputStream = null; 66 | if (cliConfig.hasConfFile()) { 67 | mapper = ConfigUtils.yamlMapper(true); 68 | inputStream = cliConfig.getConfInputStream(); 69 | } else if (cliConfig.hasXmlConfFile()) { 70 | mapper = ConfigUtils.xmlMapper(true); 71 | inputStream = cliConfig.getXmlConfInputStream(); 72 | } 73 | 74 | if (inputStream != null) { 75 | Config config = mapper.readValue(inputStream, Config.class); 76 | configNode = mapper.valueToTree(config); 77 | } 78 | } 79 | 80 | if (cliConfig.getParams() != null) { 81 | YAMLMapper yamlMapper = ConfigUtils.yamlMapper(true); 82 | for (String paramPathValue : cliConfig.getParams()) { 83 | int paramPathValueSeparatorIndex = paramPathValue.indexOf('='); 84 | String pathAndProp = paramPathValue.substring(0, paramPathValueSeparatorIndex); 85 | 86 | if (pathAndProp.startsWith("/")) { 87 | pathAndProp = pathAndProp.substring(1); 88 | } 89 | 90 | pathAndProp = "/" + pathAndProp; 91 | 92 | String value = paramPathValue.substring(paramPathValueSeparatorIndex + 1); 93 | 94 | configNode = ConfigUtils.mergeParam(yamlMapper, configNode, pathAndProp, value); 95 | } 96 | } 97 | 98 | Config config = objectMapper.treeToValue(configNode, Config.class); 99 | 100 | validateBean(config); 101 | 102 | return config; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone; 19 | 20 | import com.beust.jcommander.JCommander; 21 | import com.beust.jcommander.internal.Console; 22 | import com.beust.jcommander.internal.Lists; 23 | import com.google.common.base.Charsets; 24 | import com.google.common.base.Throwables; 25 | import com.google.common.net.HostAndPort; 26 | import com.google.common.util.concurrent.Service; 27 | import com.google.inject.CreationException; 28 | import com.google.inject.Guice; 29 | import com.torodb.core.bundle.BundleConfig; 30 | import com.torodb.core.exceptions.SystemException; 31 | import com.torodb.core.guice.EssentialModule; 32 | import com.torodb.core.logging.ComponentLoggerFactory; 33 | import com.torodb.core.logging.LoggerFactory; 34 | import com.torodb.core.metrics.MetricsConfig; 35 | import com.torodb.mongodb.core.MongoDbCoreBundle; 36 | import com.torodb.mongodb.wp.MongoDbWpBundle; 37 | import com.torodb.mongodb.wp.MongoDbWpConfig; 38 | import com.torodb.packaging.config.model.backend.BackendImplementation; 39 | import com.torodb.packaging.config.model.backend.BackendPasswordConfig; 40 | import com.torodb.packaging.config.model.backend.derby.AbstractDerby; 41 | import com.torodb.packaging.config.model.backend.postgres.AbstractPostgres; 42 | import com.torodb.packaging.config.model.protocol.mongo.AbstractShardReplication; 43 | import com.torodb.packaging.config.model.protocol.mongo.MongoPasswordConfig; 44 | import com.torodb.packaging.config.model.protocol.mongo.Net; 45 | import com.torodb.packaging.config.util.BackendImplementationVisitor; 46 | import com.torodb.packaging.config.util.BackendImplementationVisitorWithDefault; 47 | import com.torodb.packaging.config.util.BundleFactory; 48 | import com.torodb.packaging.config.util.ConfigUtils; 49 | import com.torodb.packaging.util.Log4jUtils; 50 | import com.torodb.standalone.config.model.Config; 51 | import com.torodb.standalone.config.model.backend.Backend; 52 | import org.apache.logging.log4j.Logger; 53 | 54 | import java.io.IOException; 55 | import java.io.InputStream; 56 | import java.time.Clock; 57 | import java.util.List; 58 | import java.util.PropertyResourceBundle; 59 | import java.util.ResourceBundle; 60 | import java.util.stream.Collectors; 61 | 62 | /** 63 | * ToroDB Server entry point. 64 | */ 65 | public class Main { 66 | 67 | private static final LoggerFactory LOGGER_FACTORY = new ComponentLoggerFactory("SERVER"); 68 | private static final Logger LOGGER = LOGGER_FACTORY.apply(Main.class); 69 | 70 | /** 71 | * The main method that runs ToroDB Server. 72 | */ 73 | public static void main(String[] args) throws Exception { 74 | Console console = JCommander.getConsole(); 75 | 76 | ResourceBundle cliBundle = PropertyResourceBundle.getBundle("CliMessages"); 77 | final CliConfig cliConfig = new CliConfig(); 78 | @SuppressWarnings("checkstyle:LocalVariableName") 79 | JCommander jCommander = new JCommander(cliConfig, cliBundle, args); 80 | jCommander.setColumnSize(Integer.MAX_VALUE); 81 | 82 | if (cliConfig.isHelp()) { 83 | jCommander.usage(); 84 | System.exit(0); 85 | } 86 | 87 | if (cliConfig.isHelpParam()) { 88 | console.println(cliBundle.getString("help-param-header")); 89 | ResourceBundle configBundle = PropertyResourceBundle.getBundle("ConfigMessages"); 90 | ConfigUtils.printParamDescriptionFromConfigSchema(Config.class, configBundle, console, 0); 91 | System.exit(0); 92 | } 93 | 94 | final Config config = CliConfigUtils.readConfig(cliConfig); 95 | 96 | if (cliConfig.isPrintConfig()) { 97 | ConfigUtils.printYamlConfig(config, console); 98 | 99 | System.exit(0); 100 | } 101 | 102 | if (cliConfig.isPrintXmlConfig()) { 103 | ConfigUtils.printXmlConfig(config, console); 104 | 105 | System.exit(0); 106 | } 107 | 108 | configureLogger(cliConfig, config); 109 | 110 | parseToropassFile(config); 111 | 112 | if (config.getProtocol().getMongo().getReplication() != null) { 113 | List shards; 114 | if (config.getProtocol().getMongo().getReplication().getShards().isEmpty()) { 115 | shards = Lists.newArrayList(config.getProtocol().getMongo().getReplication()); 116 | } else { 117 | shards = config.getProtocol().getMongo().getReplication().getShards() 118 | .stream() 119 | .map(shard -> (AbstractShardReplication) 120 | config.getProtocol().getMongo().getReplication().mergeWith(shard)) 121 | .collect(Collectors.toList()); 122 | } 123 | for (AbstractShardReplication shard : shards) { 124 | if (shard.getAuth().getUser() != null) { 125 | HostAndPort syncSource = HostAndPort.fromString(shard.getSyncSource().value().get(0)) 126 | .withDefaultPort(27017); 127 | ConfigUtils.parseMongopassFile(new MongoPasswordConfig() { 128 | 129 | @Override 130 | public void setPassword(String password) { 131 | shard.getAuth().setPassword(password); 132 | } 133 | 134 | @Override 135 | public String getUser() { 136 | return shard.getAuth().getUser().value(); 137 | } 138 | 139 | @Override 140 | public Integer getPort() { 141 | return syncSource.getPort(); 142 | } 143 | 144 | @Override 145 | public String getPassword() { 146 | return shard.getAuth().getPassword(); 147 | } 148 | 149 | @Override 150 | public String getMongopassFile() { 151 | return config.getProtocol().getMongo().getMongopassFile(); 152 | } 153 | 154 | @Override 155 | public String getHost() { 156 | return syncSource.getHost(); 157 | } 158 | 159 | @Override 160 | public String getDatabase() { 161 | return shard.getAuth().getSource().value(); 162 | } 163 | }, LOGGER); 164 | } 165 | } 166 | } 167 | 168 | if (config.getBackend().isLike(AbstractPostgres.class)) { 169 | AbstractPostgres postgres = config.getBackend().as(AbstractPostgres.class); 170 | 171 | if (cliConfig.isAskForPassword()) { 172 | console.print("Database user " + postgres.getUser() + " password:"); 173 | postgres.setPassword(readPwd()); 174 | } 175 | } else if (config.getBackend().isLike(AbstractDerby.class)) { 176 | AbstractDerby derby = config.getBackend().as(AbstractDerby.class); 177 | 178 | if (cliConfig.isAskForPassword()) { 179 | console.print("Database user " + derby.getUser() + " password:"); 180 | derby.setPassword(readPwd()); 181 | } 182 | } 183 | 184 | try { 185 | Clock clock = Clock.systemDefaultZone(); 186 | Service server; 187 | if (config.getProtocol().getMongo().getReplication() == null || config.getProtocol() 188 | .getMongo().getReplication().getShards().isEmpty()) { 189 | Service toroDbServer = new ServerService(createServerConfig(config)); 190 | 191 | toroDbServer.startAsync(); 192 | toroDbServer.awaitRunning(); 193 | 194 | server = toroDbServer; 195 | } else { 196 | throw new UnsupportedOperationException("Replication not supported yet!"); 197 | } 198 | 199 | Runtime.getRuntime().addShutdownHook(new Thread(() -> { 200 | server.stopAsync(); 201 | server.awaitTerminated(); 202 | })); 203 | } catch (CreationException ex) { 204 | ex.getErrorMessages().stream().forEach(m -> { 205 | if (m.getCause() != null) { 206 | LOGGER.error(m.getCause().getMessage()); 207 | } else { 208 | LOGGER.error(m.getMessage()); 209 | } 210 | }); 211 | System.exit(1); 212 | } catch (Throwable ex) { 213 | LOGGER.error("Fatal error on initialization", ex); 214 | Throwable rootCause = Throwables.getRootCause(ex); 215 | String causeMessage = rootCause.getMessage(); 216 | JCommander.getConsole().println("Fatal error while ToroDB was starting: " + causeMessage); 217 | System.exit(1); 218 | } 219 | } 220 | 221 | private static ServerConfig createServerConfig(Config config) { 222 | Clock clock = Clock.systemDefaultZone(); 223 | 224 | MetricsConfig metricsConfig = () -> true; 225 | 226 | Backend backendConfig = config.getBackend(); 227 | backendConfig.setConnectionPoolConfig(config.getGeneric()); 228 | 229 | return new ServerConfig( 230 | Guice.createInjector(new EssentialModule( 231 | new ComponentLoggerFactory("LIFECYCLE"), 232 | metricsConfig, 233 | clock) 234 | ), 235 | generalConfig -> BundleFactory.createBackendBundle( 236 | backendConfig, 237 | generalConfig 238 | ), 239 | getSelfHostAndPort(config), 240 | (generalConfig, coreBundle) -> createMongoDbWpBundle(config, coreBundle, generalConfig), 241 | LOGGER_FACTORY 242 | ); 243 | } 244 | 245 | private static HostAndPort getSelfHostAndPort(Config config) { 246 | Net net = config.getProtocol().getMongo().getNet(); 247 | return HostAndPort.fromParts(net.getBindIp(), net.getPort()); 248 | } 249 | 250 | private static MongoDbWpBundle createMongoDbWpBundle( 251 | Config config, MongoDbCoreBundle coreBundle, BundleConfig generalConfig) { 252 | int port = config.getProtocol().getMongo().getNet().getPort(); 253 | return new MongoDbWpBundle(new MongoDbWpConfig(coreBundle, port, generalConfig)); 254 | } 255 | 256 | private static void configureLogger(CliConfig cliConfig, Config config) { 257 | if (cliConfig.hasConfFile()) { 258 | if (config.getGeneric().getLogLevel() != null) { 259 | Log4jUtils.setRootLevel(config.getGeneric().getLogLevel()); 260 | } 261 | 262 | if (config.getGeneric().getLogPackages() != null) { 263 | Log4jUtils.setLogPackages(config.getGeneric().getLogPackages()); 264 | } 265 | 266 | if (config.getGeneric().getLogFile() != null) { 267 | Log4jUtils.appendToLogFile(config.getGeneric().getLogFile()); 268 | } 269 | } 270 | // If not specified in configuration YAML then the log4j2.xml is used instead (by default) 271 | } 272 | 273 | private static String readPwd() throws IOException { 274 | Console c = JCommander.getConsole(); 275 | if (System.console() == null) { // In Eclipse IDE 276 | InputStream in = System.in; 277 | int max = 50; 278 | byte[] b = new byte[max]; 279 | 280 | int l = in.read(b); 281 | l--;// last character is \n 282 | if (l > 0) { 283 | byte[] e = new byte[l]; 284 | System.arraycopy(b, 0, e, 0, l); 285 | return new String(e, Charsets.UTF_8); 286 | } else { 287 | return null; 288 | } 289 | } else { // Outside Eclipse IDE 290 | return new String(c.readPassword(false)); 291 | } 292 | } 293 | 294 | private static void parseToropassFile(Config config) { 295 | BackendImplementationVisitor visitor = 296 | new BackendImplementationVisitorWithDefault() { 297 | @Override 298 | public 299 | Void defaultVisit(T value, Void arg) { 300 | try { 301 | ConfigUtils.parseToropassFile(value, LOGGER); 302 | } catch (Exception ex) { 303 | throw new SystemException(ex); 304 | } 305 | return null; 306 | } 307 | }; 308 | 309 | config.getBackend().getBackendImplementation().accept(visitor, null); 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/jackson/BackendDeserializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.jackson; 19 | 20 | import com.google.common.collect.ImmutableMap; 21 | import com.torodb.packaging.config.jackson.AbstractBackendDeserializer; 22 | import com.torodb.standalone.config.model.backend.Backend; 23 | 24 | public class BackendDeserializer extends AbstractBackendDeserializer { 25 | 26 | public BackendDeserializer() { 27 | super(() -> new Backend(), ImmutableMap.of()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/jackson/BackendSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.jackson; 19 | 20 | import com.google.common.collect.ImmutableMap; 21 | import com.torodb.packaging.config.jackson.AbstractBackendSerializer; 22 | import com.torodb.standalone.config.model.backend.Backend; 23 | 24 | public class BackendSerializer extends AbstractBackendSerializer { 25 | 26 | public BackendSerializer() { 27 | super( 28 | ImmutableMap.of() 29 | ); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/model/Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 22 | import com.torodb.packaging.config.annotation.Description; 23 | import com.torodb.packaging.config.model.generic.Generic; 24 | import com.torodb.standalone.config.model.backend.Backend; 25 | import com.torodb.standalone.config.model.protocol.Protocol; 26 | 27 | import javax.validation.Valid; 28 | import javax.validation.constraints.NotNull; 29 | 30 | @JsonPropertyOrder({"generic", "protocol", "backend"}) 31 | public class Config { 32 | 33 | @NotNull 34 | @Valid 35 | @JsonProperty(required = true) 36 | private Generic generic = new Generic(); 37 | @NotNull 38 | @Valid 39 | @JsonProperty(required = true) 40 | private Protocol protocol = new Protocol(); 41 | @Description("config.backend") 42 | @NotNull 43 | @Valid 44 | @JsonProperty(required = true) 45 | private Backend backend = new Backend(); 46 | 47 | public Generic getGeneric() { 48 | return generic; 49 | } 50 | 51 | public void setGeneric(Generic generic) { 52 | this.generic = generic; 53 | } 54 | 55 | public Protocol getProtocol() { 56 | return protocol; 57 | } 58 | 59 | public void setProtocol(Protocol protocol) { 60 | this.protocol = protocol; 61 | } 62 | 63 | public Backend getBackend() { 64 | return backend; 65 | } 66 | 67 | public void setBackend(Backend backend) { 68 | this.backend = backend; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/model/backend/Backend.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.model.backend; 19 | 20 | import com.fasterxml.jackson.annotation.JsonIgnore; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import com.fasterxml.jackson.annotation.JsonSubTypes; 23 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 24 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 25 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 26 | import com.google.common.collect.ImmutableMap; 27 | import com.torodb.packaging.config.model.backend.AbstractBackend; 28 | import com.torodb.packaging.config.model.backend.BackendImplementation; 29 | import com.torodb.packaging.config.model.backend.ConnectionPoolConfig; 30 | import com.torodb.standalone.config.jackson.BackendDeserializer; 31 | import com.torodb.standalone.config.jackson.BackendSerializer; 32 | import com.torodb.standalone.config.model.backend.derby.Derby; 33 | import com.torodb.standalone.config.model.backend.postgres.Postgres; 34 | 35 | import javax.validation.Valid; 36 | import javax.validation.constraints.NotNull; 37 | 38 | @JsonSerialize(using = BackendSerializer.class) 39 | @JsonDeserialize(using = BackendDeserializer.class) 40 | public class Backend extends AbstractBackend { 41 | 42 | private ConnectionPoolConfig connectionPoolConfig; 43 | 44 | public static final ImmutableMap> BACKEND_CLASSES = 45 | ImmutableMap.>builder() 46 | .put("postgres", Postgres.class) 47 | .put("derby", Derby.class) 48 | .build(); 49 | 50 | public Backend() { 51 | this(new Postgres()); 52 | } 53 | 54 | public Backend(BackendImplementation backendImplementation) { 55 | super(BACKEND_CLASSES); 56 | setBackendImplementation(backendImplementation); 57 | } 58 | 59 | @JsonIgnore 60 | @Override 61 | public ConnectionPoolConfig getConnectionPoolConfig() { 62 | return connectionPoolConfig; 63 | } 64 | 65 | @JsonIgnore 66 | public void setConnectionPoolConfig(ConnectionPoolConfig connectionPoolConfig) { 67 | //TODO(gortiz): this is a patch. On Stampede connection pool is here, but on 68 | //Server, as it is using a legacy config file, is on Generic. 69 | //The main class (not jackson) set this property to the correct value before this class is used 70 | this.connectionPoolConfig = connectionPoolConfig; 71 | } 72 | 73 | @NotNull 74 | @Valid 75 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) 76 | @JsonSubTypes({@JsonSubTypes.Type(name = "postgres", value = Postgres.class), 77 | @JsonSubTypes.Type(name = "derby", value = Derby.class),}) 78 | @JsonProperty(required = true) 79 | public BackendImplementation getBackendImplementation() { 80 | return super.getBackendImplementation(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/model/backend/derby/Derby.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.model.backend.derby; 19 | 20 | import com.fasterxml.jackson.annotation.JsonIgnore; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 23 | import com.torodb.packaging.config.annotation.Description; 24 | import com.torodb.packaging.config.validation.ExistsAnyPassword; 25 | import com.torodb.packaging.config.validation.Host; 26 | import com.torodb.packaging.config.validation.InMemoryOnlyIfEmbedded; 27 | import com.torodb.packaging.config.validation.Port; 28 | 29 | import javax.validation.constraints.NotNull; 30 | 31 | @Description("config.backend.derby") 32 | @JsonPropertyOrder({"host", "port", "database", "user", "password", "toropassFile", 33 | "applicationName", "embedded", "inMemory"}) 34 | @ExistsAnyPassword 35 | @InMemoryOnlyIfEmbedded 36 | public class Derby extends com.torodb.packaging.config.model.backend.derby.AbstractDerby { 37 | 38 | public Derby() { 39 | super( 40 | "localhost", 41 | 1527, 42 | "torod", 43 | "torodb", 44 | null, 45 | System.getProperty("user.home", "/") + "/.toropass", 46 | "toro", 47 | false, 48 | true, 49 | true); 50 | } 51 | 52 | @Description("config.backend.postgres.host") 53 | @NotNull 54 | @Host 55 | @JsonProperty(required = true) 56 | @Override 57 | public String getHost() { 58 | return super.getHost(); 59 | } 60 | 61 | @Description("config.backend.postgres.port") 62 | @NotNull 63 | @Port 64 | @JsonProperty(required = true) 65 | @Override 66 | public Integer getPort() { 67 | return super.getPort(); 68 | } 69 | 70 | @Description("config.backend.postgres.database") 71 | @NotNull 72 | @JsonProperty(required = true) 73 | @Override 74 | public String getDatabase() { 75 | return super.getDatabase(); 76 | } 77 | 78 | @Description("config.backend.postgres.user") 79 | @NotNull 80 | @JsonProperty(required = true) 81 | @Override 82 | public String getUser() { 83 | return super.getUser(); 84 | } 85 | 86 | @JsonIgnore 87 | @Override 88 | public String getPassword() { 89 | return super.getPassword(); 90 | } 91 | 92 | @Description("config.backend.postgres.toropassFile") 93 | @Override 94 | public String getToropassFile() { 95 | return super.getToropassFile(); 96 | } 97 | 98 | @Description("config.backend.postgres.applicationName") 99 | @NotNull 100 | @JsonProperty(required = true) 101 | @Override 102 | public Boolean getEmbedded() { 103 | return super.getEmbedded(); 104 | } 105 | 106 | @Description("config.backend.postgres.includeForeignKeys") 107 | @NotNull 108 | @JsonProperty(required = true) 109 | @Override 110 | public Boolean getInMemory() { 111 | return super.getInMemory(); 112 | } 113 | 114 | @Description("config.backend.derby.embedded") 115 | @NotNull 116 | @JsonProperty(required = true) 117 | @Override 118 | public String getApplicationName() { 119 | return super.getApplicationName(); 120 | } 121 | 122 | @Description("config.backend.derby.inMemory") 123 | @NotNull 124 | @JsonProperty(required = true) 125 | @Override 126 | public Boolean getIncludeForeignKeys() { 127 | return super.getIncludeForeignKeys(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/model/backend/postgres/Postgres.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.model.backend.postgres; 19 | 20 | import com.fasterxml.jackson.annotation.JsonIgnore; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 23 | import com.torodb.packaging.config.annotation.Description; 24 | import com.torodb.packaging.config.model.backend.postgres.AbstractPostgres; 25 | import com.torodb.packaging.config.util.ConfigUtils; 26 | import com.torodb.packaging.config.validation.ExistsAnyPassword; 27 | import com.torodb.packaging.config.validation.Host; 28 | import com.torodb.packaging.config.validation.Port; 29 | 30 | import javax.validation.constraints.NotNull; 31 | 32 | @Description("config.backend.postgres") 33 | @JsonPropertyOrder({"host", "port", "database", "user", "password", "toropassFile", 34 | "applicationName", "includeForeignKeys", "ssl"}) 35 | @ExistsAnyPassword 36 | public class Postgres extends AbstractPostgres { 37 | 38 | public Postgres() { 39 | super( 40 | "localhost", 41 | 5432, 42 | "torod", 43 | "torodb", 44 | null, 45 | ConfigUtils.getUserHomeFilePath(".toropass"), 46 | "toro", 47 | false, 48 | false 49 | ); 50 | } 51 | 52 | @Description("config.backend.postgres.host") 53 | @NotNull 54 | @Host 55 | @JsonProperty(required = true) 56 | @Override 57 | public String getHost() { 58 | return super.getHost(); 59 | } 60 | 61 | @Description("config.backend.postgres.port") 62 | @NotNull 63 | @Port 64 | @JsonProperty(required = true) 65 | @Override 66 | public Integer getPort() { 67 | return super.getPort(); 68 | } 69 | 70 | @Description("config.backend.postgres.database") 71 | @NotNull 72 | @JsonProperty(required = true) 73 | @Override 74 | public String getDatabase() { 75 | return super.getDatabase(); 76 | } 77 | 78 | @Description("config.backend.postgres.user") 79 | @NotNull 80 | @JsonProperty(required = true) 81 | @Override 82 | public String getUser() { 83 | return super.getUser(); 84 | } 85 | 86 | @JsonIgnore 87 | @Override 88 | public String getPassword() { 89 | return super.getPassword(); 90 | } 91 | 92 | @Description("config.backend.postgres.toropassFile") 93 | @JsonProperty(required = true) 94 | @Override 95 | public String getToropassFile() { 96 | return super.getToropassFile(); 97 | } 98 | 99 | @Description("config.backend.postgres.applicationName") 100 | @NotNull 101 | @JsonProperty(required = true) 102 | @Override 103 | public String getApplicationName() { 104 | return super.getApplicationName(); 105 | } 106 | 107 | @Description("config.backend.postgres.includeForeignKeys") 108 | @NotNull 109 | @JsonProperty(required = true) 110 | @Override 111 | public Boolean getIncludeForeignKeys() { 112 | return super.getIncludeForeignKeys(); 113 | } 114 | 115 | @Description("config.backend.postgres.ssl") 116 | @NotNull 117 | @JsonProperty(required = false) 118 | @Override 119 | public Boolean getSsl() { 120 | return super.getSsl(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/model/protocol/Protocol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.model.protocol; 19 | 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.torodb.standalone.config.model.protocol.mongo.Mongo; 22 | 23 | import javax.validation.Valid; 24 | 25 | public class Protocol { 26 | 27 | @Valid 28 | @JsonProperty(required = true) 29 | private Mongo mongo = new Mongo(); 30 | 31 | public Mongo getMongo() { 32 | return mongo; 33 | } 34 | 35 | public void setMongo(Mongo mongo) { 36 | this.mongo = mongo; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/model/protocol/mongo/Mongo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.model.protocol.mongo; 19 | 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 22 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 23 | import com.torodb.packaging.config.annotation.Description; 24 | import com.torodb.packaging.config.model.protocol.mongo.Net; 25 | import com.torodb.packaging.config.util.ConfigUtils; 26 | import com.torodb.packaging.config.validation.NoDuplicatedReplName; 27 | import com.torodb.packaging.config.validation.RequiredParametersForAuthentication; 28 | import com.torodb.packaging.config.validation.SslEnabledForX509Authentication; 29 | 30 | import javax.validation.Valid; 31 | import javax.validation.constraints.NotNull; 32 | 33 | @Description("config.protocol.mongo") 34 | @JsonPropertyOrder({"net", "replication", "cursorTimeout", "mongopassFile"}) 35 | public class Mongo { 36 | 37 | @NotNull 38 | @Valid 39 | @JsonProperty(required = true) 40 | private Net net = new Net(); 41 | @Valid 42 | @NoDuplicatedReplName 43 | @SslEnabledForX509Authentication 44 | @RequiredParametersForAuthentication 45 | @JsonDeserialize(contentAs = Replication.class) 46 | private Replication replication; 47 | @Description("config.mongo.mongopassFile") 48 | @JsonProperty(required = true) 49 | private String mongopassFile = ConfigUtils.getUserHomeFilePath(".mongopass"); 50 | 51 | public Net getNet() { 52 | return net; 53 | } 54 | 55 | public void setNet(Net net) { 56 | this.net = net; 57 | } 58 | 59 | public Replication getReplication() { 60 | return replication; 61 | } 62 | 63 | public void setReplication(Replication replication) { 64 | this.replication = replication; 65 | } 66 | 67 | public String getMongopassFile() { 68 | return mongopassFile; 69 | } 70 | 71 | public void setMongopassFile(String mongopassFile) { 72 | this.mongopassFile = mongopassFile; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/model/protocol/mongo/Replication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.model.protocol.mongo; 19 | 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 22 | import com.torodb.packaging.config.annotation.Description; 23 | import com.torodb.packaging.config.model.common.EnumWithDefault; 24 | import com.torodb.packaging.config.model.common.ListOfStringWithDefault; 25 | import com.torodb.packaging.config.model.common.StringWithDefault; 26 | import com.torodb.packaging.config.model.protocol.mongo.AbstractReplication; 27 | import com.torodb.packaging.config.model.protocol.mongo.AbstractShardReplication; 28 | import com.torodb.packaging.config.model.protocol.mongo.Auth; 29 | import com.torodb.packaging.config.model.protocol.mongo.FilterList; 30 | import com.torodb.packaging.config.model.protocol.mongo.Role; 31 | import com.torodb.packaging.config.model.protocol.mongo.Ssl; 32 | import com.torodb.packaging.config.validation.NotEmptyListOfSrtingWithDefault; 33 | import com.torodb.packaging.config.validation.NotEmptySrtingWithDefault; 34 | import com.torodb.packaging.config.validation.NotNullElements; 35 | 36 | import java.util.List; 37 | 38 | import javax.validation.constraints.NotNull; 39 | 40 | @JsonPropertyOrder({"replSetName", "syncSource", 41 | "role", "ssl", "auth", "include", "exclude", "shards"}) 42 | public class Replication extends AbstractReplication { 43 | 44 | @Description("config.mongo.replication.replSetName") 45 | @NotEmptySrtingWithDefault 46 | @JsonProperty(required = true) 47 | public StringWithDefault getReplSetName() { 48 | return super.getReplSetName(); 49 | } 50 | 51 | @Description("config.mongo.replication.role") 52 | @NotNull 53 | @JsonProperty(required = true) 54 | public EnumWithDefault getRole() { 55 | return super.getRole(); 56 | } 57 | 58 | @Description("config.mongo.replication.syncSource") 59 | @NotEmptyListOfSrtingWithDefault 60 | @JsonProperty(required = true) 61 | public ListOfStringWithDefault getSyncSource() { 62 | return super.getSyncSource(); 63 | } 64 | 65 | @Description("config.mongo.replication.ssl") 66 | @NotNull 67 | @JsonProperty(required = true) 68 | public Ssl getSsl() { 69 | return super.getSsl(); 70 | } 71 | 72 | @Description("config.mongo.replication.auth") 73 | @NotNull 74 | @JsonProperty(required = true) 75 | public Auth getAuth() { 76 | return super.getAuth(); 77 | } 78 | 79 | @Description("config.mongo.replication.include") 80 | @JsonProperty(required = true) 81 | public FilterList getInclude() { 82 | return super.getInclude(); 83 | } 84 | 85 | @Description("config.mongo.replication.exclude") 86 | @JsonProperty(required = true) 87 | public FilterList getExclude() { 88 | return super.getExclude(); 89 | } 90 | 91 | @NotNullElements 92 | @JsonProperty(required = true) 93 | public List getShards() { 94 | return super.getShardList(); 95 | } 96 | 97 | public void setShards(List shards) { 98 | super.setShardList(shards); 99 | } 100 | 101 | public Replication mergeWith(AbstractShardReplication shard) { 102 | Replication mergedShard = new Replication(); 103 | 104 | merge(shard, mergedShard); 105 | 106 | return mergedShard; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /main/src/main/java/com/torodb/standalone/config/model/protocol/mongo/ShardReplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config.model.protocol.mongo; 19 | 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 22 | import com.torodb.packaging.config.annotation.Description; 23 | import com.torodb.packaging.config.model.common.EnumWithDefault; 24 | import com.torodb.packaging.config.model.common.ListOfStringWithDefault; 25 | import com.torodb.packaging.config.model.common.StringWithDefault; 26 | import com.torodb.packaging.config.model.protocol.mongo.AbstractShardReplication; 27 | import com.torodb.packaging.config.model.protocol.mongo.Auth; 28 | import com.torodb.packaging.config.model.protocol.mongo.Role; 29 | import com.torodb.packaging.config.model.protocol.mongo.Ssl; 30 | import com.torodb.packaging.config.validation.NotEmptyListOfSrtingWithDefault; 31 | import com.torodb.packaging.config.validation.NotEmptySrtingWithDefault; 32 | 33 | import javax.validation.constraints.NotNull; 34 | 35 | @JsonPropertyOrder({"replSetName", "syncSource", "role", "ssl", "auth"}) 36 | public class ShardReplication extends AbstractShardReplication { 37 | 38 | @Description("config.mongo.replication.replSetName") 39 | @NotEmptySrtingWithDefault 40 | @JsonProperty(required = true) 41 | public StringWithDefault getReplSetName() { 42 | return super.getReplSetName(); 43 | } 44 | 45 | @Description("config.mongo.replication.role") 46 | @NotNull 47 | @JsonProperty(required = true) 48 | public EnumWithDefault getRole() { 49 | return super.getRole(); 50 | } 51 | 52 | @Description("config.mongo.replication.syncSource") 53 | @NotEmptyListOfSrtingWithDefault 54 | @JsonProperty(required = true) 55 | public ListOfStringWithDefault getSyncSource() { 56 | return super.getSyncSource(); 57 | } 58 | 59 | @Description("config.mongo.replication.ssl") 60 | @NotNull 61 | @JsonProperty(required = true) 62 | public Ssl getSsl() { 63 | return super.getSsl(); 64 | } 65 | 66 | @Description("config.mongo.replication.auth") 67 | @NotNull 68 | @JsonProperty(required = true) 69 | public Auth getAuth() { 70 | return super.getAuth(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /main/src/main/profiles/dev/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /main/src/main/profiles/prod/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /main/src/main/resources/CliMessages.properties: -------------------------------------------------------------------------------- 1 | help=Print help and exit. 2 | print-config=Print the configuration in YAML format and exit. 3 | print-xml-config=Print the configuration in XML format and exit. 4 | help-param=Print help for all available parameters and exit. 5 | help-param-header=Parameters help (-p or --param flag):\n\nTo specify a parameter use the syntax = where:\n\t\ 6 | follow JSON pointer format (http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-03) with the exception that you can omit the first '/' character.\n\t\ 7 | have the same syntax as values in YAML 1.1 format (http://yaml.org/spec/1.1/).\n\n\ 8 | You can specify any number of parameters by repeating -p or --param flag. Possible paths are:\n 9 | 10 | conf=Configuration file in YAML format. 11 | xml-conf=Configuration file in XML format. 12 | backend=Specify the backend to use with default values. 13 | param=Specify a configuration parameter using = syntax. Use --help-param to see all available parameters. 14 | ask-for-password=Force input of PostgreSQL's database user password. -------------------------------------------------------------------------------- /main/src/main/resources/ConfigMessages.properties: -------------------------------------------------------------------------------- 1 | config.generic=Generic ToroDB configuration 2 | config.generic.logLevel=Level of log emitted (will overwrite default log4j2 configuration) 3 | config.generic.logPackages=Specifies level of log emitted for packages 4 | config.generic.logFile=File where log will be written 5 | config.generic.log4j2File=Log4j2 configuration file 6 | config.generic.connectionPoolTimeout=The timeout in milliseconds after which retrieve a connection from the pool will fail. 7 | config.generic.connectionPoolSize=Maximum number of connections to establish to the database. It must be higher or equal than 3 8 | config.generic.reservedReadPoolSize=Reserved connections that will be reserved to store global cursors. It must be lower than total connections minus 2 9 | config.generic.metricsEnabled=Enable or disable metrics system 10 | 11 | config.protocol.mongo=MongoDB protocol configuration 12 | 13 | config.mongo.net.bindIp=The host or IP associate to the interface where clients will connect to. Use * to specify any interface 14 | config.mongo.net.port=The port where the clients will connect to 15 | config.mongo.replication.replSetName=The name of the MongoDB Replica Set where this instance will attach 16 | config.mongo.replication.role=The role that this instance will assume in the replica set. 17 | config.mongo.role.HIDDEN_SLAVE=The instance will not participate in voting and can not be elected as master 18 | config.mongo.replication.syncSource=The host and port (:) of the node from ToroDB has to replicate. If this node must run as primary, this paramenter must not be defined 19 | config.mongo.replication.shard.name=The name that will be appended to database identifier for the specified shard 20 | config.mongo.replication.ssl=SSL configuration for replication connection to MongoDB 21 | config.mongo.replication.ssl.enabled=Enable or disable SSL/TLS layer 22 | config.mongo.replication.ssl.allowInvalidHostnames=Disable hostname verification 23 | config.mongo.replication.ssl.fipsMode=Enable FIPS 140-2 mode 24 | config.mongo.replication.ssl.caFile=The path to the Certification Authority in PEM format 25 | config.mongo.replication.ssl.trustStoreFile=The path to the Java Key Store file containing the Certification Authority. If caFile is specified it will be used instead 26 | config.mongo.replication.ssl.trustStorePassword=The password of the Java Key Store file containing the Certification Authority 27 | config.mongo.replication.ssl.keyStoreFile=The path to the Java Key Store file containing the certificate and private key used to authenticate client 28 | config.mongo.replication.ssl.keyStorePassword=The password of the Java Key Store file containing and private key used to authenticate client 29 | config.mongo.replication.ssl.keyPassword=The password of the private key used to authenticate client 30 | config.mongo.replication.auth=Authentication configuration for replication connection to MongoDB 31 | config.mongo.replication.auth.mode=The authentication mode 32 | config.mongo.replication.include=A map of databases and/or collections and/or indexes to exclusively replicate.\n\t# Each entry represent a database name under which a list of collection names can be specified.\n\t# Each collection can contain a list of indexes each formed by one or more of those fields:\n\t# \tname= the index name\n\t# \tunqiue= true when index is unique, false otherwise\n\t# \tkeys/= the name of the field indexed and the index direction or type\n\t# Character '*' can be used to denote "any-character" and character '\\' to protect characters. 33 | config.mongo.replication.exclude=A map of databases and/or collections and/or indexes that will not be replicated (override include property).\n\t# Each entry represent a database name under which a list of collection names can be specified.\n\t# Each collection can contain a list of indexes each formed by one or more of those fields:\n\t# \tname= the index name\n\t# \tunqiue= true when index is unique, false otherwise\n\t# \tkeys/= the name of the field indexed and a comma separated list index type\n\t# Character '*' can be used to denote "any-character" and character '\\' to protect characters. 34 | config.mongo.authmode.disabled=Disable authentication mechanism. No authentication will be done 35 | config.mongo.authmode.negotiate=The client will negotiate best mechanism to authenticate. With server version 3.0 or above, the driver will authenticate using the SCRAM-SHA-1 mechanism. Otherwise, the driver will authenticate using the Challenge Response mechanism 36 | config.mongo.authmode.cr=Challenge Response authentication 37 | config.mongo.authmode.x509=X.509 authentication 38 | config.mongo.authmode.scram_sha1=SCRAM-SHA-1 SASL authentication 39 | config.mongo.replication.auth.user=The user that will be authenticate 40 | config.mongo.replication.auth.source=The source database where the user is present 41 | config.mongo.replication.auth.gssapiServiceName=This property is used when the service's name is different that the default of mongodb. 42 | config.mongo.replication.auth.gssapiHostName=This property is used when the fully qualified domain name (FQDN) of the host is required to properly authenticate. 43 | config.mongo.replication.auth.gssapiSubject=This property is used for overriding the Subject under which GSSAPI authentication executes. 44 | config.mongo.replication.auth.gssapiSaslClientProperties=While rarely needed, this property is used to replace the SasClient properties. 45 | config.mongo.cursorTimeout=The timeout in milliseconds after which an opened cursor will be closed automatically. 46 | config.mongo.mongopassFile=You can specify a file that use .pgpass syntax: :::: (can have multiple lines) 47 | 48 | config.backend=Backend configuration (only one /backend/ section can be specified) 49 | 50 | config.backend.postgres=PostgreSQL configuration (default) 51 | config.backend.postgres.host=The host or ip that will be used to connect 52 | config.backend.postgres.port=The port that will be used to connect 53 | config.backend.postgres.database=The database that will be used 54 | config.backend.postgres.user=The user that will be used to connect 55 | config.backend.postgres.password=Specify password that will be used to connect 56 | config.backend.postgres.toropassFile=You can specify a file that use .pgpass syntax: :::: (can have multiple lines) 57 | config.backend.postgres.applicationName=The application name used by driver to connect 58 | config.backend.postgres.includeForeignKeys=If enabled internal columns relations between data tables will be enforced by foreign keys. 59 | config.backend.postgres.ssl=If true enabled the SSL connection with PostgreSQL server, if false is disabled. 60 | 61 | config.backend.derby=Derby configuration 62 | config.backend.derby.embedded=True to run derby as embedded database, false otherwise 63 | config.backend.derby.inMemory=True to run derby as in-memory database (config.backend.derby.embedded must be true), false otherwise 64 | -------------------------------------------------------------------------------- /main/src/main/resources/ValidationMessages.properties: -------------------------------------------------------------------------------- 1 | config.validation.NoDuplicatedReplName.message = found duplicate replSetName 2 | config.validation.NotNullElements.message = found null element in list 3 | config.validation.NotEmptyString.message = empty string are not allowed 4 | config.validation.NotEmptyListOfString.message = empty list or empty string in list are not allowed 5 | config.validation.Host.message = host must be an IP or hostname 6 | config.validation.Port.message = port must be in range 0-65535 7 | config.validation.InMemoryOnlyIfEmbedded.message = derby must be also embedded to run in memory 8 | config.validation.RequiredParametersForAuthentication.message = some required parameters are not defined for selected authentication mode 9 | config.validation.SSLEnabledForX509Authentication.message = SSL should be enabled and configured with a client certificate 10 | config.validation.MutualExclusiveReplSetOrShards.message = you can not specify syncSource and replSetName both with shards section 11 | -------------------------------------------------------------------------------- /main/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | 2 | akka { 3 | loggers = ["akka.event.slf4j.Slf4jLogger"] 4 | loglevel = "DEBUG" 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | } 7 | 8 | -------------------------------------------------------------------------------- /main/src/test/java/com/torodb/standalone/config/ByteArrayConsole.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config; 19 | 20 | import com.beust.jcommander.internal.Console; 21 | 22 | import java.io.ByteArrayOutputStream; 23 | import java.io.PrintStream; 24 | 25 | public class ByteArrayConsole implements Console { 26 | 27 | private final ByteArrayOutputStream byteArrayOutputStream; 28 | private final PrintStream printStream; 29 | 30 | public ByteArrayConsole() { 31 | byteArrayOutputStream = new ByteArrayOutputStream(); 32 | printStream = new PrintStream(byteArrayOutputStream); 33 | } 34 | 35 | public ByteArrayOutputStream getByteArrayOutputStream() { 36 | return byteArrayOutputStream; 37 | } 38 | 39 | @Override 40 | public char[] readPassword(boolean echoInput) { 41 | return null; 42 | } 43 | 44 | @Override 45 | public void println(String msg) { 46 | printStream.println(msg); 47 | } 48 | 49 | @Override 50 | public void print(String msg) { 51 | printStream.print(msg); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /main/src/test/java/com/torodb/standalone/config/ConfigTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.config; 19 | 20 | import com.google.common.collect.ImmutableList; 21 | import com.google.common.collect.ImmutableMap; 22 | import com.torodb.packaging.config.model.generic.LogLevel; 23 | import com.torodb.packaging.config.model.protocol.mongo.FilterList.IndexFilter; 24 | import com.torodb.packaging.config.model.protocol.mongo.Role; 25 | import com.torodb.packaging.config.util.ConfigUtils; 26 | import com.torodb.standalone.CliConfig; 27 | import com.torodb.standalone.CliConfigUtils; 28 | import com.torodb.standalone.config.model.Config; 29 | import com.torodb.standalone.config.model.backend.derby.Derby; 30 | import com.torodb.standalone.config.model.backend.postgres.Postgres; 31 | import org.junit.After; 32 | import org.junit.AfterClass; 33 | import org.junit.Assert; 34 | import org.junit.Before; 35 | import org.junit.BeforeClass; 36 | import org.junit.Test; 37 | 38 | import java.io.File; 39 | import java.io.InputStream; 40 | import java.util.Arrays; 41 | import java.util.List; 42 | import java.util.PropertyResourceBundle; 43 | import java.util.ResourceBundle; 44 | 45 | public class ConfigTest { 46 | 47 | public ConfigTest() { 48 | } 49 | 50 | @BeforeClass 51 | public static void setUpClass() { 52 | } 53 | 54 | @AfterClass 55 | public static void tearDownClass() { 56 | } 57 | 58 | @Before 59 | public void setUp() { 60 | } 61 | 62 | @After 63 | public void tearDown() { 64 | } 65 | 66 | @Test 67 | public void testPrintConf() throws Exception { 68 | ByteArrayConsole byteArrayConsole = new ByteArrayConsole(); 69 | ConfigUtils.printYamlConfig(new Config(), byteArrayConsole); 70 | ConfigUtils.readConfigFromYaml(Config.class, new String(byteArrayConsole 71 | .getByteArrayOutputStream().toByteArray())); 72 | } 73 | 74 | @Test 75 | public void testPrintXmlConf() throws Exception { 76 | ByteArrayConsole byteArrayConsole = new ByteArrayConsole(); 77 | ConfigUtils.printXmlConfig(new Config(), byteArrayConsole); 78 | ConfigUtils.readConfigFromXml(Config.class, new String(byteArrayConsole 79 | .getByteArrayOutputStream().toByteArray())); 80 | } 81 | 82 | @Test 83 | public void testHelpParam() throws Exception { 84 | ResourceBundle configBundle = PropertyResourceBundle.getBundle("ConfigMessages"); 85 | ConfigUtils.printParamDescriptionFromConfigSchema(Config.class, configBundle, 86 | new ByteArrayConsole(), 0); 87 | } 88 | 89 | @Test 90 | public void testParse() throws Exception { 91 | CliConfigUtils.readConfig(new CliConfig()); 92 | } 93 | 94 | @Test 95 | public void testParseWithParam() throws Exception { 96 | File tempFile = File.createTempFile("torodb", ".log"); 97 | tempFile.deleteOnExit(); 98 | final String logFile = tempFile.getPath(); 99 | 100 | CliConfig cliConfig = new CliConfig() { 101 | @Override 102 | public List getParams() { 103 | String[] params = new String[]{ 104 | "/generic/logFile=" + logFile 105 | }; 106 | return Arrays.asList(params); 107 | } 108 | }; 109 | Config config = CliConfigUtils.readConfig(cliConfig); 110 | 111 | Assert.assertEquals("Parameter has different value than that specified", logFile, config 112 | .getGeneric().getLogFile()); 113 | } 114 | 115 | @Test 116 | public void testParseWithNullParam() throws Exception { 117 | CliConfig cliConfig = new CliConfig() { 118 | @Override 119 | public List getParams() { 120 | String[] params = new String[]{ 121 | "/generic/logFile=null" 122 | }; 123 | return Arrays.asList(params); 124 | } 125 | }; 126 | Config config = CliConfigUtils.readConfig(cliConfig); 127 | 128 | Assert.assertEquals("Parameter has different value than that specified", null, config 129 | .getGeneric().getLogFile()); 130 | } 131 | 132 | @Test 133 | public void testParseWithLogPackagesParam() throws Exception { 134 | final String logPackage = "com.torodb"; 135 | final LogLevel logLevel = LogLevel.NONE; 136 | 137 | CliConfig cliConfig = new CliConfig() { 138 | @Override 139 | public List getParams() { 140 | String[] params = new String[]{ 141 | "/generic/logPackages/" + logPackage + "=" + logLevel.name() 142 | }; 143 | return Arrays.asList(params); 144 | } 145 | }; 146 | Config config = CliConfigUtils.readConfig(cliConfig); 147 | 148 | Assert.assertTrue("/generic/logPackages not defined", config.getGeneric().getLogPackages() 149 | != null); 150 | Assert.assertTrue("/generic/logPackages/" + logPackage + " not defined", config.getGeneric() 151 | .getLogPackages().get(logPackage) != null); 152 | Assert.assertEquals("/generic/logPackages has not 1 entry", 1, config.getGeneric() 153 | .getLogPackages().size()); 154 | Assert.assertEquals("/generic/logPackages/" + logPackage 155 | + " has different value than that specified", logLevel, config.getGeneric().getLogPackages() 156 | .get(logPackage)); 157 | } 158 | 159 | @Test(expected = IllegalArgumentException.class) 160 | public void testParseWithPasswordParam() throws Exception { 161 | CliConfig cliConfig = new CliConfig() { 162 | @Override 163 | public List getParams() { 164 | String[] params = new String[]{ 165 | "/backend/postgres/password=toor" 166 | }; 167 | return Arrays.asList(params); 168 | } 169 | }; 170 | CliConfigUtils.readConfig(cliConfig); 171 | } 172 | 173 | @Test(expected = IllegalArgumentException.class) 174 | public void testParseWithWrongTypeParam() throws Exception { 175 | CliConfig cliConfig = new CliConfig() { 176 | @Override 177 | public List getParams() { 178 | String[] params = new String[]{ 179 | "/generic/logLevel=ALL" 180 | }; 181 | return Arrays.asList(params); 182 | } 183 | }; 184 | CliConfigUtils.readConfig(cliConfig); 185 | } 186 | 187 | @Test(expected = IllegalArgumentException.class) 188 | public void testParseWithEmptyYAML() throws Exception { 189 | CliConfig cliConfig = new CliConfig() { 190 | @Override 191 | public boolean hasConfFile() { 192 | return true; 193 | } 194 | 195 | @Override 196 | public InputStream getConfInputStream() { 197 | return ConfigTest.class.getResourceAsStream("/test-parse-with-empty-yaml.yml"); 198 | } 199 | }; 200 | Config config = CliConfigUtils.readConfig(cliConfig); 201 | 202 | Assert.assertTrue("/generic not defined", config.getGeneric() != null); 203 | Assert.assertTrue("/protocol not defined", config.getProtocol() != null); 204 | Assert.assertTrue("/protocol/mongo not defined", config.getProtocol().getMongo() != null); 205 | Assert.assertTrue("/protocol/mongo/net not defined", config.getProtocol().getMongo().getNet() 206 | != null); 207 | Assert.assertTrue("/backend not defined", config.getBackend() != null); 208 | Assert.assertEquals("/backend/postgres not defined", Postgres.class, config.getBackend() 209 | .getBackendImplementation().getClass()); 210 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres", config.getBackend() 211 | .is(Postgres.class)); 212 | } 213 | 214 | @Test(expected = IllegalArgumentException.class) 215 | public void testParseWithWrongYAML() throws Exception { 216 | CliConfig cliConfig = new CliConfig() { 217 | @Override 218 | public boolean hasConfFile() { 219 | return true; 220 | } 221 | 222 | @Override 223 | public InputStream getConfInputStream() { 224 | return ConfigTest.class.getResourceAsStream("/test-parse-with-wrong-yaml.yml"); 225 | } 226 | }; 227 | CliConfigUtils.readConfig(cliConfig); 228 | } 229 | 230 | @Test 231 | public void testParseWithYAML() throws Exception { 232 | CliConfig cliConfig = new CliConfig() { 233 | @Override 234 | public boolean hasConfFile() { 235 | return true; 236 | } 237 | 238 | @Override 239 | public InputStream getConfInputStream() { 240 | return ConfigTest.class.getResourceAsStream("/test-parse-with-yaml.yml"); 241 | } 242 | }; 243 | Config config = CliConfigUtils.readConfig(cliConfig); 244 | 245 | Assert.assertTrue("/generic not defined", config.getGeneric() != null); 246 | Assert.assertTrue("/generic/logPackages not defined", config.getGeneric().getLogPackages() 247 | != null); 248 | Assert.assertTrue("/generic/logPackages/com.torodb not defined", config.getGeneric() 249 | .getLogPackages().get("com.torodb") != null); 250 | Assert.assertEquals("/generic/logLevel has different value than that specified", LogLevel.NONE, 251 | config.getGeneric().getLogLevel()); 252 | Assert.assertEquals("/generic/logPackages has not 1 entry", 1, config.getGeneric() 253 | .getLogPackages().size()); 254 | Assert.assertEquals("/generic/logPackages/com.torodb has different value than that specified", 255 | LogLevel.DEBUG, config.getGeneric().getLogPackages().get("com.torodb")); 256 | Assert.assertTrue("/protocol not defined", config.getProtocol() != null); 257 | Assert.assertTrue("/protocol/mongo not defined", config.getProtocol().getMongo() != null); 258 | Assert.assertTrue("/protocol/mongo/net not defined", config.getProtocol().getMongo().getNet() 259 | != null); 260 | Assert.assertEquals("/protocol/mongo/net/port has different value than that specified", Integer 261 | .valueOf(27019), config.getProtocol().getMongo().getNet().getPort()); 262 | Assert.assertTrue("/protocol/mongo/replication not defined", config.getProtocol().getMongo() 263 | .getReplication() != null); 264 | Assert.assertEquals( 265 | "/protocol/mongo/replication/replSetName has different value than that specified", "rs1", 266 | config.getProtocol().getMongo().getReplication().getReplSetName().value()); 267 | Assert 268 | .assertEquals("/protocol/mongo/replication/role has different value than that specified", 269 | Role.HIDDEN_SLAVE, config.getProtocol().getMongo().getReplication().getRole().value()); 270 | Assert.assertEquals( 271 | "/protocol/mongo/replication/syncSource has different value than that specified", 272 | "localhost:27017", config.getProtocol().getMongo().getReplication().getSyncSource().value().get(0)); 273 | Assert.assertTrue( 274 | "/protocol/mongo/replication/shards not defined", 275 | config.getProtocol().getMongo().getReplication().getShards() != null); 276 | Assert.assertTrue( 277 | "/protocol/mongo/replication/shards not empty", 278 | config.getProtocol().getMongo().getReplication().getShards().isEmpty()); 279 | Assert.assertTrue("/backend not defined", config.getBackend() != null); 280 | Assert.assertEquals("/backend/postgres not defined", Postgres.class, config.getBackend() 281 | .getBackendImplementation().getClass()); 282 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres", config.getBackend() 283 | .is(Postgres.class)); 284 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres Like", config 285 | .getBackend().isLike(Postgres.class)); 286 | Assert.assertEquals("/backend/postgres/host has different value than that specified", 287 | "localhost", config.getBackend().as(Postgres.class).getHost()); 288 | Assert.assertEquals("/backend/postgres/port has different value than that specified", Integer 289 | .valueOf(5432), config.getBackend().as(Postgres.class).getPort()); 290 | Assert.assertEquals("/backend/postgres/user has different value than that specified", "root", 291 | config.getBackend().as(Postgres.class).getUser()); 292 | Assert.assertEquals( 293 | "/backend/postgres/password specified but should have not been read from parameters", null, 294 | config.getBackend().as(Postgres.class).getPassword()); 295 | } 296 | 297 | @Test 298 | public void testParseWithYAMLAndReplaceBackendWithParam() throws Exception { 299 | CliConfig cliConfig = new CliConfig() { 300 | @Override 301 | public boolean hasConfFile() { 302 | return true; 303 | } 304 | 305 | @Override 306 | public InputStream getConfInputStream() { 307 | return ConfigTest.class.getResourceAsStream("/test-parse-with-yaml.yml"); 308 | } 309 | 310 | @Override 311 | public List getParams() { 312 | String[] params = new String[]{ 313 | "/backend=null", 314 | "/backend/derby/host=localhost", 315 | "/backend/derby/port=5432", 316 | "/backend/derby/user=root",}; 317 | return Arrays.asList(params); 318 | } 319 | }; 320 | Config config = CliConfigUtils.readConfig(cliConfig); 321 | 322 | Assert.assertTrue("/backend not defined", config.getBackend() != null); 323 | Assert.assertEquals("/backend/derby not defined", Derby.class, config.getBackend() 324 | .getBackendImplementation().getClass()); 325 | Assert.assertTrue("/backend/derby not identified as AbstractDerby", config.getBackend().is( 326 | Derby.class)); 327 | Assert.assertTrue("/backend/derby not identified as AbstractDerby Like", config.getBackend() 328 | .isLike(Derby.class)); 329 | Assert.assertEquals("/backend/derby/host has different value than that specified", "localhost", 330 | config.getBackend().as(Derby.class).getHost()); 331 | Assert.assertEquals("/backend/derby/port has different value than that specified", Integer 332 | .valueOf(5432), config.getBackend().as(Derby.class).getPort()); 333 | Assert.assertEquals("/backend/derby/user has different value than that specified", "root", 334 | config.getBackend().as(Derby.class).getUser()); 335 | Assert.assertEquals( 336 | "/backend/derby/password specified but should have not been read from parameters", null, 337 | config.getBackend().as(Derby.class).getPassword()); 338 | } 339 | 340 | @Test 341 | public void testParseWithYAMLUsingDerby() throws Exception { 342 | CliConfig cliConfig = new CliConfig() { 343 | @Override 344 | public boolean hasConfFile() { 345 | return true; 346 | } 347 | 348 | @Override 349 | public InputStream getConfInputStream() { 350 | return ConfigTest.class.getResourceAsStream("/test-parse-with-yaml-using-derby.yml"); 351 | } 352 | }; 353 | Config config = CliConfigUtils.readConfig(cliConfig); 354 | 355 | Assert.assertTrue("/backend not defined", config.getBackend() != null); 356 | Assert.assertEquals("/backend/derby not defined", Derby.class, config.getBackend() 357 | .getBackendImplementation().getClass()); 358 | Assert.assertTrue("/backend/derby not identified as AbstractDerby", config.getBackend().is( 359 | Derby.class)); 360 | Assert.assertTrue("/backend/derby not identified as AbstractDerby Like", config.getBackend() 361 | .isLike(Derby.class)); 362 | Assert.assertEquals("/backend/derby/host has different value than that specified", "localhost", 363 | config.getBackend().as(Derby.class).getHost()); 364 | Assert.assertEquals("/backend/derby/port has different value than that specified", Integer 365 | .valueOf(5432), config.getBackend().as(Derby.class).getPort()); 366 | Assert.assertEquals("/backend/derby/user has different value than that specified", "root", 367 | config.getBackend().as(Derby.class).getUser()); 368 | Assert.assertEquals( 369 | "/backend/derby/password specified but should have not been read from parameters", null, 370 | config.getBackend().as(Derby.class).getPassword()); 371 | } 372 | 373 | @Test(expected = IllegalArgumentException.class) 374 | public void testParseWithYAMLUsingPassword() throws Exception { 375 | CliConfig cliConfig = new CliConfig() { 376 | @Override 377 | public boolean hasConfFile() { 378 | return true; 379 | } 380 | 381 | @Override 382 | public InputStream getConfInputStream() { 383 | return ConfigTest.class.getResourceAsStream("/test-parse-with-yaml-using-password.yml"); 384 | } 385 | }; 386 | CliConfigUtils.readConfig(cliConfig); 387 | } 388 | 389 | @Test(expected = IllegalArgumentException.class) 390 | public void testParseWithYAMLUsingEmptyProtocol() throws Exception { 391 | CliConfig cliConfig = new CliConfig() { 392 | @Override 393 | public boolean hasConfFile() { 394 | return true; 395 | } 396 | 397 | @Override 398 | public InputStream getConfInputStream() { 399 | return ConfigTest.class 400 | .getResourceAsStream("/test-parse-with-yaml-using-empty-protocol.yml"); 401 | } 402 | }; 403 | CliConfigUtils.readConfig(cliConfig); 404 | } 405 | 406 | @Test(expected = IllegalArgumentException.class) 407 | public void testParseWithYAMLUsingDoubleBackend() throws Exception { 408 | CliConfig cliConfig = new CliConfig() { 409 | @Override 410 | public boolean hasConfFile() { 411 | return true; 412 | } 413 | 414 | @Override 415 | public InputStream getConfInputStream() { 416 | return ConfigTest.class 417 | .getResourceAsStream("/test-parse-with-yaml-using-double-backend.yml"); 418 | } 419 | }; 420 | CliConfigUtils.readConfig(cliConfig); 421 | } 422 | 423 | @Test 424 | public void testParseWithXML() throws Exception { 425 | CliConfig cliConfig = new CliConfig() { 426 | @Override 427 | public boolean hasXmlConfFile() { 428 | return true; 429 | } 430 | 431 | @Override 432 | public InputStream getXmlConfInputStream() { 433 | return ConfigTest.class.getResourceAsStream("/test-parse-with-xml.xml"); 434 | } 435 | }; 436 | Config config = CliConfigUtils.readConfig(cliConfig); 437 | 438 | Assert.assertTrue("/generic not defined", config.getGeneric() != null); 439 | Assert.assertTrue("/generic/logPackages not defined", config.getGeneric().getLogPackages() 440 | != null); 441 | Assert.assertTrue("/generic/logPackages/com.torodb not defined", config.getGeneric() 442 | .getLogPackages().get("com.torodb") != null); 443 | Assert.assertEquals("/generic/logLevel has different value than that specified", LogLevel.NONE, 444 | config.getGeneric().getLogLevel()); 445 | Assert.assertEquals("/generic/logPackages has not 1 entry", 1, config.getGeneric() 446 | .getLogPackages().size()); 447 | Assert.assertEquals("/generic/logPackages/com.torodb has different value than that specified", 448 | LogLevel.DEBUG, config.getGeneric().getLogPackages().get("com.torodb")); 449 | Assert.assertTrue("/protocol not defined", config.getProtocol() != null); 450 | Assert.assertTrue("/protocol/mongo not defined", config.getProtocol().getMongo() != null); 451 | Assert.assertTrue("/protocol/mongo/net not defined", config.getProtocol().getMongo().getNet() 452 | != null); 453 | Assert.assertEquals("/protocol/mongo/net/port has different value than that specified", Integer 454 | .valueOf(27019), config.getProtocol().getMongo().getNet().getPort()); 455 | Assert.assertTrue("/protocol/mongo/replication not defined", config.getProtocol().getMongo() 456 | .getReplication() != null); 457 | Assert.assertEquals( 458 | "/protocol/mongo/replication/replSetName has different value than that specified", "rs1", 459 | config.getProtocol().getMongo().getReplication().getReplSetName().value()); 460 | Assert 461 | .assertEquals("/protocol/mongo/replication/role has different value than that specified", 462 | Role.HIDDEN_SLAVE, config.getProtocol().getMongo().getReplication().getRole().value()); 463 | Assert.assertEquals( 464 | "/protocol/mongo/replication/syncSource has different value than that specified", 465 | "localhost:27017", config.getProtocol().getMongo().getReplication().getSyncSource().value().get(0)); 466 | Assert.assertTrue( 467 | "/protocol/mongo/replication/shards not defined", 468 | config.getProtocol().getMongo().getReplication().getShards() != null); 469 | Assert.assertTrue( 470 | "/protocol/mongo/replication/shards not empty", 471 | config.getProtocol().getMongo().getReplication().getShards().isEmpty()); 472 | Assert.assertTrue("/backend not defined", config.getBackend() != null); 473 | Assert.assertEquals("/backend/postgres not defined", Postgres.class, config.getBackend() 474 | .getBackendImplementation().getClass()); 475 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres", config.getBackend() 476 | .is(Postgres.class)); 477 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres Like", config 478 | .getBackend().isLike(Postgres.class)); 479 | Assert.assertEquals("/backend/postgres/host has different value than that specified", 480 | "localhost", config.getBackend().as(Postgres.class).getHost()); 481 | Assert.assertEquals("/backend/postgres/port has different value than that specified", Integer 482 | .valueOf(5432), config.getBackend().as(Postgres.class).getPort()); 483 | Assert.assertEquals("/backend/postgres/user has different value than that specified", "root", 484 | config.getBackend().as(Postgres.class).getUser()); 485 | Assert.assertEquals("/backend/postgres/password has different value than that specified", null, 486 | config.getBackend().as(Postgres.class).getPassword()); 487 | } 488 | 489 | @Test 490 | public void testReplicationFiltering() throws Exception { 491 | CliConfig cliConfig = new CliConfig() { 492 | @Override 493 | public boolean hasConfFile() { 494 | return true; 495 | } 496 | 497 | @Override 498 | public InputStream getConfInputStream() { 499 | return ConfigTest.class.getResourceAsStream("/test-parse-with-yaml.yml"); 500 | } 501 | 502 | @Override 503 | public List getParams() { 504 | String[] params = new String[]{ 505 | "/protocol/mongo/replication/include={torodb: [postgres, derby]}", 506 | "/protocol/mongo/replication/exclude={mongodb: {mmapv1, wiredtiger}}" 507 | }; 508 | return Arrays.asList(params); 509 | } 510 | }; 511 | Config config = CliConfigUtils.readConfig(cliConfig); 512 | 513 | Assert.assertTrue("/generic not defined", config.getGeneric() != null); 514 | Assert.assertTrue("/generic/logPackages not defined", config.getGeneric().getLogPackages() 515 | != null); 516 | Assert.assertTrue("/generic/logPackages/com.torodb not defined", config.getGeneric() 517 | .getLogPackages().get("com.torodb") != null); 518 | Assert.assertEquals("/generic/logLevel has different value than that specified", LogLevel.NONE, 519 | config.getGeneric().getLogLevel()); 520 | Assert.assertEquals("/generic/logPackages has not 1 entry", 1, config.getGeneric() 521 | .getLogPackages().size()); 522 | Assert.assertEquals("/generic/logPackages/com.torodb has different value than that specified", 523 | LogLevel.DEBUG, config.getGeneric().getLogPackages().get("com.torodb")); 524 | Assert.assertTrue("/protocol not defined", config.getProtocol() != null); 525 | Assert.assertTrue("/protocol/mongo not defined", config.getProtocol().getMongo() != null); 526 | Assert.assertTrue("/protocol/mongo/net not defined", config.getProtocol().getMongo().getNet() 527 | != null); 528 | Assert.assertEquals("/protocol/mongo/net/port has different value than that specified", Integer 529 | .valueOf(27019), config.getProtocol().getMongo().getNet().getPort()); 530 | Assert.assertTrue("/protocol/mongo/replication not defined", config.getProtocol().getMongo() 531 | .getReplication() != null); 532 | Assert.assertEquals( 533 | "/protocol/mongo/replication/replSetName has different value than that specified", "rs1", 534 | config.getProtocol().getMongo().getReplication().getReplSetName().value()); 535 | Assert 536 | .assertEquals("/protocol/mongo/replication/role has different value than that specified", 537 | Role.HIDDEN_SLAVE, config.getProtocol().getMongo().getReplication().getRole().value()); 538 | Assert.assertEquals( 539 | "/protocol/mongo/replication/syncSource has different value than that specified", 540 | "localhost:27017", config.getProtocol().getMongo().getReplication().getSyncSource().value().get(0)); 541 | Assert.assertTrue( 542 | "/protocol/mongo/replication/shards not defined", 543 | config.getProtocol().getMongo().getReplication().getShards() != null); 544 | Assert.assertTrue( 545 | "/protocol/mongo/replication/shards not empty", 546 | config.getProtocol().getMongo().getReplication().getShards().isEmpty()); 547 | Assert.assertTrue("/protocol/mongo/replication/include not defined", config.getProtocol() 548 | .getMongo().getReplication().getInclude() != null); 549 | Assert.assertTrue("/protocol/mongo/replication/include/torodb not defined", config 550 | .getProtocol().getMongo().getReplication().getInclude().get("torodb") != null); 551 | Assert.assertEquals( 552 | "/protocol/mongo/replication/include/torodb has different value than that specified", 553 | ImmutableMap.of("postgres", ImmutableList.of(), "derby", ImmutableList.of()), 554 | config.getProtocol().getMongo().getReplication().getInclude().get("torodb")); 555 | Assert.assertTrue("/protocol/mongo/replication/exclude not defined", config.getProtocol() 556 | .getMongo().getReplication().getExclude() != null); 557 | Assert.assertTrue("/protocol/mongo/replication/exclude/mongodb not defined", config 558 | .getProtocol().getMongo().getReplication().getExclude().get("mongodb") != null); 559 | Assert.assertEquals( 560 | "/protocol/mongo/replication/exclude/mongodb has different value than that specified", 561 | ImmutableMap.of("mmapv1", ImmutableList.of(), "wiredtiger", ImmutableList.of()), 562 | config.getProtocol().getMongo().getReplication().getExclude().get("mongodb")); 563 | Assert.assertTrue("/backend not defined", config.getBackend() != null); 564 | Assert.assertEquals("/backend/postgres not defined", Postgres.class, config.getBackend() 565 | .getBackendImplementation().getClass()); 566 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres", config.getBackend() 567 | .is(Postgres.class)); 568 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres Like", config 569 | .getBackend().isLike(Postgres.class)); 570 | Assert.assertEquals("/backend/postgres/host has different value than that specified", 571 | "localhost", config.getBackend().as(Postgres.class).getHost()); 572 | Assert.assertEquals("/backend/postgres/port has different value than that specified", Integer 573 | .valueOf(5432), config.getBackend().as(Postgres.class).getPort()); 574 | Assert.assertEquals("/backend/postgres/user has different value than that specified", "root", 575 | config.getBackend().as(Postgres.class).getUser()); 576 | Assert.assertEquals( 577 | "/backend/postgres/password specified but should have not been read from parameters", null, 578 | config.getBackend().as(Postgres.class).getPassword()); 579 | } 580 | 581 | @Test 582 | public void testReplicationFilteringWithIndexes() throws Exception { 583 | CliConfig cliConfig = new CliConfig() { 584 | @Override 585 | public boolean hasConfFile() { 586 | return true; 587 | } 588 | 589 | @Override 590 | public InputStream getConfInputStream() { 591 | return ConfigTest.class.getResourceAsStream("/test-parse-with-yaml.yml"); 592 | } 593 | 594 | @Override 595 | public List getParams() { 596 | String[] params = new String[]{ 597 | "/protocol/mongo/replication/include={torodb: [{postgres: {name: awesome, unique: true}}, derby]}", 598 | "/protocol/mongo/replication/exclude={mongodb: [{mmapv1: {keys: {\"the.old.mmapv1\": 1}}}, wiredtiger]}" 599 | }; 600 | return Arrays.asList(params); 601 | } 602 | }; 603 | Config config = CliConfigUtils.readConfig(cliConfig); 604 | 605 | Assert.assertTrue("/generic not defined", config.getGeneric() != null); 606 | Assert.assertTrue("/generic/logPackages not defined", config.getGeneric().getLogPackages() 607 | != null); 608 | Assert.assertTrue("/generic/logPackages/com.torodb not defined", config.getGeneric() 609 | .getLogPackages().get("com.torodb") != null); 610 | Assert.assertEquals("/generic/logLevel has different value than that specified", LogLevel.NONE, 611 | config.getGeneric().getLogLevel()); 612 | Assert.assertEquals("/generic/logPackages has not 1 entry", 1, config.getGeneric() 613 | .getLogPackages().size()); 614 | Assert.assertEquals("/generic/logPackages/com.torodb has different value than that specified", 615 | LogLevel.DEBUG, config.getGeneric().getLogPackages().get("com.torodb")); 616 | Assert.assertTrue("/protocol not defined", config.getProtocol() != null); 617 | Assert.assertTrue("/protocol/mongo not defined", config.getProtocol().getMongo() != null); 618 | Assert.assertTrue("/protocol/mongo/net not defined", config.getProtocol().getMongo().getNet() 619 | != null); 620 | Assert.assertEquals("/protocol/mongo/net/port has different value than that specified", Integer 621 | .valueOf(27019), config.getProtocol().getMongo().getNet().getPort()); 622 | Assert.assertTrue("/protocol/mongo/replication not defined", config.getProtocol().getMongo() 623 | .getReplication() != null); 624 | Assert.assertEquals( 625 | "/protocol/mongo/replication/replSetName has different value than that specified", "rs1", 626 | config.getProtocol().getMongo().getReplication().getReplSetName().value()); 627 | Assert 628 | .assertEquals("/protocol/mongo/replication/role has different value than that specified", 629 | Role.HIDDEN_SLAVE, config.getProtocol().getMongo().getReplication().getRole().value()); 630 | Assert.assertEquals( 631 | "/protocol/mongo/replication/syncSource has different value than that specified", 632 | "localhost:27017", config.getProtocol().getMongo().getReplication().getSyncSource().value().get(0)); 633 | Assert.assertTrue( 634 | "/protocol/mongo/replication/shards not defined", 635 | config.getProtocol().getMongo().getReplication().getShards() != null); 636 | Assert.assertTrue( 637 | "/protocol/mongo/replication/shards not empty", 638 | config.getProtocol().getMongo().getReplication().getShards().isEmpty()); 639 | Assert.assertTrue("/protocol/mongo/replication/include not defined", config.getProtocol() 640 | .getMongo().getReplication().getInclude() != null); 641 | Assert.assertTrue("/protocol/mongo/replication/include/torodb not defined", config 642 | .getProtocol().getMongo().getReplication().getInclude().get("torodb") != null); 643 | Assert.assertEquals( 644 | "/protocol/mongo/replication/include/torodb has different value than that specified", 645 | ImmutableMap.of("postgres", ImmutableList.of(new IndexFilter("awesome", true, null)), 646 | "derby", ImmutableList.of()), 647 | config.getProtocol().getMongo().getReplication().getInclude().get("torodb")); 648 | Assert.assertTrue("/protocol/mongo/replication/exclude not defined", config.getProtocol() 649 | .getMongo().getReplication().getExclude() != null); 650 | Assert.assertTrue("/protocol/mongo/replication/exclude/mongodb not defined", config 651 | .getProtocol().getMongo().getReplication().getExclude().get("mongodb") != null); 652 | Assert.assertEquals( 653 | "/protocol/mongo/replication/exclude/mongodb has different value than that specified", 654 | ImmutableMap.of("mmapv1", ImmutableList.of(new IndexFilter(null, null, ImmutableMap 655 | .builder().put("the.old.mmapv1", "1").build())), "wiredtiger", 656 | ImmutableList.of()), 657 | config.getProtocol().getMongo().getReplication().getExclude().get("mongodb")); 658 | Assert.assertTrue("/backend not defined", config.getBackend() != null); 659 | Assert.assertEquals("/backend/postgres not defined", Postgres.class, config.getBackend() 660 | .getBackendImplementation().getClass()); 661 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres", config.getBackend() 662 | .is(Postgres.class)); 663 | Assert.assertTrue("/backend/postgres not identified as AbstractPostgres Like", config 664 | .getBackend().isLike(Postgres.class)); 665 | Assert.assertEquals("/backend/postgres/host has different value than that specified", 666 | "localhost", config.getBackend().as(Postgres.class).getHost()); 667 | Assert.assertEquals("/backend/postgres/port has different value than that specified", Integer 668 | .valueOf(5432), config.getBackend().as(Postgres.class).getPort()); 669 | Assert.assertEquals("/backend/postgres/user has different value than that specified", "root", 670 | config.getBackend().as(Postgres.class).getUser()); 671 | Assert.assertEquals( 672 | "/backend/postgres/password specified but should have not been read from parameters", null, 673 | config.getBackend().as(Postgres.class).getPassword()); 674 | } 675 | 676 | } 677 | -------------------------------------------------------------------------------- /main/src/test/resources/test-parse-with-empty-yaml.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /main/src/test/resources/test-parse-with-wrong-yaml.yml: -------------------------------------------------------------------------------- 1 | generics: 2 | logLevel: NONE 3 | logPackages: 4 | com.torodb: DEBUG 5 | protocol: 6 | mongo: 7 | net: 8 | port: 27019 9 | replication: 10 | replSetName: rs1 11 | role: HIDDEN_SLAVE 12 | syncSource: localhost:27017 13 | backend: 14 | postgres: 15 | host: localhost 16 | port: 5432 17 | user: root 18 | password: toor -------------------------------------------------------------------------------- /main/src/test/resources/test-parse-with-xml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | NONE 4 | 5 | DEBUG 6 | 7 | 8 | 9 | 10 | 11 | 27019 12 | 13 | 14 | rs1 15 | HIDDEN_SLAVE 16 | localhost:27017 17 | 18 | 19 | 20 | 21 | 22 | localhost 23 | 5432 24 | root 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /main/src/test/resources/test-parse-with-yaml-using-derby.yml: -------------------------------------------------------------------------------- 1 | backend: 2 | derby: 3 | host: localhost 4 | port: 5432 5 | user: root 6 | -------------------------------------------------------------------------------- /main/src/test/resources/test-parse-with-yaml-using-double-backend.yml: -------------------------------------------------------------------------------- 1 | backend: 2 | postgres: 3 | host: localhost 4 | port: 5432 5 | user: root 6 | derby: 7 | host: localhost 8 | port: 5432 9 | user: root 10 | -------------------------------------------------------------------------------- /main/src/test/resources/test-parse-with-yaml-using-empty-protocol.yml: -------------------------------------------------------------------------------- 1 | protocol: 2 | backend: 3 | postgres: 4 | host: localhost 5 | port: 5432 6 | user: root 7 | -------------------------------------------------------------------------------- /main/src/test/resources/test-parse-with-yaml-using-password.yml: -------------------------------------------------------------------------------- 1 | backend: 2 | derby: 3 | host: localhost 4 | port: 5432 5 | user: root 6 | password: toor 7 | -------------------------------------------------------------------------------- /main/src/test/resources/test-parse-with-yaml.yml: -------------------------------------------------------------------------------- 1 | generic: 2 | logLevel: NONE 3 | logPackages: 4 | com.torodb: DEBUG 5 | protocol: 6 | mongo: 7 | net: 8 | port: 27019 9 | replication: 10 | replSetName: rs1 11 | role: HIDDEN_SLAVE 12 | syncSource: localhost:27017 13 | backend: 14 | postgres: 15 | host: localhost 16 | port: 5432 17 | user: root 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.torodb 6 | parent-pom 7 | 1.0.1-SNAPSHOT 8 | 9 | 10 | com.torodb.server 11 | server-pom 12 | pom 13 | 14 | 0.50.2-SNAPSHOT 15 | 16 | ToroDB: Server 17 | ToroDB standalone project. 18 | 19 | 20 | service 21 | main 22 | reporting 23 | 24 | 25 | 26 | 0.50.3-SNAPSHOT 27 | 0.1.0-SNAPSHOT 28 | 29 | agpl 30 | ToroDB Server 31 | 2014 32 | 33 | 34 | 35 | 36 | 37 | com.torodb.engine 38 | packaging-utils 39 | ${torodb.engine.version} 40 | 41 | 42 | com.torodb.engine.backend 43 | backend-postgresql 44 | ${torodb.engine.version} 45 | 46 | 47 | com.torodb.engine.backend 48 | backend-derby 49 | ${torodb.engine.version} 50 | 51 | 52 | com.torodb.testing 53 | postgres-junit-5 54 | ${torodb.testing.version} 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | com.mycila 63 | license-maven-plugin 64 | 65 | 66 | 67 | 68 | 69 | 70 | OSSRH 71 | https://oss.sonatype.org/content/groups/public 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /reporting/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.torodb.server 6 | server-pom 7 | 0.50.2-SNAPSHOT 8 | 9 | reporting 10 | ToroDB: Server reporting 11 | pom 12 | 13 | 14 | true 15 | 16 | 17 | 18 | 19 | 20 | com.torodb.server 21 | server-main 22 | ${project.version} 23 | 24 | 25 | com.torodb.server 26 | server-service 27 | ${project.version} 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.jacoco 37 | jacoco-maven-plugin 38 | 39 | 40 | report-aggregate 41 | verify 42 | false 43 | 44 | report-aggregate 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ossrh-release 58 | OSSRH Release repository 59 | https://please.dont/deploy/me 60 | 61 | 62 | ossrh-snapshot 63 | OSSRH Snapshot repository 64 | https://please.dont/deploy/me 65 | 66 | 67 | -------------------------------------------------------------------------------- /service/.docker/run-postgres.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./setup-postgres.sh 4 | 5 | ./toro_dist/bin/torodb -c ./torodb-postgres.yml -l 6 | ./toro_dist/bin/torodb -c ./torodb-postgres.yml 7 | -------------------------------------------------------------------------------- /service/.docker/run-replication-postgres.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./setup-postgres.sh 4 | ./setup-replication.sh 5 | 6 | ./toro_dist/bin/torodb -c ./torodb-replication-postgres.yml -l 7 | ./toro_dist/bin/torodb -c ./torodb-replication-postgres.yml 8 | -------------------------------------------------------------------------------- /service/.docker/setup-postgres.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo -n "Waiting PostgreSQL..." 6 | POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-}" 7 | echo "postgres:5432:*:postgres:$POSTGRES_PASSWORD" > ~/.pgpass 8 | chmod 400 ~/.pgpass 9 | max_seconds=15 10 | while ! /usr/bin/psql -h postgres -U postgres -c "SELECT 1" > /dev/null 2>&1 11 | do 12 | sleep 1 13 | echo -n . 14 | max_seconds=$((max_seconds-1)) 15 | if [ "$max_seconds" -le 0 ] 16 | then 17 | echo timeout 18 | exit 1 19 | fi 20 | done 21 | echo ok 22 | 23 | echo -n "Setting up PostgreSQL..." 24 | TORODB_PASSWORD="${TORODB_PASSWORD:-trustme}" 25 | echo "postgres:5432:torod:torodb:$TORODB_PASSWORD" > ~/.toropass 26 | chown 400 ~/.toropass 27 | /usr/bin/psql -h postgres -U postgres -c "CREATE USER torodb PASSWORD '$TORODB_PASSWORD'" 28 | /usr/bin/psql -h postgres -U postgres -c "CREATE DATABASE torod OWNER torodb" 29 | echo ok 30 | 31 | rm ~/.pgpass 32 | POSTGRES_PASSWORD= 33 | TORODB_PASSWORD= 34 | -------------------------------------------------------------------------------- /service/.docker/setup-replication.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo -n "Waiting MongoDB..." 6 | max_seconds=15 7 | while ! /opt/mongodb/bin/mongo mongo:27017/local --eval true > /dev/null 2>&1 8 | do 9 | sleep 1 10 | echo -n . 11 | max_seconds=$((max_seconds-1)) 12 | if [ "$max_seconds" -le 0 ] 13 | then 14 | echo timeout 15 | exit 1 16 | fi 17 | done 18 | echo ok 19 | 20 | echo -n "Setting up MongoDB..." 21 | /opt/mongodb/bin/mongo mongo:27017/local --eval 'rs.initiate({_id:"rs1",members:[{_id:0,host:"localhost:27017"}]})' > /dev/null 2>&1 22 | max_seconds=15 23 | while ! /opt/mongodb/bin/mongo mongo:27017/local --eval 'assert(db.isMaster().ismaster)' > /dev/null 2>&1 24 | do 25 | sleep 1 26 | echo -n . 27 | max_seconds=$((max_seconds-1)) 28 | if [ "$max_seconds" -le 0 ] 29 | then 30 | echo timeout 31 | exit 1 32 | fi 33 | done 34 | echo ok 35 | -------------------------------------------------------------------------------- /service/.docker/torodb-postgres.yml: -------------------------------------------------------------------------------- 1 | --- 2 | generic: 3 | logLevel: INFO 4 | connectionPoolSize: 30 5 | reservedReadPoolSize: 10 6 | connectionPoolTimeout: 10000 7 | protocol: 8 | mongo: 9 | net: 10 | bindIp: localhost 11 | port: 27018 12 | cursorTimeout: 600000 13 | backend: 14 | postgres: 15 | host: postgres 16 | port: 5432 17 | database: torod 18 | user: torodb 19 | toropassFile: /root/.toropass 20 | applicationName: toro 21 | -------------------------------------------------------------------------------- /service/.docker/torodb-replication-postgres.yml: -------------------------------------------------------------------------------- 1 | --- 2 | generic: 3 | logLevel: INFO 4 | connectionPoolSize: 30 5 | reservedReadPoolSize: 10 6 | connectionPoolTimeout: 10000 7 | protocol: 8 | mongo: 9 | net: 10 | bindIp: localhost 11 | port: 27018 12 | cursorTimeout: 600000 13 | replication: 14 | - replSetName: rs1 15 | syncSource: mongo:27017 16 | backend: 17 | postgres: 18 | host: postgres 19 | port: 5432 20 | database: torod 21 | user: torodb 22 | toropassFile: /root/.toropass 23 | applicationName: toro 24 | -------------------------------------------------------------------------------- /service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.torodb.server 6 | server-pom 7 | 0.50.2-SNAPSHOT 8 | 9 | 10 | server-service 11 | 12 | ToroDB: Server service 13 | ToroDB server service project. Contains DI dependencies and services configuration. 14 | 15 | 16 | 17 | com.torodb.engine.mongodb 18 | wp 19 | ${torodb.engine.version} 20 | 21 | 22 | com.torodb.engine.backend 23 | backend-postgresql 24 | 25 | 26 | com.torodb.engine.backend 27 | backend-derby 28 | 29 | 30 | 31 | org.glassfish 32 | javax.json 33 | 34 | 35 | com.google.inject 36 | guice 37 | 38 | 39 | javax.validation 40 | validation-api 41 | 42 | 43 | org.hibernate 44 | hibernate-validator 45 | 46 | 47 | org.glassfish 48 | javax.el 49 | 50 | 51 | com.google.code.findbugs 52 | jsr305 53 | 54 | 55 | com.google.code.findbugs 56 | annotations 57 | 58 | 59 | commons-configuration 60 | commons-configuration 61 | 62 | 63 | commons-logging 64 | commons-logging 65 | 66 | 67 | 68 | 69 | javax.inject 70 | javax.inject 71 | 72 | 73 | org.apache.logging.log4j 74 | log4j-slf4j-impl 75 | 76 | 77 | 78 | junit 79 | junit 80 | test 81 | 82 | 83 | org.apache.logging.log4j 84 | log4j-core 85 | test 86 | 87 | 88 | com.torodb.engine 89 | packaging-utils 90 | test 91 | 92 | 93 | org.junit.jupiter 94 | junit-jupiter-api 95 | test 96 | 97 | 98 | org.junit.platform 99 | junit-platform-runner 100 | test 101 | 102 | 103 | org.junit.jupiter 104 | junit-jupiter-engine 105 | test 106 | 107 | 108 | com.torodb.testing 109 | postgres-junit-5 110 | test 111 | 112 | 113 | commons-logging 114 | commons-logging 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | org.apache.maven.plugins 124 | maven-jar-plugin 125 | 2.6 126 | 127 | 128 | 129 | test-jar 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /service/src/main/java/com/torodb/standalone/ServerConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone; 19 | 20 | import com.google.common.net.HostAndPort; 21 | import com.google.inject.Injector; 22 | import com.torodb.core.backend.BackendBundle; 23 | import com.torodb.core.bundle.BundleConfig; 24 | import com.torodb.core.logging.LoggerFactory; 25 | import com.torodb.mongodb.core.MongoDbCoreBundle; 26 | import com.torodb.mongodb.wp.MongoDbWpBundle; 27 | import org.apache.logging.log4j.Logger; 28 | 29 | import java.util.function.BiFunction; 30 | import java.util.function.Function; 31 | 32 | public class ServerConfig { 33 | 34 | private final Injector essentialInjector; 35 | private final Function backendBundleGenerator; 36 | private final HostAndPort selfHostAndPort; 37 | @SuppressWarnings("checkstyle:LineLength") 38 | private final BiFunction mongoDbWpBundleGenerator; 39 | private final Logger logger; 40 | 41 | public ServerConfig(Injector essentialInjector, 42 | Function backendBundleGenerator, HostAndPort selfHostAndPort, 43 | BiFunction mongoDbWpBundleGenerator, 44 | LoggerFactory loggerFactory) { 45 | this.essentialInjector = essentialInjector; 46 | this.backendBundleGenerator = backendBundleGenerator; 47 | this.selfHostAndPort = selfHostAndPort; 48 | this.mongoDbWpBundleGenerator = mongoDbWpBundleGenerator; 49 | this.logger = loggerFactory.apply(ServerService.class); 50 | } 51 | 52 | public Injector getEssentialInjector() { 53 | return essentialInjector; 54 | } 55 | 56 | public Logger getLifecycleLogger() { 57 | return logger; 58 | } 59 | 60 | public Function getBackendBundleGenerator() { 61 | return backendBundleGenerator; 62 | } 63 | 64 | public HostAndPort getSelfHostAndPort() { 65 | return selfHostAndPort; 66 | } 67 | 68 | @SuppressWarnings("checkstyle:LineLength") 69 | public BiFunction getMongoDbWpBundleGenerator() { 70 | return mongoDbWpBundleGenerator; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /service/src/main/java/com/torodb/standalone/ServerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone; 19 | 20 | import com.google.common.util.concurrent.AbstractIdleService; 21 | import com.google.common.util.concurrent.Service; 22 | import com.google.inject.Injector; 23 | import com.torodb.core.Shutdowner; 24 | import com.torodb.core.backend.BackendBundle; 25 | import com.torodb.core.bundle.Bundle; 26 | import com.torodb.core.bundle.BundleConfig; 27 | import com.torodb.core.bundle.BundleConfigImpl; 28 | import com.torodb.core.logging.ComponentLoggerFactory; 29 | import com.torodb.core.logging.LoggerFactory; 30 | import com.torodb.core.supervision.Supervisor; 31 | import com.torodb.core.supervision.SupervisorDecision; 32 | import com.torodb.mongodb.core.MongoDbCoreBundle; 33 | import com.torodb.mongodb.core.MongoDbCoreConfig; 34 | import com.torodb.mongodb.core.MongodServerConfig; 35 | import com.torodb.mongodb.wp.MongoDbWpBundle; 36 | import com.torodb.torod.TorodBundle; 37 | import com.torodb.torod.impl.sql.SqlTorodBundle; 38 | import com.torodb.torod.impl.sql.SqlTorodConfig; 39 | 40 | import java.util.Optional; 41 | import java.util.concurrent.Executor; 42 | import java.util.concurrent.ThreadFactory; 43 | 44 | /** 45 | * This service is used to start and stop ToroDB Server. 46 | * 47 | *

It takes a {@link ServerConfig} and uses it to create and start the required 48 | * {@link Bundle bundles}. 49 | */ 50 | public class ServerService extends AbstractIdleService implements Supervisor { 51 | 52 | private final ThreadFactory threadFactory; 53 | private final Injector essentialInjector; 54 | private final BundleConfig generalBundleConfig; 55 | private final ServerConfig config; 56 | private final Shutdowner shutdowner; 57 | 58 | public ServerService(ServerConfig config) { 59 | this.config = config; 60 | this.essentialInjector = config.getEssentialInjector(); 61 | this.threadFactory = essentialInjector.getInstance(ThreadFactory.class); 62 | this.generalBundleConfig = new BundleConfigImpl(essentialInjector, this); 63 | this.shutdowner = essentialInjector.getInstance(Shutdowner.class); 64 | } 65 | 66 | @Override 67 | protected Executor executor() { 68 | return (Runnable command) -> { 69 | Thread thread = threadFactory.newThread(command); 70 | thread.start(); 71 | }; 72 | } 73 | 74 | @Override 75 | public SupervisorDecision onError(Object supervised, Throwable error) { 76 | this.stopAsync(); 77 | return SupervisorDecision.STOP; 78 | } 79 | 80 | @Override 81 | protected void startUp() throws Exception { 82 | config.getLifecycleLogger().info("Starting up ToroDB Server"); 83 | 84 | shutdowner.startAsync(); 85 | shutdowner.awaitRunning(); 86 | 87 | BackendBundle backendBundle = config.getBackendBundleGenerator().apply(generalBundleConfig); 88 | startBundle(backendBundle); 89 | 90 | TorodBundle torodBundle = createTorodBundle(backendBundle); 91 | startBundle(torodBundle); 92 | 93 | MongoDbCoreBundle mongoDbCoreBundle = createMongoDbCoreBundle(torodBundle); 94 | startBundle(mongoDbCoreBundle); 95 | 96 | MongoDbWpBundle mongodbWpBundle = config.getMongoDbWpBundleGenerator() 97 | .apply(generalBundleConfig, mongoDbCoreBundle); 98 | startBundle(mongodbWpBundle); 99 | 100 | config.getLifecycleLogger().info("ToroDB Server is now running"); 101 | } 102 | 103 | @Override 104 | protected void shutDown() throws Exception { 105 | config.getLifecycleLogger().info("Shutting down ToroDB Standalone"); 106 | if (shutdowner != null) { 107 | shutdowner.stopAsync(); 108 | shutdowner.awaitTerminated(); 109 | } 110 | config.getLifecycleLogger().info("ToroDB Stampede has been shutted down"); 111 | } 112 | 113 | private MongoDbCoreBundle createMongoDbCoreBundle(TorodBundle torodBundle) { 114 | MongodServerConfig mongodServerConfig = new MongodServerConfig(config.getSelfHostAndPort()); 115 | LoggerFactory lf = new ComponentLoggerFactory("MONGOD"); 116 | return new MongoDbCoreBundle( 117 | MongoDbCoreConfig.simpleConfig( 118 | torodBundle, 119 | lf, 120 | mongodServerConfig, 121 | Optional.empty(), 122 | generalBundleConfig 123 | ) 124 | ); 125 | } 126 | 127 | private TorodBundle createTorodBundle(BackendBundle backendBundle) { 128 | return new SqlTorodBundle(new SqlTorodConfig( 129 | backendBundle, 130 | essentialInjector, 131 | this 132 | )); 133 | } 134 | 135 | private void startBundle(Service service) { 136 | service.startAsync(); 137 | service.awaitRunning(); 138 | 139 | shutdowner.addStopShutdownListener(service); 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /service/src/test/java/com/torodb/standalone/ServerServiceIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone; 19 | 20 | import static com.torodb.standalone.utils.RequireClientSupplier.BackendType.POSTGRES; 21 | 22 | import com.google.common.collect.Iterables; 23 | import com.mongodb.MongoClient; 24 | import com.mongodb.client.MongoCollection; 25 | import com.torodb.standalone.utils.ClientSupplier; 26 | import org.bson.Document; 27 | import org.junit.jupiter.api.Assertions; 28 | import org.junit.jupiter.api.Disabled; 29 | import org.junit.jupiter.api.Test; 30 | import org.junit.platform.runner.JUnitPlatform; 31 | import org.junit.runner.RunWith; 32 | import com.torodb.standalone.utils.RequireClientSupplier; 33 | import org.bson.BsonDocument; 34 | import org.bson.BsonInt32; 35 | 36 | 37 | /** 38 | * 39 | */ 40 | @RunWith(JUnitPlatform.class) 41 | @RequireClientSupplier(backend = POSTGRES, newForEachCase = false) 42 | public class ServerServiceIT { 43 | 44 | @Test 45 | public void someInserts(ClientSupplier clientSupplier) { 46 | MongoClient client = clientSupplier.get(); 47 | MongoCollection collection = client.getDatabase("dbTest") 48 | .getCollection("colTest"); 49 | for (int i = 0; i < 10; i++) { 50 | collection.insertOne(new Document("i", i)); 51 | } 52 | 53 | Assertions.assertEquals(10, collection.count()); 54 | } 55 | 56 | 57 | @Test 58 | @Disabled 59 | public void createCollection(ClientSupplier clientSupplier) { 60 | MongoClient client = clientSupplier.get(); 61 | 62 | client.getDatabase("aDb") 63 | .createCollection("aCol"); 64 | 65 | Assertions.assertTrue( 66 | Iterables.contains( 67 | client.getDatabase("aDb").listCollectionNames(), 68 | "aCol" 69 | ), 70 | "The created collection has not been found on the server" 71 | ); 72 | } 73 | 74 | @Test 75 | @Disabled 76 | public void ping(ClientSupplier clientSupplier) { 77 | MongoClient client = clientSupplier.get(); 78 | 79 | client.getDatabase("admin") 80 | .runCommand(new BsonDocument("ping", new BsonInt32(1))); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /service/src/test/java/com/torodb/standalone/ServerServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.torodb.standalone; 20 | 21 | import static com.torodb.standalone.utils.RequireClientSupplier.BackendType.DERBY; 22 | 23 | import com.mongodb.MongoClient; 24 | import com.torodb.standalone.utils.ClientSupplier; 25 | import com.torodb.standalone.utils.RequireClientSupplier; 26 | import org.bson.BsonDocument; 27 | import org.bson.BsonInt32; 28 | import org.junit.jupiter.api.Disabled; 29 | import org.junit.jupiter.api.Test; 30 | import org.junit.platform.runner.JUnitPlatform; 31 | import org.junit.runner.RunWith; 32 | 33 | 34 | @RunWith(JUnitPlatform.class) 35 | @RequireClientSupplier(backend = DERBY) 36 | public class ServerServiceTest { 37 | 38 | @Test 39 | public void isRunning(ClientSupplier clientSupplier) { 40 | 41 | } 42 | 43 | @Test 44 | @Disabled 45 | public void ping(ClientSupplier clientSupplier) { 46 | MongoClient client = clientSupplier.get(); 47 | 48 | client.getDatabase("admin") 49 | .runCommand(new BsonDocument("ping", new BsonInt32(1))); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /service/src/test/java/com/torodb/standalone/utils/ClientSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.utils; 19 | 20 | import com.mongodb.MongoClient; 21 | 22 | import java.util.function.Supplier; 23 | 24 | /** 25 | * A MongoClient {@link Supplier} that can be closed. 26 | */ 27 | public interface ClientSupplier extends AutoCloseable, Supplier{ 28 | 29 | /** 30 | * Returns a {@link MongoClient} that can be used to talk with a ToroDB Server instance. 31 | */ 32 | @Override 33 | public MongoClient get(); 34 | 35 | @Override 36 | public void close(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /service/src/test/java/com/torodb/standalone/utils/ClientSupplierExtension.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.utils; 19 | 20 | import static com.torodb.standalone.utils.RequireClientSupplier.BackendType.DERBY; 21 | import static com.torodb.standalone.utils.RequireClientSupplier.BackendType.POSTGRES; 22 | 23 | import com.google.common.net.HostAndPort; 24 | import com.torodb.backend.BackendConfigImplBuilder; 25 | import com.torodb.backend.derby.DerbyDbBackendBundle; 26 | import com.torodb.backend.derby.driver.DerbyDbBackendConfigBuilder; 27 | import com.torodb.backend.postgresql.PostgreSqlBackendBundle; 28 | import com.torodb.core.backend.BackendBundle; 29 | import com.torodb.core.bundle.BundleConfig; 30 | import com.torodb.testing.core.junit5.AnnotationFinder; 31 | import com.torodb.testing.core.junit5.CloseableParameterResolver; 32 | import com.torodb.testing.docker.postgres.EnumVersion; 33 | import com.torodb.testing.docker.postgres.PostgresConfig; 34 | import com.torodb.testing.docker.postgres.PostgresService; 35 | import com.torodb.testing.docker.postgres.PostgresVersion; 36 | import com.torodb.testing.docker.sql.SqlService; 37 | import org.junit.jupiter.api.extension.ExtensionContext; 38 | 39 | import java.util.function.Function; 40 | 41 | 42 | /** 43 | * The JUnit 5 extension that resolves parameters of type {@link ClientSupplier}. 44 | */ 45 | class ClientSupplierExtension extends CloseableParameterResolver { 46 | 47 | private static final PostgresVersion POSTGRES_VERSION = EnumVersion.LATEST; 48 | 49 | @Override 50 | protected Class getParameterClass() { 51 | return ClientSupplier.class; 52 | } 53 | 54 | @Override 55 | protected ClientSupplier createParamValue(ExtensionContext context) { 56 | RequireClientSupplier annotation = findInjectorAnnotation(context); 57 | 58 | SqlService sqlService = createSqlService(annotation); 59 | sqlService.startAsync(); 60 | sqlService.awaitRunning(); 61 | 62 | boolean correct = false; 63 | try { 64 | ServerTestInstance testInstance = new ServerTestInstance( 65 | createBackendBundleGenerator(annotation, sqlService) 66 | ); 67 | testInstance.startAsync(); 68 | testInstance.awaitRunning(); 69 | 70 | ClientSupplier result = new DefaultClientSupplier(sqlService, testInstance); 71 | 72 | correct = true; 73 | 74 | return result; 75 | } finally { 76 | if (!correct) { 77 | sqlService.stopAsync(); 78 | sqlService.awaitTerminated(); 79 | } 80 | } 81 | } 82 | 83 | @Override 84 | protected boolean cleanAfterTest(ExtensionContext context) { 85 | return findInjectorAnnotation(context).newForEachCase(); 86 | } 87 | 88 | private RequireClientSupplier findInjectorAnnotation(ExtensionContext context) { 89 | return AnnotationFinder.resolve(context, RequireClientSupplier.class); 90 | } 91 | 92 | private PostgresService createSqlService(RequireClientSupplier annotation) { 93 | return PostgresService.defaultService(EnumVersion.LATEST); 94 | } 95 | 96 | private static Function createBackendBundleGenerator( 97 | RequireClientSupplier annotation, SqlService sqlService) { 98 | switch (annotation.backend()) { 99 | case DERBY: { 100 | return (BundleConfig bc) -> createDerbyBackendBundle(bc, sqlService); 101 | } 102 | case POSTGRES: { 103 | return (BundleConfig bc) -> createPostgresBackendBundle(bc, sqlService); 104 | } 105 | default: { 106 | throw new AssertionError("Unexpected backend type " + annotation.backend()); 107 | } 108 | } 109 | } 110 | 111 | private static BackendBundle createDerbyBackendBundle(BundleConfig bundleConfig, 112 | SqlService sqlService) { 113 | HostAndPort address = sqlService.getAddress(); 114 | return new DerbyDbBackendBundle(new DerbyDbBackendConfigBuilder(bundleConfig) 115 | .setDbHost(address.getHost()) 116 | .setDbPort(address.getPort()) 117 | .build() 118 | ); 119 | } 120 | 121 | private static BackendBundle createPostgresBackendBundle(BundleConfig bundleConfig, 122 | SqlService sqlService) { 123 | 124 | HostAndPort address = sqlService.getAddress(); 125 | 126 | PostgresConfig sqlConfig = PostgresConfig.getDefaultConfig(POSTGRES_VERSION); 127 | 128 | return new PostgreSqlBackendBundle(new BackendConfigImplBuilder(bundleConfig) 129 | .setDbHost(address.getHost()) 130 | .setDbPort(address.getPort()) 131 | .setUsername(sqlConfig.getUsername()) 132 | .setPassword(sqlConfig.getPassword()) 133 | .setDbName(sqlConfig.getDb()) 134 | .build() 135 | ); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /service/src/test/java/com/torodb/standalone/utils/DefaultClientSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.utils; 19 | 20 | 21 | import com.google.common.base.Preconditions; 22 | import com.google.common.net.HostAndPort; 23 | import com.mongodb.MongoClient; 24 | import com.torodb.testing.docker.sql.SqlService; 25 | 26 | class DefaultClientSupplier implements ClientSupplier { 27 | 28 | private final SqlService sqlService; 29 | private final ServerTestInstance serverInstance; 30 | private final MongoClient client; 31 | private boolean closed = false; 32 | 33 | DefaultClientSupplier(SqlService sqlService, ServerTestInstance serverInstance) { 34 | this.sqlService = sqlService; 35 | this.serverInstance = serverInstance; 36 | 37 | assert sqlService.isRunning() : "The sql server is not running"; 38 | assert serverInstance.isRunning() : "The ToroDB Server is not running"; 39 | 40 | HostAndPort serverAddress = serverInstance.getAddress(); 41 | this.client = new MongoClient(serverAddress.getHost(), serverAddress.getPort()); 42 | } 43 | 44 | @Override 45 | public void close() { 46 | if (!closed) { 47 | closed = true; 48 | client.close(); 49 | serverInstance.stopAsync(); 50 | serverInstance.awaitTerminated(); 51 | 52 | sqlService.stopAsync(); 53 | sqlService.awaitTerminated(); 54 | } 55 | } 56 | 57 | @Override 58 | public MongoClient get() { 59 | Preconditions.checkState(!closed, "The client supplier has been closed"); 60 | assert client != null; 61 | return client; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /service/src/test/java/com/torodb/standalone/utils/RequireClientSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.torodb.standalone.utils; 20 | 21 | import static com.torodb.standalone.utils.RequireClientSupplier.BackendType.POSTGRES; 22 | 23 | import org.junit.jupiter.api.BeforeEach; 24 | import org.junit.jupiter.api.extension.ExtendWith; 25 | 26 | import java.lang.annotation.ElementType; 27 | import java.lang.annotation.Retention; 28 | import java.lang.annotation.RetentionPolicy; 29 | import java.lang.annotation.Target; 30 | 31 | /** 32 | * This annotation the annotated JUnit 5 test to be able to resolve {@link ClientSupplier} 33 | * parameters. 34 | */ 35 | @Target({ElementType.TYPE}) 36 | @Retention(RetentionPolicy.RUNTIME) 37 | @ExtendWith(ClientSupplierExtension.class) 38 | public @interface RequireClientSupplier { 39 | 40 | BackendType backend() default POSTGRES; 41 | 42 | /** 43 | * If each case requires its own {@link ClientSupplier} instace. 44 | * 45 | * If this is false, all cases will share the same instance and therefore the supplied client will 46 | * see changes produced by previous tests. A mehod annotated with {@link BeforeEach} in 47 | * the test class can be used to clean the state of the database. 48 | * 49 | * @return if each test requires its own fresh client. 50 | */ 51 | boolean newForEachCase() default true; 52 | 53 | public static enum BackendType { 54 | POSTGRES, 55 | DERBY 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /service/src/test/java/com/torodb/standalone/utils/ServerTestInstance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ToroDB Server 3 | * Copyright © 2014 8Kdata Technology (www.8kdata.com) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.torodb.standalone.utils; 19 | 20 | import com.google.common.base.Preconditions; 21 | import com.google.common.net.HostAndPort; 22 | import com.google.common.util.concurrent.AbstractIdleService; 23 | import com.google.common.util.concurrent.Service; 24 | import com.google.inject.Guice; 25 | import com.google.inject.Injector; 26 | import com.torodb.core.backend.BackendBundle; 27 | import com.torodb.core.bundle.BundleConfig; 28 | import com.torodb.core.guice.EssentialModule; 29 | import com.torodb.core.logging.ComponentLoggerFactory; 30 | import com.torodb.core.logging.DefaultLoggerFactory; 31 | import com.torodb.mongodb.core.MongoDbCoreBundle; 32 | import com.torodb.mongodb.wp.MongoDbWpBundle; 33 | import com.torodb.mongodb.wp.MongoDbWpConfig; 34 | import com.torodb.standalone.ServerConfig; 35 | import com.torodb.standalone.ServerService; 36 | import com.torodb.testing.core.CloseableService; 37 | 38 | import java.io.IOException; 39 | import java.net.ServerSocket; 40 | import java.time.Clock; 41 | import java.util.Random; 42 | import java.util.function.Function; 43 | 44 | 45 | /** 46 | * 47 | */ 48 | public class ServerTestInstance extends AbstractIdleService implements CloseableService { 49 | 50 | private final Function backendBundleGenerator; 51 | private Service serverService; 52 | private HostAndPort address; 53 | 54 | public ServerTestInstance(Function backendBundleGenerator) { 55 | this.backendBundleGenerator = backendBundleGenerator; 56 | } 57 | 58 | @Override 59 | protected void startUp() throws Exception { 60 | int port = getAvailablePort(); 61 | this.address = HostAndPort.fromParts("localhost", port); 62 | ServerConfig config = createServerConfig(port, backendBundleGenerator); 63 | 64 | serverService = new ServerService(config); 65 | serverService.startAsync(); 66 | serverService.awaitRunning(); 67 | } 68 | 69 | @Override 70 | protected void shutDown() throws Exception { 71 | serverService.stopAsync(); 72 | serverService.awaitTerminated(); 73 | } 74 | 75 | public HostAndPort getAddress() { 76 | Preconditions.checkState(isRunning(), "The service is not running"); 77 | return address; 78 | } 79 | 80 | private int getAvailablePort() { 81 | try (ServerSocket socket = new ServerSocket(0)) { 82 | return socket.getLocalPort(); 83 | } catch (IOException ex) { 84 | int ephemeralMax = 61000; 85 | int ephemeralMin = 32768; 86 | int range = ephemeralMax - ephemeralMin; 87 | 88 | return new Random(System.identityHashCode(this)).nextInt(range) + ephemeralMin; 89 | } 90 | } 91 | 92 | private static ServerConfig createServerConfig(int port, 93 | Function backendBundleGenerator) { 94 | 95 | HostAndPort selfAddress = HostAndPort.fromParts("localhost", port); 96 | 97 | return new ServerConfig( 98 | createEssentialInjector(), 99 | backendBundleGenerator, 100 | selfAddress, 101 | (bundleConf, mongoDbCoreBundle) -> createConfigBuilder(bundleConf, mongoDbCoreBundle, port), 102 | new ComponentLoggerFactory("LIFECYCLE") 103 | ); 104 | } 105 | 106 | private static Injector createEssentialInjector() { 107 | return Guice.createInjector(new EssentialModule( 108 | DefaultLoggerFactory.getInstance(), 109 | () -> true, 110 | Clock.systemUTC()) 111 | ); 112 | } 113 | 114 | private static MongoDbWpBundle createConfigBuilder(BundleConfig bundleConfig, 115 | MongoDbCoreBundle mongoDbCoreBundle, int selfPort) { 116 | return new MongoDbWpBundle( 117 | new MongoDbWpConfig(mongoDbCoreBundle, selfPort, bundleConfig) 118 | ); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /service/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | --------------------------------------------------------------------------------