mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:arangodb/arangodb into devel
This commit is contained in:
commit
69d9cce680
|
@ -2,195 +2,201 @@
|
|||
|
||||
## C/C++ Libraries
|
||||
|
||||
### Google V8
|
||||
### Boost 1.58.0
|
||||
|
||||
* https://code.google.com/p/v8/
|
||||
* [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause)
|
||||
* Project Home: http://www.boost.org/
|
||||
* License: [boost software license](http://www.boost.org/LICENSE_1_0.txt), [free as-is license](https://raw.githubusercontent.com/arangodb/arangodb/devel/3rdParty/boost/1.58.0/boost/test/utils/runtime/cla/detail/argument_value_usage.hpp)
|
||||
|
||||
### icu
|
||||
### Google V8 4.3.61
|
||||
|
||||
* http://site.icu-project.org/
|
||||
* [ICU License](http://source.icu-project.org/repos/icu/icu/trunk/license.html)
|
||||
* Project Home: https://code.google.com/p/v8/
|
||||
* License: [v8-overview](https://raw.githubusercontent.com/v8/v8/4.3.61/LICENSE), [V8](https://raw.githubusercontent.com/v8/v8/4.3.61/LICENSE.v8), [strongtalk](https://raw.githubusercontent.com/v8/v8/4.3.61/LICENSE.strongtalk), [valgrind](https://raw.githubusercontent.com/v8/v8/4.3.61/LICENSE.valgrind), [vtune](https://raw.githubusercontent.com/v8/v8/4.3.61/src/third_party/vtune/v8-vtune.h), [gmock](https://raw.githubusercontent.com/arangodb/arangodb/devel/3rdParty/V8-4.3.61/testing/gmock/LICENSE), [gtest](https://raw.githubusercontent.com/arangodb/arangodb/devel/3rdParty/V8-4.3.61/testing/gtest/LICENSE), [fdlibm](https://raw.githubusercontent.com/v8/v8/4.3.61/src/third_party/fdlibm/LICENSE), [PCRE](https://raw.githubusercontent.com/v8/v8/master/test/mjsunit/third_party/regexp-pcre/LICENSE), [object-keys](https://raw.githubusercontent.com/v8/v8/master/test/mjsunit/third_party/object-keys/LICENSE)
|
||||
|
||||
### libev
|
||||
### ICU 54.1
|
||||
|
||||
* http://software.schmorp.de/pkg/libev.html
|
||||
* [free as-is license](http://cvs.schmorp.de/libev/LICENSE?revision=1.11&view=markup)
|
||||
|
||||
### zlib
|
||||
|
||||
* [free as-is license](https://github.com/arangodb/arangodb/blob/devel/3rdParty/zlib-1.2.7/README#L85)
|
||||
|
||||
### Valgrind
|
||||
|
||||
* valgrind.h header file only
|
||||
* [BSD-style license](https://github.com/arangodb/arangodb/blob/devel/3rdParty/valgrind/valgrind.h)
|
||||
|
||||
### boost
|
||||
|
||||
* http://www.boost.org/
|
||||
* [boost software license](http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
### linenoise
|
||||
|
||||
* https://github.com/antirez/linenoise
|
||||
* [free as-is license](https://github.com/antirez/linenoise/blob/master/LICENSE)
|
||||
* Project Home: http://site.icu-project.org/
|
||||
* License: [ICU License](http://source.icu-project.org/repos/icu/icu/trunk/license.html)
|
||||
|
||||
### fpconv_dtoa
|
||||
|
||||
* https://github.com/night-shift/fpconv/
|
||||
* [MIT License](https://raw.githubusercontent.com/night-shift/fpconv/master/license)
|
||||
* Project Home: https://github.com/night-shift/fpconv/
|
||||
* License: [MIT License](https://raw.githubusercontent.com/night-shift/fpconv/master/license)
|
||||
|
||||
### libev 4.11
|
||||
|
||||
* Project Home: http://software.schmorp.de/pkg/libev.html
|
||||
* License: Dual-License, including [free as-is license](http://cvs.schmorp.de/libev/LICENSE?revision=1.11&view=markup)
|
||||
|
||||
### linenoise
|
||||
|
||||
* Project Home: https://github.com/antirez/linenoise
|
||||
* License: [free as-is license](https://raw.githubusercontent.com/antirez/linenoise/master/LICENSE)
|
||||
|
||||
### Valgrind
|
||||
|
||||
* Project Home: http://valgrind.org/
|
||||
* valgrind.h header file only
|
||||
* License: [BSD-style license](https://raw.githubusercontent.com/arangodb/arangodb/devel/3rdParty/valgrind/valgrind.h)
|
||||
|
||||
### zlib 1.2.7
|
||||
|
||||
* License: [free as-is license](https://github.com/arangodb/arangodb/blob/devel/3rdParty/zlib-1.2.7/README#L85)
|
||||
|
||||
## Programs
|
||||
|
||||
### autoconf
|
||||
|
||||
* Project Home: http://www.gnu.org/software/autoconf/autoconf.html
|
||||
* only used to generate code, not part of the distribution
|
||||
* License: [configure](https://github.com/arangodb/arangodb/blob/master/configure#L11) [ax_cxx_compile_stdcxx_11.m4](https://github.com/arangodb/arangodb/blob/master/m4/ax_cxx_compile_stdcxx_11.m4#L25)
|
||||
|
||||
### automake
|
||||
|
||||
* Project https://www.gnu.org/software/automake/
|
||||
* only used to generate code, not part of the distribution
|
||||
* License: [Makefile.in](https://raw.githubusercontent.com/arangodb/arangodb/master/Makefile.in)
|
||||
|
||||
### Bison 3.0
|
||||
|
||||
* Project Home: https://www.gnu.org/software/bison/
|
||||
* only used to generate code, not part of the distribution; for details about using Bison in this way see http://www.gnu.org/software/bison/manual/bison.html#Conditions
|
||||
* License: [grammar.cpp](https://github.com/arangodb/arangodb/blob/devel/arangod/Aql/grammar.cpp#L20)
|
||||
|
||||
### CoreOS etcd
|
||||
|
||||
* https://coreos.com/using-coreos/etcd/
|
||||
* [Apache 2 License](https://github.com/coreos/etcd/blob/master/LICENSE)
|
||||
* Project Home: https://coreos.com/using-coreos/etcd/
|
||||
* License: [Apache 2 License](https://github.com/coreos/etcd/blob/master/LICENSE)
|
||||
|
||||
### autotools
|
||||
### Flex 2.5
|
||||
|
||||
* http://www.gnu.org/software/autoconf/autoconf.html
|
||||
* https://www.gnu.org/software/automake/
|
||||
* Project Home: http://flex.sourceforge.net/
|
||||
* only used to generate code, not part of the distribution
|
||||
* parts generated are free as-is license
|
||||
* License: [free as-is license](http://flex.sourceforge.net/manual/Copyright.html#Copyright)
|
||||
|
||||
### Bison
|
||||
|
||||
* https://www.gnu.org/software/bison/
|
||||
* only used to generate code, not part of the distribution
|
||||
* parts generated use see https://github.com/arangodb/arangodb/blob/devel/arangod/Aql/grammar.cpp#L20
|
||||
|
||||
### Flex
|
||||
|
||||
* http://flex.sourceforge.net/
|
||||
* only used to generate code, not part of the distribution
|
||||
* [free as-is license](http://flex.sourceforge.net/manual/Copyright.html#Copyright)
|
||||
|
||||
## Javascript, Node and NPM
|
||||
## Javascript
|
||||
|
||||
### Node core modules
|
||||
|
||||
* http://nodejs.org
|
||||
* [MIT License](https://raw.githubusercontent.com/joyent/node/v0.10.33/LICENSE)
|
||||
* Project Home: http://nodejs.org
|
||||
* License: Node MIT License [_stream_duplex.js,_stream_passthrough.js,_stream_readable.js,_stream_transform.js,_stream_writable.js,events.js,querystring.js,stream.js,string_decoder.js,url.js](https://raw.githubusercontent.com/joyent/node/v0.10.33/LICENSE), MIT [punycode.js](https://raw.githubusercontent.com/joyent/node/v0.10.33/LICENSE)
|
||||
|
||||
### Bundled NPM modules
|
||||
|
||||
#### Jasmine
|
||||
#### Ace
|
||||
|
||||
* https://jasmine.github.io
|
||||
* [MIT License](https://raw.githubusercontent.com/jasmine/jasmine/master/MIT.LICENSE)
|
||||
|
||||
#### JSUnity
|
||||
|
||||
* https://github.com/atesgoral/jsunity
|
||||
* [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
* Project Home: https://github.com/ajaxorg/ace
|
||||
* License: [BSD 3-Clause License](https://raw.githubusercontent.com/ajaxorg/ace/master/LICENSE)
|
||||
|
||||
#### ArangoDB Query Builder
|
||||
|
||||
* https://github.com/arangodb/aqbjs
|
||||
* [Apache 2](https://raw.githubusercontent.com/arangodb/aqbjs/master/LICENSE)
|
||||
* Project Home: https://github.com/arangodb/aqbjs
|
||||
* License: [Apache 2](https://raw.githubusercontent.com/arangodb/aqbjs/master/LICENSE)
|
||||
|
||||
#### Chai
|
||||
|
||||
* http://chaijs.com
|
||||
* [MIT License](https://github.com/chaijs/chai/blob/master/README.md)
|
||||
* Project Home: http://chaijs.com
|
||||
* License: [MIT License](https://github.com/chaijs/chai/blob/master/README.md)
|
||||
|
||||
#### CoffeeScript
|
||||
|
||||
* http://coffeescript.org
|
||||
* [MIT License](https://www.npmjs.com/package/coffee-script)
|
||||
|
||||
#### stacktrace.js
|
||||
|
||||
* http://www.stacktracejs.com/
|
||||
* [The Unlicense](http://unlicense.org)
|
||||
* Project Home: http://coffeescript.org
|
||||
* License: [MIT License](https://www.npmjs.com/package/coffee-script)
|
||||
|
||||
#### expect.js
|
||||
|
||||
* https://github.com/Automattic/expect.js
|
||||
* [MIT License](https://github.com/Automattic/expect.js/blob/master/README.md)
|
||||
* Project Home: https://github.com/Automattic/expect.js
|
||||
* License: [MIT License](https://github.com/Automattic/expect.js/blob/master/README.md)
|
||||
|
||||
#### extendible
|
||||
|
||||
* https://github.com/3rd-Eden/extendible
|
||||
* [MIT License](https://github.com/bigpipe/extendible/blob/master/README.md)
|
||||
* Project Home: https://github.com/3rd-Eden/extendible
|
||||
* License: [MIT License](https://github.com/bigpipe/extendible/blob/master/README.md)
|
||||
|
||||
#### Foxx Generator
|
||||
|
||||
* https://github.com/moonglum/foxx_generator
|
||||
* [Apache 2 License](https://raw.githubusercontent.com/moonglum/foxx_generator/master/LICENSE)
|
||||
* Project Home: https://github.com/moonglum/foxx_generator
|
||||
* License: [Apache 2 License](https://raw.githubusercontent.com/moonglum/foxx_generator/master/LICENSE)
|
||||
|
||||
#### highlight.js
|
||||
|
||||
* https://highlightjs.org
|
||||
* [BSD 3-Clause License](https://raw.githubusercontent.com/isagalaev/highlight.js/master/LICENSE)
|
||||
* Project Home: https://highlightjs.org
|
||||
* License: [BSD 3-Clause License](https://raw.githubusercontent.com/isagalaev/highlight.js/master/LICENSE)
|
||||
|
||||
#### http-errors
|
||||
|
||||
* https://github.com/jshttp/http-errors
|
||||
* [MIT License](https://raw.githubusercontent.com/jshttp/http-errors/master/LICENSE)
|
||||
* Project Home: https://github.com/jshttp/http-errors
|
||||
* License: [MIT License](https://raw.githubusercontent.com/jshttp/http-errors/master/LICENSE)
|
||||
|
||||
#### i
|
||||
#### inflect
|
||||
|
||||
* https://github.com/pksunkara/inflect
|
||||
* [MIT License](https://raw.githubusercontent.com/pksunkara/inflect/master/LICENSE)
|
||||
* Project Home: https://github.com/pksunkara/inflect
|
||||
* License: [MIT License](https://raw.githubusercontent.com/pksunkara/inflect/master/LICENSE)
|
||||
|
||||
#### Jasmine
|
||||
|
||||
* Project Home: https://jasmine.github.io
|
||||
* License: [MIT License](https://raw.githubusercontent.com/jasmine/jasmine/master/MIT.LICENSE)
|
||||
|
||||
#### Joi
|
||||
|
||||
* https://github.com/hapijs/joi
|
||||
* [BSD 3-Clause License](https://raw.githubusercontent.com/hapijs/joi/master/LICENSE)
|
||||
* Project Home: https://github.com/hapijs/joi
|
||||
* License: [BSD 3-Clause License](https://raw.githubusercontent.com/hapijs/joi/master/LICENSE)
|
||||
|
||||
#### Ace
|
||||
#### JSHint
|
||||
|
||||
* https://github.com/ajaxorg/ace
|
||||
* [BSD 3-Clause License](https://raw.githubusercontent.com/ajaxorg/ace/master/LICENSE)
|
||||
* Project Home: http://jshint.com
|
||||
* License: [MIT License](https://raw.githubusercontent.com/jshint/jshint/master/LICENSE)
|
||||
|
||||
#### JSUnity
|
||||
|
||||
* Project Home: https://github.com/atesgoral/jsunity
|
||||
* License: [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
|
||||
#### minimatch
|
||||
|
||||
* Project Home: https://github.com/isaacs/minimatch
|
||||
* License: [MIT License](https://raw.githubusercontent.com/isaacs/minimatch/master/LICENSE)
|
||||
|
||||
#### mocha
|
||||
|
||||
* Project Home: http://mochajs.org
|
||||
* License: [MIT License](https://raw.githubusercontent.com/mochajs/mocha/master/LICENSE)
|
||||
|
||||
#### qs
|
||||
|
||||
* Project Home: https://github.com/hapijs/qs
|
||||
* License: [BSD 3-Clause License](https://raw.githubusercontent.com/hapijs/hapi/master/LICENSE)
|
||||
|
||||
#### Ramda
|
||||
|
||||
* Project Home: http://ramdajs.com
|
||||
* License: [MIT License](https://raw.githubusercontent.com/ramda/ramda/master/LICENSE.txt)
|
||||
|
||||
#### semver
|
||||
|
||||
* Project Home: https://github.com/npm/node-semver
|
||||
* License: [BSD 2-Clause License](http://opensource.org/licenses/BSD-2-Clause)
|
||||
|
||||
#### Sinon.JS
|
||||
|
||||
* Project Home: http://sinonjs.org
|
||||
* License: [BSD 3-Clause License](https://www.npmjs.com/package/sinon)
|
||||
|
||||
#### stacktrace.js
|
||||
|
||||
* Project Home: http://www.stacktracejs.com/
|
||||
* License: [The Unlicense](http://unlicense.org)
|
||||
|
||||
#### underscore
|
||||
|
||||
* Project Home: http://underscorejs.org
|
||||
* License: [MIT License](https://github.com/jashkenas/underscore/blob/master/LICENSE)
|
||||
|
||||
#### YAML
|
||||
|
||||
* https://github.com/nodeca/js-yaml
|
||||
* [MIT License](https://raw.githubusercontent.com/nodeca/js-yaml/master/LICENSE)
|
||||
|
||||
#### JSHint
|
||||
|
||||
* http://jshint.com
|
||||
* [MIT License](https://raw.githubusercontent.com/jshint/jshint/master/LICENSE)
|
||||
|
||||
#### minimatch
|
||||
|
||||
* https://github.com/isaacs/minimatch
|
||||
* [MIT License](https://raw.githubusercontent.com/isaacs/minimatch/master/LICENSE)
|
||||
|
||||
#### mocha
|
||||
|
||||
* http://mochajs.org
|
||||
* [MIT License](https://raw.githubusercontent.com/mochajs/mocha/master/LICENSE)
|
||||
|
||||
#### qs
|
||||
|
||||
* https://github.com/hapijs/qs
|
||||
* [BSD 3-Clause License](https://raw.githubusercontent.com/hapijs/hapi/master/LICENSE)
|
||||
|
||||
#### Ramda
|
||||
|
||||
* http://ramdajs.com
|
||||
* [MIT License](https://raw.githubusercontent.com/ramda/ramda/master/LICENSE.txt)
|
||||
|
||||
#### semver
|
||||
|
||||
* https://github.com/npm/node-semver
|
||||
* [BSD 2-Clause License](http://opensource.org/licenses/BSD-2-Clause)
|
||||
|
||||
#### Sinon.JS
|
||||
|
||||
* http://sinonjs.org
|
||||
* [BSD 3-Clause License](https://www.npmjs.com/package/sinon)
|
||||
|
||||
#### underscore
|
||||
|
||||
* http://underscorejs.org
|
||||
* [MIT License](https://github.com/jashkenas/underscore/blob/master/LICENSE)
|
||||
|
||||
### Frontend libraries
|
||||
|
||||
#### swagger
|
||||
|
|
|
@ -436,18 +436,88 @@ BOOST_AUTO_TEST_CASE (tst_json_string_utf8_3) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test empty json list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_json_list_empty) {
|
||||
INIT_BUFFER
|
||||
|
||||
|
||||
TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
|
||||
STRINGIFY
|
||||
BOOST_CHECK_EQUAL("[]", STRING_VALUE);
|
||||
FREE_JSON
|
||||
FREE_BUFFER
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test remove from array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_remove_from_array_empty) {
|
||||
TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
BOOST_CHECK_EQUAL(0ULL, TRI_LengthArrayJson(json));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 0));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 10));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 5));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 2));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 1));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 0));
|
||||
|
||||
FREE_JSON
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test remove from array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_remove_from_array_nonempty1) {
|
||||
TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
TRI_PushBack3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE));
|
||||
TRI_PushBack3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 3.5));
|
||||
|
||||
BOOST_CHECK_EQUAL(2ULL, TRI_LengthArrayJson(json));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 10));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 5));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 2));
|
||||
|
||||
BOOST_CHECK_EQUAL(true, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 1));
|
||||
BOOST_CHECK_EQUAL(static_cast<TRI_json_t*>(0), TRI_LookupArrayJson(json, 1));
|
||||
BOOST_CHECK_EQUAL(1ULL, TRI_LengthArrayJson(json));
|
||||
BOOST_CHECK_EQUAL(true, TRI_IsNullJson(TRI_LookupArrayJson(json, 0)));
|
||||
|
||||
BOOST_CHECK_EQUAL(true, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 0));
|
||||
BOOST_CHECK_EQUAL(0ULL, TRI_LengthArrayJson(json));
|
||||
BOOST_CHECK_EQUAL(static_cast<TRI_json_t*>(0), TRI_LookupArrayJson(json, 0));
|
||||
|
||||
FREE_JSON
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test remove from array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_remove_from_array_nonempty2) {
|
||||
TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
TRI_PushBack3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE));
|
||||
TRI_PushBack3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 3.5));
|
||||
|
||||
BOOST_CHECK_EQUAL(2ULL, TRI_LengthArrayJson(json));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 10));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 5));
|
||||
BOOST_CHECK_EQUAL(false, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 2));
|
||||
|
||||
BOOST_CHECK_EQUAL(true, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 0));
|
||||
BOOST_CHECK_EQUAL(1ULL, TRI_LengthArrayJson(json));
|
||||
BOOST_CHECK_EQUAL(static_cast<TRI_json_t*>(0), TRI_LookupArrayJson(json, 1));
|
||||
BOOST_CHECK_EQUAL(true, TRI_IsNumberJson(TRI_LookupArrayJson(json, 0)));
|
||||
|
||||
BOOST_CHECK_EQUAL(true, TRI_DeleteArrayJson(TRI_UNKNOWN_MEM_ZONE, json, 0));
|
||||
BOOST_CHECK_EQUAL(0ULL, TRI_LengthArrayJson(json));
|
||||
BOOST_CHECK_EQUAL(static_cast<TRI_json_t*>(0), TRI_LookupArrayJson(json, 0));
|
||||
|
||||
FREE_JSON
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test json list mixed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -83,6 +83,7 @@ BOOST_AUTO_TEST_CASE (tst_deque_case) {
|
|||
BOOST_CHECK_EQUAL(true, pq.empty());
|
||||
|
||||
bool b;
|
||||
MyValue* v;
|
||||
|
||||
b = pq.insert("a", new MyValue("a", 1));
|
||||
BOOST_CHECK_EQUAL(b, true);
|
||||
|
@ -92,8 +93,10 @@ BOOST_AUTO_TEST_CASE (tst_deque_case) {
|
|||
BOOST_CHECK_EQUAL(b, true);
|
||||
b = pq.insert("d", new MyValue("d", 4));
|
||||
BOOST_CHECK_EQUAL(b, true);
|
||||
b = pq.insert("c", new MyValue("c", 5));
|
||||
v = new MyValue("c", 5);
|
||||
b = pq.insert("c", v);
|
||||
BOOST_CHECK_EQUAL(b, false);
|
||||
delete v;
|
||||
|
||||
BOOST_CHECK_EQUAL(4, (int) pq.size());
|
||||
BOOST_CHECK_EQUAL(false, pq.empty());
|
||||
|
@ -112,7 +115,6 @@ BOOST_AUTO_TEST_CASE (tst_deque_case) {
|
|||
BOOST_CHECK(p == nullptr);
|
||||
|
||||
std::string k;
|
||||
MyValue* v;
|
||||
|
||||
p = pq.getMinimal();
|
||||
BOOST_CHECK_EQUAL(p->_key, "a");
|
||||
|
@ -173,6 +175,7 @@ BOOST_AUTO_TEST_CASE (tst_heap_case) {
|
|||
BOOST_CHECK_EQUAL(true, pq.empty());
|
||||
|
||||
bool b;
|
||||
MyValue* v;
|
||||
|
||||
b = pq.insert("a", new MyValue("a", 4));
|
||||
BOOST_CHECK_EQUAL(b, true);
|
||||
|
@ -182,8 +185,10 @@ BOOST_AUTO_TEST_CASE (tst_heap_case) {
|
|||
BOOST_CHECK_EQUAL(b, true);
|
||||
b = pq.insert("d", new MyValue("d", 2));
|
||||
BOOST_CHECK_EQUAL(b, true);
|
||||
b = pq.insert("c", new MyValue("c", 5));
|
||||
v = new MyValue("c", 5);
|
||||
b = pq.insert("c", v);
|
||||
BOOST_CHECK_EQUAL(b, false);
|
||||
delete v;
|
||||
|
||||
BOOST_CHECK_EQUAL(4, (int) pq.size());
|
||||
BOOST_CHECK_EQUAL(false, pq.empty());
|
||||
|
@ -202,7 +207,6 @@ BOOST_AUTO_TEST_CASE (tst_heap_case) {
|
|||
BOOST_CHECK(p == nullptr);
|
||||
|
||||
std::string k;
|
||||
MyValue* v;
|
||||
|
||||
p = pq.getMinimal();
|
||||
BOOST_CHECK_EQUAL(p->_key, "b");
|
||||
|
@ -263,6 +267,7 @@ BOOST_AUTO_TEST_CASE (tst_deque_case_with_lowering) {
|
|||
BOOST_CHECK_EQUAL(true, pq.empty());
|
||||
|
||||
bool b;
|
||||
MyValue* v;
|
||||
|
||||
b = pq.insert("a", new MyValue("a", 1));
|
||||
BOOST_CHECK_EQUAL(b, true);
|
||||
|
@ -272,8 +277,10 @@ BOOST_AUTO_TEST_CASE (tst_deque_case_with_lowering) {
|
|||
BOOST_CHECK_EQUAL(b, true);
|
||||
b = pq.insert("d", new MyValue("d", 4));
|
||||
BOOST_CHECK_EQUAL(b, true);
|
||||
b = pq.insert("c", new MyValue("c", 5));
|
||||
v = new MyValue("c", 5);
|
||||
b = pq.insert("c", v);
|
||||
BOOST_CHECK_EQUAL(b, false);
|
||||
delete v;
|
||||
|
||||
BOOST_CHECK_EQUAL(4, (int) pq.size());
|
||||
BOOST_CHECK_EQUAL(false, pq.empty());
|
||||
|
@ -294,7 +301,6 @@ BOOST_AUTO_TEST_CASE (tst_deque_case_with_lowering) {
|
|||
BOOST_CHECK(p == nullptr);
|
||||
|
||||
std::string k;
|
||||
MyValue* v;
|
||||
|
||||
p = pq.getMinimal();
|
||||
BOOST_CHECK_EQUAL(p->_key, "a");
|
||||
|
@ -355,6 +361,7 @@ BOOST_AUTO_TEST_CASE (tst_heap_case_with_lowering) {
|
|||
BOOST_CHECK_EQUAL(true, pq.empty());
|
||||
|
||||
bool b;
|
||||
MyValue* v;
|
||||
|
||||
b = pq.insert("a", new MyValue("a", 4));
|
||||
BOOST_CHECK_EQUAL(b, true);
|
||||
|
@ -364,8 +371,10 @@ BOOST_AUTO_TEST_CASE (tst_heap_case_with_lowering) {
|
|||
BOOST_CHECK_EQUAL(b, true);
|
||||
b = pq.insert("d", new MyValue("d", 3));
|
||||
BOOST_CHECK_EQUAL(b, true);
|
||||
b = pq.insert("c", new MyValue("c", 5));
|
||||
v = new MyValue("c", 5);
|
||||
b = pq.insert("c", v);
|
||||
BOOST_CHECK_EQUAL(b, false);
|
||||
delete v;
|
||||
|
||||
BOOST_CHECK_EQUAL(4, (int) pq.size());
|
||||
BOOST_CHECK_EQUAL(false, pq.empty());
|
||||
|
@ -386,7 +395,6 @@ BOOST_AUTO_TEST_CASE (tst_heap_case_with_lowering) {
|
|||
BOOST_CHECK(p == nullptr);
|
||||
|
||||
std::string k;
|
||||
MyValue* v;
|
||||
|
||||
p = pq.getMinimal();
|
||||
BOOST_CHECK_EQUAL(p->_key, "a");
|
||||
|
|
|
@ -480,8 +480,6 @@ BOOST_AUTO_TEST_CASE (tst_clear) {
|
|||
const char* ptr = TRI_BeginStringBuffer(&sb);
|
||||
TRI_ClearStringBuffer(&sb);
|
||||
BOOST_CHECK_EQUAL(0, (int) TRI_LengthStringBuffer(&sb));
|
||||
// clang 5.1 failes without the cast
|
||||
BOOST_CHECK_EQUAL((unsigned int) '\0', (unsigned int) TRI_LastCharStringBuffer(&sb));
|
||||
|
||||
// buffer should still point to ptr
|
||||
BOOST_CHECK_EQUAL((void*) ptr, (void*) TRI_BeginStringBuffer(&sb));
|
||||
|
@ -531,9 +529,6 @@ BOOST_AUTO_TEST_CASE (tst_last_char) {
|
|||
|
||||
TRI_InitStringBuffer(&sb, TRI_CORE_MEM_ZONE);
|
||||
|
||||
// clang 5.1 failes without the cast
|
||||
BOOST_CHECK_EQUAL((unsigned int) '\0', (unsigned int) TRI_LastCharStringBuffer(&sb));
|
||||
|
||||
TRI_AppendStringStringBuffer(&sb, "f");
|
||||
BOOST_CHECK_EQUAL((unsigned int) 'f', (unsigned int) TRI_LastCharStringBuffer(&sb));
|
||||
|
||||
|
@ -544,7 +539,7 @@ BOOST_AUTO_TEST_CASE (tst_last_char) {
|
|||
BOOST_CHECK_EQUAL((unsigned int) '\n', (unsigned int) TRI_LastCharStringBuffer(&sb));
|
||||
|
||||
TRI_ClearStringBuffer(&sb);
|
||||
BOOST_CHECK_EQUAL((unsigned int) '\0', (unsigned int) TRI_LastCharStringBuffer(&sb));
|
||||
BOOST_CHECK_EQUAL(0, (int) TRI_LengthStringBuffer(&sb));
|
||||
|
||||
for (size_t i = 0; i < 100; ++i) {
|
||||
TRI_AppendStringStringBuffer(&sb, "the quick brown fox jumped over the lazy dog");
|
||||
|
@ -554,7 +549,6 @@ BOOST_AUTO_TEST_CASE (tst_last_char) {
|
|||
BOOST_CHECK_EQUAL((unsigned int) '.', (unsigned int) TRI_LastCharStringBuffer(&sb));
|
||||
|
||||
TRI_AnnihilateStringBuffer(&sb);
|
||||
BOOST_CHECK_EQUAL((unsigned int) '\0', (unsigned int) TRI_LastCharStringBuffer(&sb));
|
||||
|
||||
TRI_DestroyStringBuffer(&sb);
|
||||
}
|
||||
|
|
|
@ -3734,6 +3734,10 @@ static void JS_CollectionVocbase (const v8::FunctionCallbackInfo<v8::Value>& arg
|
|||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (TRI_IsDeletedVocBase(vocbase)) {
|
||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
// expecting one argument
|
||||
if (args.Length() != 1) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("_collection(<name>|<identifier>)");
|
||||
|
|
|
@ -54,9 +54,9 @@ TRI_vocbase_t* GetContextVocBase (v8::Isolate* isolate) {
|
|||
|
||||
v8::Handle<v8::Value> V8TickId (v8::Isolate* isolate, TRI_voc_tick_t tick) {
|
||||
char buffer[21];
|
||||
size_t len = TRI_StringUInt64InPlace((uint64_t) tick, (char*) &buffer);
|
||||
size_t len = TRI_StringUInt64InPlace(static_cast<uint64_t>(tick), &buffer[0]);
|
||||
|
||||
return TRI_V8_PAIR_STRING((char const*) buffer, (int) len);
|
||||
return TRI_V8_PAIR_STRING(&buffer[0], static_cast<int>(len));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -65,9 +65,9 @@ v8::Handle<v8::Value> V8TickId (v8::Isolate* isolate, TRI_voc_tick_t tick) {
|
|||
|
||||
v8::Handle<v8::Value> V8RevisionId (v8::Isolate* isolate, TRI_voc_rid_t rid) {
|
||||
char buffer[21];
|
||||
size_t len = TRI_StringUInt64InPlace((uint64_t) rid, (char*) &buffer);
|
||||
size_t len = TRI_StringUInt64InPlace(static_cast<uint64_t>(rid), &buffer[0]);
|
||||
|
||||
return TRI_V8_PAIR_STRING((char const*) buffer, (int) len);
|
||||
return TRI_V8_PAIR_STRING(&buffer[0], static_cast<int>(len));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -75,9 +75,9 @@ v8::Handle<v8::Value> V8RevisionId (v8::Isolate* isolate, TRI_voc_rid_t rid) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> V8DocumentId (v8::Isolate* isolate,
|
||||
string const& collectionName,
|
||||
string const& key) {
|
||||
string const&& id = DocumentHelper::assembleDocumentId(collectionName, key);
|
||||
std::string const& collectionName,
|
||||
std::string const& key) {
|
||||
std::string const&& id = DocumentHelper::assembleDocumentId(collectionName, key);
|
||||
|
||||
return TRI_V8_STD_STRING(id);
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ v8::Handle<v8::Value> V8DocumentId (v8::Isolate* isolate,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool ParseDocumentHandle (v8::Handle<v8::Value> const arg,
|
||||
string& collectionName,
|
||||
std::string& collectionName,
|
||||
std::unique_ptr<char[]>& key) {
|
||||
TRI_ASSERT(collectionName.empty());
|
||||
|
||||
|
|
|
@ -3140,6 +3140,10 @@ static void JS_UseDatabase (const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
if (TRI_IsDeletedVocBase(vocbase)) {
|
||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (TRI_EqualString(name.c_str(), vocbase->_name)) {
|
||||
// same database. nothing to do
|
||||
TRI_V8_RETURN(WrapVocBase(isolate, vocbase));
|
||||
|
|
|
@ -63,8 +63,6 @@
|
|||
#include "Wal/Marker.h"
|
||||
#include "Wal/Slots.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace triagens::arango;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -117,7 +115,9 @@ void TRI_doc_mptr_copy_t::setDataPtr (void const* d) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_document_collection_t::TRI_document_collection_t ()
|
||||
: _useSecondaryIndexes(true),
|
||||
: _lock(),
|
||||
_shaper(nullptr),
|
||||
_useSecondaryIndexes(true),
|
||||
_capConstraint(nullptr),
|
||||
_ditches(this),
|
||||
_headersPtr(nullptr),
|
||||
|
@ -199,6 +199,14 @@ int TRI_document_collection_t::beginWrite () {
|
|||
// std::cout << "BeginWrite: " << document->_info._name << std::endl;
|
||||
TRI_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(this);
|
||||
|
||||
try {
|
||||
_vocbase->_deadlockDetector.setWriterStarted(this);
|
||||
}
|
||||
catch (...) {
|
||||
TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(this);
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -220,6 +228,12 @@ int TRI_document_collection_t::endWrite () {
|
|||
// LOCKING-DEBUG
|
||||
// std::cout << "EndWrite: " << document->_info._name << std::endl;
|
||||
TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(this);
|
||||
|
||||
try {
|
||||
_vocbase->_deadlockDetector.setWriterFinished(this);
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
@ -241,10 +255,45 @@ int TRI_document_collection_t::beginReadTimed (uint64_t timeout,
|
|||
}
|
||||
}
|
||||
uint64_t waited = 0;
|
||||
if (timeout == 0) {
|
||||
// we don't allow looping forever. limit waiting to 15 minutes max.
|
||||
timeout = 15 * 60 * 1000 * 1000;
|
||||
}
|
||||
|
||||
// LOCKING-DEBUG
|
||||
// std::cout << "BeginReadTimed: " << document->_info._name << std::endl;
|
||||
int iterations = 0;
|
||||
bool wasBlocked = false;
|
||||
|
||||
while (! TRI_TRY_READ_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(this)) {
|
||||
try {
|
||||
if (! wasBlocked) {
|
||||
// insert reader
|
||||
if (_vocbase->_deadlockDetector.setReaderBlocked(this)) {
|
||||
// deadlock
|
||||
return TRI_ERROR_DEADLOCK;
|
||||
}
|
||||
wasBlocked = true;
|
||||
}
|
||||
else if (++iterations >= 5) {
|
||||
// periodically check for deadlocks
|
||||
TRI_ASSERT(wasBlocked);
|
||||
iterations = 0;
|
||||
if (_vocbase->_deadlockDetector.isDeadlocked(this)) {
|
||||
// deadlock
|
||||
_vocbase->_deadlockDetector.setReaderUnblocked(this);
|
||||
return TRI_ERROR_DEADLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
// clean up!
|
||||
if (wasBlocked) {
|
||||
_vocbase->_deadlockDetector.setReaderUnblocked(this);
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
usleep((unsigned long) sleepPeriod);
|
||||
#else
|
||||
|
@ -254,10 +303,16 @@ int TRI_document_collection_t::beginReadTimed (uint64_t timeout,
|
|||
waited += sleepPeriod;
|
||||
|
||||
if (waited > timeout) {
|
||||
_vocbase->_deadlockDetector.setReaderUnblocked(this);
|
||||
return TRI_ERROR_LOCK_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
// when we are here, we've got the read lock
|
||||
if (wasBlocked) {
|
||||
_vocbase->_deadlockDetector.setReaderUnblocked(this);
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -278,10 +333,45 @@ int TRI_document_collection_t::beginWriteTimed (uint64_t timeout,
|
|||
}
|
||||
}
|
||||
uint64_t waited = 0;
|
||||
if (timeout == 0) {
|
||||
// we don't allow looping forever. limit waiting to 15 minutes max.
|
||||
timeout = 15 * 60 * 1000 * 1000;
|
||||
}
|
||||
|
||||
// LOCKING-DEBUG
|
||||
// std::cout << "BeginWriteTimed: " << document->_info._name << std::endl;
|
||||
int iterations = 0;
|
||||
bool wasBlocked = false;
|
||||
|
||||
while (! TRI_TRY_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(this)) {
|
||||
try {
|
||||
if (! wasBlocked) {
|
||||
// insert writer (with method named "setReaderBlocked"..., but it works)
|
||||
if (_vocbase->_deadlockDetector.setReaderBlocked(this)) {
|
||||
// deadlock
|
||||
return TRI_ERROR_DEADLOCK;
|
||||
}
|
||||
wasBlocked = true;
|
||||
}
|
||||
else if (++iterations >= 5) {
|
||||
// periodically check for deadlocks
|
||||
TRI_ASSERT(wasBlocked);
|
||||
iterations = 0;
|
||||
if (_vocbase->_deadlockDetector.isDeadlocked(this)) {
|
||||
// deadlock
|
||||
_vocbase->_deadlockDetector.setReaderUnblocked(this);
|
||||
return TRI_ERROR_DEADLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
// clean up!
|
||||
if (wasBlocked) {
|
||||
_vocbase->_deadlockDetector.setReaderUnblocked(this);
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
usleep((unsigned long) sleepPeriod);
|
||||
#else
|
||||
|
@ -291,9 +381,23 @@ int TRI_document_collection_t::beginWriteTimed (uint64_t timeout,
|
|||
waited += sleepPeriod;
|
||||
|
||||
if (waited > timeout) {
|
||||
_vocbase->_deadlockDetector.setReaderUnblocked(this);
|
||||
return TRI_ERROR_LOCK_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
// when we are here, we've got the write lock
|
||||
if (wasBlocked) {
|
||||
_vocbase->_deadlockDetector.setReaderUnblocked(this);
|
||||
}
|
||||
|
||||
try {
|
||||
_vocbase->_deadlockDetector.setWriterStarted(this);
|
||||
}
|
||||
catch (...) {
|
||||
TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(this);
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
|
|
@ -364,7 +364,6 @@ struct TRI_document_collection_t : public TRI_collection_t {
|
|||
// TRI_read_write_lock_t _lock;
|
||||
triagens::basics::ReadWriteLockCPP11 _lock;
|
||||
|
||||
|
||||
private:
|
||||
VocShaper* _shaper;
|
||||
|
||||
|
|
|
@ -365,8 +365,6 @@ static void FreeDitch (TRI_transaction_collection_t* trxCollection) {
|
|||
static int LockCollection (TRI_transaction_collection_t* trxCollection,
|
||||
TRI_transaction_type_e type,
|
||||
int nestingLevel) {
|
||||
int res;
|
||||
|
||||
TRI_ASSERT(trxCollection != nullptr);
|
||||
|
||||
TRI_transaction_t* trx = trxCollection->_transaction;
|
||||
|
@ -394,29 +392,20 @@ static int LockCollection (TRI_transaction_collection_t* trxCollection,
|
|||
|
||||
TRI_document_collection_t* document = trxCollection->_collection->_collection;
|
||||
|
||||
int res;
|
||||
if (type == TRI_TRANSACTION_READ) {
|
||||
LOG_TRX(trx,
|
||||
nestingLevel,
|
||||
"read-locking collection %llu",
|
||||
(unsigned long long) trxCollection->_cid);
|
||||
if (trx->_timeout == 0) {
|
||||
res = document->beginRead();
|
||||
}
|
||||
else {
|
||||
res = document->beginReadTimed(trx->_timeout, TRI_TRANSACTION_DEFAULT_SLEEP_DURATION);
|
||||
}
|
||||
res = document->beginReadTimed(trx->_timeout, TRI_TRANSACTION_DEFAULT_SLEEP_DURATION);
|
||||
}
|
||||
else {
|
||||
LOG_TRX(trx,
|
||||
nestingLevel,
|
||||
"write-locking collection %llu",
|
||||
(unsigned long long) trxCollection->_cid);
|
||||
if (trx->_timeout == 0) {
|
||||
res = document->beginWrite();
|
||||
}
|
||||
else {
|
||||
res = document->beginWriteTimed(trx->_timeout, TRI_TRANSACTION_DEFAULT_SLEEP_DURATION);
|
||||
}
|
||||
res = document->beginWriteTimed(trx->_timeout, TRI_TRANSACTION_DEFAULT_SLEEP_DURATION * 50);
|
||||
}
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
|
@ -816,7 +805,7 @@ TRI_transaction_t* TRI_CreateTransaction (TRI_vocbase_t* vocbase,
|
|||
trx->_timeout = (uint64_t) (timeout * 1000000.0);
|
||||
}
|
||||
else if (timeout == 0.0) {
|
||||
trx->_timeout = (uint64_t) 0;
|
||||
trx->_timeout = static_cast<uint64_t>(0);
|
||||
}
|
||||
|
||||
TRI_InitVectorPointer(&trx->_collections, TRI_UNKNOWN_MEM_ZONE, 2);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/associative.h"
|
||||
#include "Basics/DeadlockDetector.h"
|
||||
#include "Basics/locks.h"
|
||||
#include "Basics/ReadWriteLock.h"
|
||||
#include "Basics/threads.h"
|
||||
|
@ -274,6 +275,8 @@ struct TRI_vocbase_t {
|
|||
TRI_server_t* _server;
|
||||
TRI_vocbase_defaults_t _settings;
|
||||
|
||||
triagens::basics::DeadlockDetector<TRI_document_collection_t> _deadlockDetector;
|
||||
|
||||
triagens::basics::ReadWriteLock _collectionsLock; // collection iterator lock
|
||||
std::vector<struct TRI_vocbase_col_s*> _collections; // pointers to ALL collections
|
||||
std::vector<struct TRI_vocbase_col_s*> _deadCollections; // pointers to collections dropped that can be removed later
|
||||
|
|
|
@ -1290,6 +1290,79 @@ struct TransactionCountTest : public BenchmarkOperation {
|
|||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- transaction deadlock test
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
struct TransactionDeadlockTest : public BenchmarkOperation {
|
||||
TransactionDeadlockTest ()
|
||||
: BenchmarkOperation () {
|
||||
}
|
||||
|
||||
~TransactionDeadlockTest () {
|
||||
}
|
||||
|
||||
bool setUp (SimpleHttpClient* client) {
|
||||
_c1 = std::string(Collection + "1");
|
||||
_c2 = std::string(Collection + "2");
|
||||
|
||||
return DeleteCollection(client, _c1) &&
|
||||
DeleteCollection(client, _c2) &&
|
||||
CreateCollection(client, _c1, 2) &&
|
||||
CreateCollection(client, _c2, 2) &&
|
||||
CreateDocument(client, _c2, "{ \"_key\": \"sum\", \"count\": 0 }");
|
||||
}
|
||||
|
||||
void tearDown () {
|
||||
}
|
||||
|
||||
std::string url (const int threadNumber, const size_t threadCounter, const size_t globalCounter) {
|
||||
return std::string("/_api/transaction");
|
||||
}
|
||||
|
||||
HttpRequest::HttpRequestType type (const int threadNumber, const size_t threadCounter, const size_t globalCounter) {
|
||||
return HttpRequest::HTTP_REQUEST_POST;
|
||||
}
|
||||
|
||||
const char* payload (size_t* length, const int threadNumber, const size_t threadCounter, const size_t globalCounter, bool* mustFree) {
|
||||
const size_t mod = globalCounter % 2;
|
||||
TRI_string_buffer_t* buffer;
|
||||
buffer = TRI_CreateSizedStringBuffer(TRI_UNKNOWN_MEM_ZONE, 256);
|
||||
|
||||
TRI_AppendStringStringBuffer(buffer, "{ \"collections\": { ");
|
||||
TRI_AppendStringStringBuffer(buffer, "\"write\": [ \"");
|
||||
|
||||
if (mod == 0) {
|
||||
TRI_AppendStringStringBuffer(buffer, _c1.c_str());
|
||||
}
|
||||
else {
|
||||
TRI_AppendStringStringBuffer(buffer, _c2.c_str());
|
||||
}
|
||||
|
||||
TRI_AppendStringStringBuffer(buffer, "\" ] }, \"action\": \"function () { ");
|
||||
TRI_AppendStringStringBuffer(buffer, "var c = require(\\\"internal\\\").db[\\\"");
|
||||
if (mod == 0) {
|
||||
TRI_AppendStringStringBuffer(buffer, _c2.c_str());
|
||||
}
|
||||
else {
|
||||
TRI_AppendStringStringBuffer(buffer, _c1.c_str());
|
||||
}
|
||||
TRI_AppendStringStringBuffer(buffer, "\\\"]; c.any();");
|
||||
|
||||
TRI_AppendStringStringBuffer(buffer, " }\" }");
|
||||
|
||||
*length = TRI_LengthStringBuffer(buffer);
|
||||
*mustFree = true;
|
||||
char* ptr = TRI_StealStringBuffer(buffer);
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
|
||||
return (const char*) ptr;
|
||||
}
|
||||
|
||||
std::string _c1;
|
||||
std::string _c2;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- transaction test
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -1738,6 +1811,9 @@ static BenchmarkOperation* GetTestCase (const std::string& name) {
|
|||
if (name == "multitrx") {
|
||||
return new TransactionMultiTest();
|
||||
}
|
||||
if (name == "deadlocktrx") {
|
||||
return new TransactionDeadlockTest();
|
||||
}
|
||||
if (name == "multi-collection") {
|
||||
return new TransactionMultiCollectionTest();
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
"ERROR_LEGEND_NOT_IN_WAL_FILE" : { "code" : 26, "message" : "internal error if a legend for a marker does not yet exist in the same WAL file" },
|
||||
"ERROR_FILE_EXISTS" : { "code" : 27, "message" : "file exists" },
|
||||
"ERROR_LOCKED" : { "code" : 28, "message" : "locked" },
|
||||
"ERROR_DEADLOCK" : { "code" : 29, "message" : "deadlock detected" },
|
||||
"ERROR_HTTP_BAD_PARAMETER" : { "code" : 400, "message" : "bad parameter" },
|
||||
"ERROR_HTTP_UNAUTHORIZED" : { "code" : 401, "message" : "unauthorized" },
|
||||
"ERROR_HTTP_FORBIDDEN" : { "code" : 403, "message" : "forbidden" },
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
"ERROR_LEGEND_NOT_IN_WAL_FILE" : { "code" : 26, "message" : "internal error if a legend for a marker does not yet exist in the same WAL file" },
|
||||
"ERROR_FILE_EXISTS" : { "code" : 27, "message" : "file exists" },
|
||||
"ERROR_LOCKED" : { "code" : 28, "message" : "locked" },
|
||||
"ERROR_DEADLOCK" : { "code" : 29, "message" : "deadlock detected" },
|
||||
"ERROR_HTTP_BAD_PARAMETER" : { "code" : 400, "message" : "bad parameter" },
|
||||
"ERROR_HTTP_UNAUTHORIZED" : { "code" : 401, "message" : "unauthorized" },
|
||||
"ERROR_HTTP_FORBIDDEN" : { "code" : 403, "message" : "forbidden" },
|
||||
|
|
|
@ -0,0 +1,257 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deadlock detector
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2013-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGODB_BASICS_DEADLOCK_DETECTOR_H
|
||||
#define ARANGODB_BASICS_DEADLOCK_DETECTOR_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/Mutex.h"
|
||||
#include "Basics/MutexLocker.h"
|
||||
#include "Basics/threads.h"
|
||||
|
||||
namespace triagens {
|
||||
namespace basics {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- DeadlockDetector
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
class DeadlockDetector {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
DeadlockDetector () = default;
|
||||
~DeadlockDetector () = default;
|
||||
|
||||
DeadlockDetector (DeadlockDetector const&) = delete;
|
||||
DeadlockDetector& operator= (DeadlockDetector const&) = delete;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
bool isDeadlocked (T const* value) {
|
||||
auto tid = TRI_CurrentThreadId();
|
||||
std::unordered_set<TRI_tid_t> watchFor({ tid });
|
||||
|
||||
std::vector<TRI_tid_t> stack;
|
||||
|
||||
TRI_tid_t writerTid;
|
||||
|
||||
{
|
||||
MUTEX_LOCKER(_writersLock);
|
||||
// find responsible writer
|
||||
auto it = _writers.find(value);
|
||||
|
||||
if (it == _writers.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
writerTid = (*it).second;
|
||||
}
|
||||
|
||||
stack.push_back(writerTid);
|
||||
|
||||
MUTEX_LOCKER(_readersLock);
|
||||
|
||||
while (! stack.empty()) {
|
||||
TRI_tid_t current = stack.back();
|
||||
stack.pop_back();
|
||||
|
||||
watchFor.emplace(current);
|
||||
auto it2 = _readersBlocked.find(current);
|
||||
|
||||
if (it2 == _readersBlocked.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (watchFor.find((*it2).second) != watchFor.end()) {
|
||||
// deadlock!
|
||||
return true;
|
||||
}
|
||||
|
||||
stack.push_back((*it2).second);
|
||||
}
|
||||
|
||||
// no deadlock found
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief insert a reader into the list of blocked readers
|
||||
/// returns true if a deadlock was detected and false otherwise
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool setReaderBlocked (T const* value) {
|
||||
auto tid = TRI_CurrentThreadId();
|
||||
std::unordered_set<TRI_tid_t> watchFor({ tid });
|
||||
|
||||
std::vector<TRI_tid_t> stack;
|
||||
|
||||
TRI_tid_t writerTid;
|
||||
|
||||
{
|
||||
MUTEX_LOCKER(_writersLock);
|
||||
// find responsible writer
|
||||
auto it = _writers.find(value);
|
||||
|
||||
if (it == _writers.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
writerTid = (*it).second;
|
||||
}
|
||||
|
||||
stack.push_back(writerTid);
|
||||
|
||||
MUTEX_LOCKER(_readersLock);
|
||||
_readersBlocked.emplace(tid, writerTid);
|
||||
|
||||
try {
|
||||
while (! stack.empty()) {
|
||||
TRI_tid_t current = stack.back();
|
||||
stack.pop_back();
|
||||
|
||||
watchFor.emplace(current);
|
||||
auto it2 = _readersBlocked.find(current);
|
||||
|
||||
if (it2 == _readersBlocked.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (watchFor.find((*it2).second) != watchFor.end()) {
|
||||
// deadlock!
|
||||
_readersBlocked.erase(tid);
|
||||
return true;
|
||||
}
|
||||
|
||||
stack.push_back((*it2).second);
|
||||
}
|
||||
|
||||
// no deadlock found
|
||||
return false;
|
||||
}
|
||||
catch (...) {
|
||||
// clean up and re-throw
|
||||
_readersBlocked.erase(tid);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove a reader from the list of blocked readers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setReaderUnblocked (T const* value) noexcept {
|
||||
auto tid = TRI_CurrentThreadId();
|
||||
|
||||
try {
|
||||
MUTEX_LOCKER(_readersLock);
|
||||
_readersBlocked.erase(tid);
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief inserts a writer into the list of writers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setWriterStarted (T const* value) {
|
||||
auto tid = TRI_CurrentThreadId();
|
||||
|
||||
MUTEX_LOCKER(_writersLock);
|
||||
_writers.emplace(value, tid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes a writers from the list of writers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setWriterFinished (T const* value) noexcept {
|
||||
try {
|
||||
MUTEX_LOCKER(_writersLock);
|
||||
_writers.erase(value);
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lock for managing the writers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
triagens::basics::Mutex _writersLock;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief all operating writers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_map<T const*, TRI_tid_t> _writers;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lock for managing the readers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
triagens::basics::Mutex _readersLock;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief readers that are blocked on writers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_map<TRI_tid_t, TRI_tid_t> _readersBlocked;
|
||||
|
||||
};
|
||||
|
||||
} // namespace triagens::basics
|
||||
} // namespace triagens
|
||||
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
// End:
|
|
@ -31,6 +31,7 @@ ERROR_IP_ADDRESS_INVALID,25,"IP address is invalid","Will be raised when the str
|
|||
ERROR_LEGEND_NOT_IN_WAL_FILE,26,"internal error if a legend for a marker does not yet exist in the same WAL file","Will be raised internally, then fixed internally, and never come out to the user."
|
||||
ERROR_FILE_EXISTS,27,"file exists","Will be raised when a file already exists."
|
||||
ERROR_LOCKED,28,"locked","Will be raised when a resource or an operation is locked."
|
||||
ERROR_DEADLOCK,29,"deadlock detected","Will be raised when a deadlock is detected when accessing collections."
|
||||
|
||||
################################################################################
|
||||
## HTTP standard errors
|
||||
|
|
|
@ -669,6 +669,27 @@ TRI_json_t* TRI_LookupArrayJson (TRI_json_t const* array, size_t pos) {
|
|||
return static_cast<TRI_json_t*>(TRI_AtVector(&array->_value._objects, pos));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deletes an element from a json array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_DeleteArrayJson (TRI_memory_zone_t* zone, TRI_json_t* array, size_t index) {
|
||||
TRI_ASSERT(TRI_IsArrayJson(array));
|
||||
|
||||
size_t const n = TRI_LengthArrayJson(array);
|
||||
|
||||
if (index >= n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TRI_json_t* element = static_cast<TRI_json_t*>(TRI_AtVector(&array->_value._objects, index));
|
||||
TRI_ASSERT(element != nullptr);
|
||||
TRI_DestroyJson(zone, element);
|
||||
TRI_RemoveVector(&array->_value._objects, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a new attribute to an object, using copy
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -292,6 +292,14 @@ int TRI_PushBack3ArrayJson (TRI_memory_zone_t*,
|
|||
TRI_json_t* TRI_LookupArrayJson (TRI_json_t const*,
|
||||
size_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deletes an element from a json array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_DeleteArrayJson (TRI_memory_zone_t* zone,
|
||||
TRI_json_t* object,
|
||||
size_t index);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a new attribute to an object, using copy
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -35,6 +35,7 @@ void TRI_InitializeErrorMessages () {
|
|||
REG_ERROR(ERROR_LEGEND_NOT_IN_WAL_FILE, "internal error if a legend for a marker does not yet exist in the same WAL file");
|
||||
REG_ERROR(ERROR_FILE_EXISTS, "file exists");
|
||||
REG_ERROR(ERROR_LOCKED, "locked");
|
||||
REG_ERROR(ERROR_DEADLOCK, "deadlock detected");
|
||||
REG_ERROR(ERROR_HTTP_BAD_PARAMETER, "bad parameter");
|
||||
REG_ERROR(ERROR_HTTP_UNAUTHORIZED, "unauthorized");
|
||||
REG_ERROR(ERROR_HTTP_FORBIDDEN, "forbidden");
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
/// Will be raised when a file already exists.
|
||||
/// - 28: @LIT{locked}
|
||||
/// Will be raised when a resource or an operation is locked.
|
||||
/// - 29: @LIT{deadlock detected}
|
||||
/// Will be raised when a deadlock is detected when accessing collections.
|
||||
/// - 400: @LIT{bad parameter}
|
||||
/// Will be raised when the HTTP request does not fulfill the requirements.
|
||||
/// - 401: @LIT{unauthorized}
|
||||
|
@ -966,6 +968,16 @@ void TRI_InitializeErrorMessages ();
|
|||
|
||||
#define TRI_ERROR_LOCKED (28)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief 29: ERROR_DEADLOCK
|
||||
///
|
||||
/// deadlock detected
|
||||
///
|
||||
/// Will be raised when a deadlock is detected when accessing collections.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_ERROR_DEADLOCK (29)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief 400: ERROR_HTTP_BAD_PARAMETER
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue