mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/triAGENS/ArangoDB into devel
This commit is contained in:
commit
7042c03020
|
@ -15,6 +15,8 @@ v1.4
|
|||
v1.3.1 (2013-XX-XX)
|
||||
-------------------
|
||||
|
||||
* issue #540: suppress return of temporary internal variables in AQL
|
||||
|
||||
* issue #530: ReferenceError: ArangoError is not a constructor
|
||||
|
||||
* issue #535: Problem with AQL user functions javascript API
|
||||
|
|
|
@ -295,7 +295,8 @@ man: Doxygen/.setup-directories
|
|||
################################################################################
|
||||
|
||||
CLEANUP += \
|
||||
Doxygen/*
|
||||
Doxygen/.setup-directories \
|
||||
Doxygen/*
|
||||
|
||||
## -----------------------------------------------------------------------------
|
||||
## --SECTION-- EXAMPLES
|
||||
|
|
|
@ -209,8 +209,7 @@ Server Statistics {#NewFeatures11ServerStatistics}
|
|||
--------------------------------------------------
|
||||
|
||||
ArangoDB 1.1 allows querying the server status via the administration
|
||||
front-end (see @ref UserManualWebInterfaceStatistics) or via REST API
|
||||
methods.
|
||||
front-end or via REST API methods.
|
||||
|
||||
The following methods are available:
|
||||
- `GET /_admin/connection-statistics`: provides connection statistics
|
||||
|
|
|
@ -7,7 +7,7 @@ ArangoDB's Web-Interface {#UserManualWebInterface}
|
|||
Accessing the Web-Interface {#UserManualWebInterfaceAccess}
|
||||
===========================================================
|
||||
|
||||
The web interfaced can be access as
|
||||
The web interface can be accessed via the URL
|
||||
|
||||
http://localhost:8529
|
||||
|
||||
|
@ -20,64 +20,55 @@ application instead. In this case use
|
|||
Collections Tab {#UserManualWebInterfaceCollections}
|
||||
----------------------------------------------------
|
||||
|
||||
The collection tabs shows an overview about the loaded and unloaded
|
||||
collections of the database.
|
||||
The *Collections* tab shows an overview of the loaded and unloaded
|
||||
collections present in ArangoDB. System collections (i.e. collections
|
||||
whose names start with an underscore) are not shown by default.
|
||||
|
||||
@htmlonly <img src="images/fe-collections.png" alt="ArangoDB Front-End">@endhtmlonly
|
||||
@latexonly\includegraphics[width=12cm]{images/fe-collections.png}@endlatexonly
|
||||
The list of collections can be restricted using the search bar, or by
|
||||
using the filtering at the top. The filter can also be used to show or
|
||||
hide system collections.
|
||||
|
||||
You can load, unloaded, delete, or inspect the collections. Please
|
||||
note that you should not delete or change system collections, i. e.,
|
||||
collections starting with an underscore.
|
||||
Clicking on a collection will show the documents contained in it.
|
||||
Clicking the small icon on a collection's badge will bring up a dialog
|
||||
that allows loading/unloading, renaming and deleting the collection.
|
||||
|
||||
If you click on the magnifying glass, you will get a list of all documents
|
||||
in the collection.
|
||||
Please note that you should not change or delete system collections.
|
||||
|
||||
@htmlonly <img src="images/fe-documents.png" alt="ArangoDB Front-End">@endhtmlonly
|
||||
@latexonly\includegraphics[width=12cm]{images/fe-documents.png}@endlatexonly
|
||||
In the list of documents of a collection, you can click on the *Add document*
|
||||
line to add a new document to the collection. The document will be created
|
||||
instantly, with a system-defined key. The key and all other attributes of the
|
||||
document can be adjusted in the following view.
|
||||
|
||||
Using the pencil you can edit the document.
|
||||
|
||||
Query Tab {#UserManualWebInterfaceQuery}
|
||||
----------------------------------------
|
||||
AQL Editor Tab {#UserManualWebInterfaceQuery}
|
||||
---------------------------------------------
|
||||
|
||||
The query tabs allows you to execute AQL queries.
|
||||
The *AQL Editor* tab allow to execute AQL queries.
|
||||
|
||||
@htmlonly <img src="images/fe-query.png" alt="ArangoDB Front-End">@endhtmlonly
|
||||
@latexonly\includegraphics[width=12cm]{images/fe-query.png}@endlatexonly
|
||||
Type in a query in the bottom box and execute it by pressing the *Submit* button.
|
||||
The query result will be shown in the box at the top.
|
||||
|
||||
Type in a query and execute it.
|
||||
|
||||
Shell Tab {#UserManualWebInterfaceShell}
|
||||
----------------------------------------
|
||||
JS Shell Tab {#UserManualWebInterfaceShell}
|
||||
-------------------------------------------
|
||||
|
||||
The shell tabs give you access to a JavaScript shell connection to the
|
||||
The *JS Shell* tab provides access to a JavaScript shell connection to the
|
||||
database server.
|
||||
|
||||
@htmlonly <img src="images/fe-shell.png" alt="ArangoDB Front-End">@endhtmlonly
|
||||
@latexonly\includegraphics[width=12cm]{images/fe-shell.png}@endlatexonly
|
||||
Any valid JavaScript code can be executed inside the shell. The code will be
|
||||
executed inside your browser. To contact the ArangoDB server, you can use the
|
||||
`db` object, for example as follows:
|
||||
|
||||
JSH> db._create("mycollection");
|
||||
JSH> db.mycollection.save({ _key: "test", value: "something" });
|
||||
|
||||
Use the OK button or return to execute a command.
|
||||
|
||||
Logs Tab {#UserManualWebInterfaceLogs}
|
||||
--------------------------------------
|
||||
|
||||
You can browse the log files.
|
||||
|
||||
@htmlonly <img src="images/fe-logs.png" alt="ArangoDB Front-End">@endhtmlonly
|
||||
@latexonly\includegraphics[width=12cm]{images/fe-logs.png}@endlatexonly
|
||||
You can use the *Logs* tab to browse the most recent log entries provided by the
|
||||
ArangoDB database server.
|
||||
|
||||
Note that the server only keeps a limited number of log entries. For
|
||||
real log analyses write the logs to disk using syslog or a similar
|
||||
mechanism.
|
||||
|
||||
Statistics Tab {#UserManualWebInterfaceStatistics}
|
||||
--------------------------------------------------
|
||||
|
||||
Use the statistics tab to display information about the server.
|
||||
|
||||
@htmlonly <img src="images/fe-statistics.png" alt="ArangoDB Front-End">@endhtmlonly
|
||||
@latexonly\includegraphics[width=12cm]{images/fe-statistics.png}@endlatexonly
|
||||
|
||||
Initially no statistics will be display. You must use the add button
|
||||
to configure what type of information should be displayed.
|
||||
mechanism. ArangoDB provides several startup options for this.
|
||||
|
|
|
@ -6,4 +6,3 @@ TOC {#UserManualWebInterfaceTOC}
|
|||
- @ref UserManualWebInterfaceQuery
|
||||
- @ref UserManualWebInterfaceShell
|
||||
- @ref UserManualWebInterfaceLogs
|
||||
- @ref UserManualWebInterfaceStatistics
|
||||
|
|
|
@ -103,7 +103,7 @@ bool RestActionHandler::isDirect () {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& RestActionHandler::queue () {
|
||||
string const& RestActionHandler::queue () const {
|
||||
return _queue;
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ namespace triagens {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& queue ();
|
||||
string const& queue () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
|
|
|
@ -437,10 +437,13 @@ TRI_aql_node_t* TRI_CreateNodeVariableAql (TRI_aql_context_t* const context,
|
|||
ABORT_OOM
|
||||
}
|
||||
|
||||
if (! TRI_AddVariableScopeAql(context, name, definingNode)) {
|
||||
// duplicate variable name
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_VARIABLE_REDECLARED, name);
|
||||
return NULL;
|
||||
// if not a temporary variable
|
||||
if (*name != '_') {
|
||||
if (! TRI_AddVariableScopeAql(context, name, definingNode)) {
|
||||
// duplicate variable name
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_VARIABLE_REDECLARED, name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_AQL_NODE_STRING(node) = (char*) name;
|
||||
|
|
|
@ -668,7 +668,7 @@ static void InitArray (TRI_aql_codegen_js_t* const generator,
|
|||
static void EnterSymbol (TRI_aql_codegen_js_t* const generator,
|
||||
const char* const name,
|
||||
const TRI_aql_codegen_register_t registerIndex) {
|
||||
TRI_aql_codegen_scope_t* scope = CurrentScope(generator);
|
||||
TRI_aql_codegen_scope_t* scope;
|
||||
TRI_aql_codegen_variable_t* variable = CreateVariable(name, registerIndex);
|
||||
|
||||
if (variable == NULL) {
|
||||
|
@ -676,6 +676,17 @@ static void EnterSymbol (TRI_aql_codegen_js_t* const generator,
|
|||
return;
|
||||
}
|
||||
|
||||
// if not a temporary variable
|
||||
if (*name != '_') {
|
||||
scope = CurrentScope(generator);
|
||||
}
|
||||
else {
|
||||
assert(generator->_scopes._length > 0);
|
||||
|
||||
// get scope at level 0
|
||||
scope = (TRI_aql_codegen_scope_t*) TRI_AtVectorPointer(&generator->_scopes, 0);
|
||||
}
|
||||
|
||||
if (TRI_InsertKeyAssociativePointer(&scope->_variables, name, (void*) variable, false)) {
|
||||
// variable already exists in symbol table. this should never happen
|
||||
LOG_TRACE("variable already registered: %s", name);
|
||||
|
|
|
@ -87,7 +87,7 @@ bool RestBatchHandler::isDirect () {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& RestBatchHandler::queue () {
|
||||
string const& RestBatchHandler::queue () const {
|
||||
static string const client = "STANDARD";
|
||||
|
||||
return client;
|
||||
|
|
|
@ -153,7 +153,7 @@ namespace triagens {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& queue ();
|
||||
string const& queue () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
|
|
|
@ -85,7 +85,7 @@ bool RestDocumentHandler::isDirect () {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& RestDocumentHandler::queue () {
|
||||
string const& RestDocumentHandler::queue () const {
|
||||
static string const client = "STANDARD";
|
||||
|
||||
return client;
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace triagens {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& queue ();
|
||||
string const& queue () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
|
|
|
@ -83,7 +83,7 @@ bool RestImportHandler::isDirect () {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& RestImportHandler::queue () {
|
||||
string const& RestImportHandler::queue () const {
|
||||
static string const client = "STANDARD";
|
||||
|
||||
return client;
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace triagens {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& queue ();
|
||||
string const& queue () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
|
|
|
@ -87,7 +87,7 @@ bool RestUploadHandler::isDirect () {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& RestUploadHandler::queue () {
|
||||
string const& RestUploadHandler::queue () const {
|
||||
static string const client = "STANDARD";
|
||||
|
||||
return client;
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace triagens {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& queue ();
|
||||
string const& queue () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
|
|
|
@ -527,7 +527,7 @@ void ApplicationV8::setupOptions (map<string, basics::ProgramOptionsDescription>
|
|||
("javascript.gc-frequency", &_gcFrequency, "JavaScript time-based garbage collection frequency (each x seconds)")
|
||||
("javascript.action-directory", &_actionPath, "path to the JavaScript action directory")
|
||||
("javascript.app-path", &_appPath, "one directory for applications")
|
||||
("javascript.dev-app-path", &_devAppPath, "one directory for dev aaplications")
|
||||
("javascript.dev-app-path", &_devAppPath, "one directory for dev applications")
|
||||
("javascript.modules-path", &_modulesPath, "one or more directories separated by semi-colons")
|
||||
("javascript.package-path", &_packagePath, "one or more directories separated by semi-colons")
|
||||
("javascript.startup-directory", &_startupPath, "path to the directory containing alternate JavaScript startup scripts")
|
||||
|
|
|
@ -235,18 +235,14 @@ static void MoveHeader (TRI_headers_t* h,
|
|||
headers->_begin = header;
|
||||
}
|
||||
else if (headers->_begin == header) {
|
||||
if (header->_next != NULL) {
|
||||
headers->_begin = header->_next;
|
||||
}
|
||||
headers->_begin = header->_next;
|
||||
}
|
||||
|
||||
if (old->_next == NULL) {
|
||||
headers->_end = header;
|
||||
}
|
||||
else if (headers->_end == header) {
|
||||
if (header->_prev != NULL) {
|
||||
headers->_end = header->_prev;
|
||||
}
|
||||
headers->_end = header->_prev;
|
||||
}
|
||||
|
||||
if (header->_prev != NULL) {
|
||||
|
|
|
@ -215,96 +215,6 @@ static bool EqualKeyCollectionName (TRI_associative_pointer_t* array, void const
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a JSON array with collection meta data
|
||||
///
|
||||
/// this function is called when a collection is created or dropped
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_json_t* CreateJsonCollectionInfo (TRI_vocbase_col_t const* collection,
|
||||
const char* situation) {
|
||||
TRI_json_t* json;
|
||||
TRI_json_t* details;
|
||||
char* cidString;
|
||||
|
||||
details = TRI_CreateArrayJson(TRI_CORE_MEM_ZONE);
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, details, "type", TRI_CreateStringCopyJson(TRI_CORE_MEM_ZONE, TRI_TypeNameCollection(collection->_type)));
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, details, "name", TRI_CreateStringCopyJson(TRI_CORE_MEM_ZONE, collection->_name));
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, details, "action", TRI_CreateStringCopyJson(TRI_CORE_MEM_ZONE, situation));
|
||||
|
||||
cidString = TRI_StringUInt64((uint64_t) collection->_cid);
|
||||
|
||||
json = TRI_CreateArrayJson(TRI_CORE_MEM_ZONE);
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, json, "id", TRI_CreateStringCopyJson(TRI_CORE_MEM_ZONE, cidString));
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, json, "type", TRI_CreateStringCopyJson(TRI_CORE_MEM_ZONE, "collection"));
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, json, "details", details);
|
||||
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, cidString);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief insert the id of a collection into the "_ids" collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int InsertIdCallback (TRI_transaction_collection_t* trxCollection,
|
||||
void* data) {
|
||||
TRI_shaped_json_t* shaped;
|
||||
TRI_primary_collection_t* primary;
|
||||
TRI_json_t* json;
|
||||
TRI_doc_mptr_t mptr;
|
||||
int res;
|
||||
|
||||
primary = (TRI_primary_collection_t*) trxCollection->_collection->_collection;
|
||||
json = data;
|
||||
|
||||
shaped = TRI_ShapedJsonJson(primary->_shaper, json);
|
||||
|
||||
if (shaped == NULL) {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
res = primary->insert(trxCollection, NULL, &mptr, TRI_DOC_MARKER_KEY_DOCUMENT, shaped, NULL, false, false);
|
||||
TRI_FreeShapedJson(primary->_shaper, shaped);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief save collection info on create or drop
|
||||
///
|
||||
/// the info will be stored permanently in the "_ids" collection, so we can
|
||||
/// later reconstruct ids of collections that are/were dropped
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool WriteCollectionInfo (TRI_vocbase_t* vocbase,
|
||||
TRI_vocbase_col_t const* collection,
|
||||
const char* situation) {
|
||||
TRI_json_t* json;
|
||||
int res;
|
||||
|
||||
if (collection == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
json = CreateJsonCollectionInfo(collection, situation);
|
||||
|
||||
if (json == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
res = TRI_ExecuteSingleOperationTransaction(vocbase,
|
||||
"_ids",
|
||||
TRI_TRANSACTION_WRITE,
|
||||
InsertIdCallback,
|
||||
json);
|
||||
|
||||
TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
|
||||
|
||||
return (res == TRI_ERROR_NO_ERROR);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the current tick value, without using a lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -456,8 +366,6 @@ static void FreeCollection (TRI_vocbase_t* vocbase, TRI_vocbase_col_t* collectio
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool UnregisterCollection (TRI_vocbase_t* vocbase, TRI_vocbase_col_t* collection) {
|
||||
WriteCollectionInfo(vocbase, collection, "drop");
|
||||
|
||||
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, collection->_name);
|
||||
|
|
|
@ -12,21 +12,36 @@
|
|||
}
|
||||
*/
|
||||
|
||||
.dbNotVisible {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
#dashboardHeader .btn-group {
|
||||
margin-left: 10px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.db-zoom, .db-minimize, .db-hide, .db-info {
|
||||
.group-close, .group-open {
|
||||
float:right;
|
||||
margin-top: 17px !important;
|
||||
margin-right: 7px !important;
|
||||
}
|
||||
|
||||
.db-zoom, .db-minimize, .db-hide, .db-info, #db-collectionMinimize {
|
||||
float: right;
|
||||
margin-top: -4px !important;
|
||||
margin-right: 4px !important;
|
||||
}
|
||||
|
||||
.db-zoom:hover, .db-minimize:hover, .db-hide, .db-info:hover {
|
||||
.db-zoom:hover, .db-minimize:hover, .db-hide, .db-info:hover, .group-close:hover, .group-open:hover,
|
||||
#db-collectionMinimize:hover {
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.groupHidden li {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.statGroups {
|
||||
margin-left: 0px;
|
||||
float:left;
|
||||
|
@ -66,36 +81,49 @@
|
|||
|
||||
.statClient {
|
||||
float: left;
|
||||
height: 150px;
|
||||
width: 280px;
|
||||
height: 120px;
|
||||
width: 203px;
|
||||
margin-left: 9px;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid black;
|
||||
border-radius: 2px 2px 2px 2px;
|
||||
background-color: #F4F3F3;
|
||||
box-shadow: 0 0 3px #333333;
|
||||
}
|
||||
|
||||
.statChart {
|
||||
#detailGraphChart {
|
||||
margin-left: -10px !important;
|
||||
}
|
||||
|
||||
.statGroups .statChart {
|
||||
margin-left: -45px !important;
|
||||
}
|
||||
|
||||
.nv-axislabel {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.nv-axisMaxMin > text {
|
||||
font: 10px sans-serif;
|
||||
}
|
||||
|
||||
.svgCollections {
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.svgClass {
|
||||
margin-top: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
height: 150px;
|
||||
width: 270px;
|
||||
height: 140px;
|
||||
width: 255px;
|
||||
}
|
||||
|
||||
.svgDetailClass {
|
||||
margin-top: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
height: 300px;
|
||||
width: 877px;
|
||||
width: 887px;
|
||||
}
|
||||
|
||||
.boxHeader {
|
||||
|
@ -110,6 +138,7 @@
|
|||
}
|
||||
|
||||
.statsHeader {
|
||||
margin-top: 12px;
|
||||
margin-left: -10px;
|
||||
width: 940px;
|
||||
background-color: #686766;
|
||||
|
@ -143,3 +172,83 @@
|
|||
.nv-point {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*Dashboard Dropdown*/
|
||||
|
||||
.dropdown-menu li > a {
|
||||
padding: 0px 20px !important;
|
||||
}
|
||||
|
||||
.checkboxLabel {
|
||||
margin-top: 4px;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.svgClass .nv-axisMaxMin text {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.svgClass .major text {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.svgClass .nv-axislabel {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/*Dashboard Checkbox*/
|
||||
input[type=checkbox].css-checkbox {
|
||||
display:none;
|
||||
}
|
||||
|
||||
input[type=checkbox].css-checkbox + label.css-label {
|
||||
padding-left:20px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: -0px;
|
||||
height:15px;
|
||||
display:inline-block;
|
||||
line-height:15px;
|
||||
background-repeat:no-repeat;
|
||||
background-position: 0 0;
|
||||
font-size:15px;
|
||||
vertical-align:middle;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
input[type=checkbox].css-checkbox:checked + label.css-label {
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.css-label {
|
||||
background-image:url(../img/dark-check-green.png);
|
||||
}
|
||||
|
||||
/*Dashboard Radio */
|
||||
|
||||
.dropdown-menu .radio {
|
||||
margin-left: -21px;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
display:none;
|
||||
}
|
||||
|
||||
input[type="radio"] + label {
|
||||
/*color:#f2f2f2;*/
|
||||
/*font-family:Arial, sans-serif;
|
||||
font-size:14px;*/
|
||||
}
|
||||
|
||||
input[type="radio"] + label span {
|
||||
display:inline-block;
|
||||
width:19px;
|
||||
height:19px;
|
||||
margin:-1px 4px 0 0;
|
||||
vertical-align:middle;
|
||||
background:url(../img/check_radio_sheet.png) -38px top no-repeat;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
input[type="radio"]:checked + label span {
|
||||
background:url(../img/check_radio_sheet.png) -57px top no-repeat;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
|
@ -110,6 +110,7 @@
|
|||
<script src="js/graphViewer/graph/edgeShaper.js"></script>
|
||||
<script src="js/graphViewer/graph/arangoAdapter.js"></script>
|
||||
<script src="js/graphViewer/graph/zoomManager.js"></script>
|
||||
<script src="js/graphViewer/graph/nodeReducer.js"></script>
|
||||
|
||||
<script type="text/javascript" src="js/graphViewer/ui/modalDialogHelper.js"></script>
|
||||
<script type="text/javascript" src="js/graphViewer/ui/nodeShaperControls.js"></script>
|
||||
|
|
|
@ -17,6 +17,9 @@ window.arangoCollections = Backbone.Collection.extend({
|
|||
},
|
||||
|
||||
translateStatus : function (status) {
|
||||
if (status == 0) {
|
||||
return 'corrupted';
|
||||
}
|
||||
if (status == 1) {
|
||||
return 'new born collection';
|
||||
}
|
||||
|
|
|
@ -79,6 +79,9 @@ function JSONAdapter(jsonPath, nodes, edges, width, height) {
|
|||
return this.start + Math.random() * this.range;
|
||||
};
|
||||
|
||||
self.loadNode = function(nodeId, callback) {
|
||||
self.loadNodeFromTreeById(nodeId, callback);
|
||||
};
|
||||
|
||||
self.loadNodeFromTreeById = function(nodeId, callback) {
|
||||
var json = jsonPath + nodeId + ".json";
|
||||
|
@ -159,4 +162,8 @@ function JSONAdapter(jsonPath, nodes, edges, width, height) {
|
|||
|
||||
};
|
||||
|
||||
self.expandCommunity = function (commNode, callback) {
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -53,6 +53,7 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
api = {},
|
||||
queries = {},
|
||||
cachedCommunities = {},
|
||||
joinedInCommunities = {},
|
||||
nodeCollection,
|
||||
edgeCollection,
|
||||
limit,
|
||||
|
@ -60,6 +61,7 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
arangodb,
|
||||
width,
|
||||
height,
|
||||
direction,
|
||||
|
||||
setWidth = function(w) {
|
||||
initialX.range = w / 2;
|
||||
|
@ -93,12 +95,22 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
if (config.height !== undefined) {
|
||||
setHeight(config.height);
|
||||
}
|
||||
if (config.undirected !== undefined) {
|
||||
if (config.undirected === true) {
|
||||
direction = "any";
|
||||
} else {
|
||||
direction = "outbound";
|
||||
}
|
||||
} else {
|
||||
direction = "outbound";
|
||||
}
|
||||
},
|
||||
|
||||
findNode = function(id) {
|
||||
var res = $.grep(nodes, function(e){
|
||||
return e._id === id;
|
||||
});
|
||||
var intId = joinedInCommunities[id] || id,
|
||||
res = $.grep(nodes, function(e){
|
||||
return e._id === intId;
|
||||
});
|
||||
if (res.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -118,7 +130,7 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
if (res.length === 1) {
|
||||
return res[0];
|
||||
}
|
||||
throw "Too many nodes with the same ID, should never happen";
|
||||
throw "Too many edges with the same ID, should never happen";
|
||||
},
|
||||
|
||||
insertNode = function(data) {
|
||||
|
@ -145,7 +157,8 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
_data: data,
|
||||
_id: data._id
|
||||
},
|
||||
e = findEdge(edge._id);
|
||||
e = findEdge(edge._id),
|
||||
edgeToPush;
|
||||
if (e) {
|
||||
return e;
|
||||
}
|
||||
|
@ -160,8 +173,32 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
edge.source = source;
|
||||
edge.target = target;
|
||||
edges.push(edge);
|
||||
source._outboundCounter++;
|
||||
target._inboundCounter++;
|
||||
|
||||
|
||||
if (cachedCommunities[source._id] !== undefined) {
|
||||
edgeToPush = {};
|
||||
edgeToPush.type = "s";
|
||||
edgeToPush.id = edge._id;
|
||||
edgeToPush.source = $.grep(cachedCommunities[source._id].nodes, function(e){
|
||||
return e._id === data._from;
|
||||
})[0];
|
||||
edgeToPush.source._outboundCounter++;
|
||||
cachedCommunities[source._id].edges.push(edgeToPush);
|
||||
} else {
|
||||
source._outboundCounter++;
|
||||
}
|
||||
if (cachedCommunities[target._id] !== undefined) {
|
||||
edgeToPush = {};
|
||||
edgeToPush.type = "t";
|
||||
edgeToPush.id = edge._id;
|
||||
edgeToPush.target = $.grep(cachedCommunities[target._id].nodes, function(e){
|
||||
return e._id === data._to;
|
||||
})[0];
|
||||
edgeToPush.target._inboundCounter++;
|
||||
cachedCommunities[target._id].edges.push(edgeToPush);
|
||||
} else {
|
||||
target._inboundCounter++;
|
||||
}
|
||||
return edge;
|
||||
},
|
||||
|
||||
|
@ -187,7 +224,7 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
|
||||
removeEdgesForNode = function (node) {
|
||||
var i;
|
||||
for ( i = 0; i < edges.length; i++ ) {
|
||||
for (i = 0; i < edges.length; i++ ) {
|
||||
if (edges[i].source === node) {
|
||||
node._outboundCounter--;
|
||||
edges[i].target._inboundCounter--;
|
||||
|
@ -202,6 +239,53 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
}
|
||||
},
|
||||
|
||||
combineCommunityEdges = function (nodes, commNode) {
|
||||
var i, j, s, t,
|
||||
cachedCommEdges = cachedCommunities[commNode._id].edges,
|
||||
edgeToPush;
|
||||
for (i = 0; i < edges.length; i++ ) {
|
||||
edgeToPush = {};
|
||||
// s and t keep old values yay!
|
||||
s = edges[i].source;
|
||||
t = edges[i].target;
|
||||
for (j = 0; j < nodes.length; j++) {
|
||||
if (s === nodes[j]) {
|
||||
if (edgeToPush.type !== undefined) {
|
||||
edges[i].target = edgeToPush.target;
|
||||
delete edgeToPush.target;
|
||||
edgeToPush.type = "b";
|
||||
edgeToPush.edge = edges[i];
|
||||
edges.splice( i, 1 );
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
edges[i].source = commNode;
|
||||
edgeToPush.type = "s";
|
||||
edgeToPush.id = edges[i]._id;
|
||||
edgeToPush.source = s;
|
||||
}
|
||||
if (t === nodes[j]) {
|
||||
if (edgeToPush.type !== undefined) {
|
||||
edges[i].source = edgeToPush.source;
|
||||
delete edgeToPush.source;
|
||||
edgeToPush.type = "b";
|
||||
edgeToPush.edge = edges[i];
|
||||
edges.splice( i, 1 );
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
edges[i].target = commNode;
|
||||
edgeToPush.type = "t";
|
||||
edgeToPush.id = edges[i]._id;
|
||||
edgeToPush.target = t;
|
||||
}
|
||||
}
|
||||
if (edgeToPush.type !== undefined) {
|
||||
cachedCommEdges.push(edgeToPush);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Helper function to easily remove all outbound edges for one node
|
||||
removeOutboundEdgesFromNode = function ( node ) {
|
||||
if (node._outboundCounter > 0) {
|
||||
|
@ -228,6 +312,9 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
if (query !== queries.connectedEdges) {
|
||||
bindVars["@nodes"] = nodeCollection;
|
||||
}
|
||||
if (query !== queries.childrenCentrality) {
|
||||
bindVars["@dir"] = direction;
|
||||
}
|
||||
bindVars["@edges"] = edgeCollection;
|
||||
var data = {
|
||||
query: query,
|
||||
|
@ -257,24 +344,61 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
},
|
||||
|
||||
collapseCommunity = function (community) {
|
||||
var commId = "community_1",
|
||||
var commId = "*community_" + Math.floor(Math.random()* 1000000),
|
||||
commNode = {
|
||||
_id: commId,
|
||||
x: 1,
|
||||
y: 1
|
||||
edges: []
|
||||
},
|
||||
nodesToRemove = _.map(community, function(id) {
|
||||
return findNode(id);
|
||||
});
|
||||
cachedCommunities[commId] = nodesToRemove;
|
||||
commNode.x = nodesToRemove[0].x;
|
||||
commNode.y = nodesToRemove[0].y;
|
||||
cachedCommunities[commId] = {};
|
||||
cachedCommunities[commId].nodes = nodesToRemove;
|
||||
cachedCommunities[commId].edges = [];
|
||||
|
||||
combineCommunityEdges(nodesToRemove, commNode);
|
||||
_.each(nodesToRemove, function(n) {
|
||||
joinedInCommunities[n._id] = commId;
|
||||
removeNode(n);
|
||||
removeEdgesForNode(n);
|
||||
});
|
||||
nodes.push(commNode);
|
||||
},
|
||||
|
||||
expandCommunity = function (commNode) {
|
||||
var commId = commNode._id,
|
||||
nodesToAdd = cachedCommunities[commId].nodes,
|
||||
edgesToChange = cachedCommunities[commId].edges,
|
||||
com;
|
||||
removeNode(commNode);
|
||||
if (limit < nodes.length + nodesToAdd.length) {
|
||||
com = reducer.getCommunity(limit);
|
||||
collapseCommunity(com);
|
||||
}
|
||||
_.each(nodesToAdd, function(n) {
|
||||
delete joinedInCommunities[n._id];
|
||||
nodes.push(n);
|
||||
});
|
||||
_.each(edgesToChange, function(e) {
|
||||
var edge;
|
||||
switch(e.type) {
|
||||
case "t":
|
||||
edge = findEdge(e.id);
|
||||
edge.target = e.target;
|
||||
break;
|
||||
case "s":
|
||||
edge = findEdge(e.id);
|
||||
edge.source = e.source;
|
||||
break;
|
||||
case "b":
|
||||
edges.push(e.edge);
|
||||
break;
|
||||
}
|
||||
});
|
||||
delete cachedCommunities[commId];
|
||||
},
|
||||
|
||||
parseResultOfTraversal = function (result, callback) {
|
||||
result = result[0];
|
||||
_.each(result, function(visited) {
|
||||
|
@ -366,7 +490,7 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
+ "@@nodes, "
|
||||
+ "@@edges, "
|
||||
+ "@id, "
|
||||
+ "\"outbound\", {"
|
||||
+ "@dir, {"
|
||||
+ "strategy: \"depthfirst\","
|
||||
+ "maxDepth: 1,"
|
||||
+ "paths: true"
|
||||
|
@ -379,7 +503,7 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
+ "@@nodes, "
|
||||
+ "@@edges, "
|
||||
+ "n._id, "
|
||||
+ "\"outbound\", {"
|
||||
+ "@dir, {"
|
||||
+ "strategy: \"depthfirst\","
|
||||
+ "maxDepth: 1,"
|
||||
+ "paths: true"
|
||||
|
@ -399,7 +523,6 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
|
||||
reducer = new NodeReducer(nodes, edges);
|
||||
|
||||
|
||||
self.oldLoadNodeFromTreeById = function(nodeId, callback) {
|
||||
sendQuery(queries.nodeById, {
|
||||
id: nodeId
|
||||
|
@ -408,6 +531,10 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
});
|
||||
};
|
||||
|
||||
self.loadNode = function(nodeId, callback) {
|
||||
self.loadNodeFromTreeById(nodeId, callback);
|
||||
};
|
||||
|
||||
self.loadNodeFromTreeById = function(nodeId, callback) {
|
||||
sendQuery(queries.traversalById, {
|
||||
id: nodeId
|
||||
|
@ -554,9 +681,16 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
});
|
||||
};
|
||||
|
||||
self.changeTo = function (nodesCol, edgesCol ) {
|
||||
self.changeTo = function (nodesCol, edgesCol, dir) {
|
||||
nodeCollection = nodesCol;
|
||||
edgeCollection = edgesCol;
|
||||
if (dir !== undefined) {
|
||||
if (dir === true) {
|
||||
direction = "any";
|
||||
} else {
|
||||
direction = "outbound";
|
||||
}
|
||||
}
|
||||
api.node = api.base + "document?collection=" + nodeCollection;
|
||||
api.edge = api.base + "edge?collection=" + edgeCollection;
|
||||
};
|
||||
|
@ -572,4 +706,11 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
}
|
||||
};
|
||||
|
||||
self.expandCommunity = function (commNode, callback) {
|
||||
expandCommunity(commNode);
|
||||
if (callback !== undefined) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -67,8 +67,8 @@ function EventLibrary() {
|
|||
if (config.startCallback === undefined) {
|
||||
throw "A callback to the Start-method has to be defined";
|
||||
}
|
||||
if (config.loadNode === undefined) {
|
||||
throw "A callback to load a node has to be defined";
|
||||
if (config.adapter === undefined) {
|
||||
throw "An adapter to load data has to be defined";
|
||||
}
|
||||
if (config.reshapeNodes === undefined) {
|
||||
throw "A callback to reshape nodes has to be defined";
|
||||
|
@ -81,7 +81,9 @@ function EventLibrary() {
|
|||
var edges = config.edges,
|
||||
nodes = config.nodes,
|
||||
startCallback = config.startCallback,
|
||||
loadNode = config.loadNode,
|
||||
adapter = config.adapter,
|
||||
loadNode = adapter.loadNode,
|
||||
expandCom = adapter.expandCommunity,
|
||||
reshapeNodes = config.reshapeNodes,
|
||||
removeNode = function (node) {
|
||||
var i;
|
||||
|
@ -126,8 +128,12 @@ function EventLibrary() {
|
|||
},
|
||||
|
||||
expandNode = function(n) {
|
||||
n._expanded = true;
|
||||
loadNode(n._id, startCallback);
|
||||
if (/^\*community/.test(n._id)) {
|
||||
expandCom(n, startCallback);
|
||||
} else {
|
||||
n._expanded = true;
|
||||
loadNode(n._id, startCallback);
|
||||
}
|
||||
};
|
||||
|
||||
return function(n) {
|
||||
|
|
|
@ -148,7 +148,7 @@ function NodeReducer(nodes, edges) {
|
|||
_.each(nodes, function (n) {
|
||||
var id = n._id,
|
||||
c1, c2;
|
||||
if (id == sID || id == lID) {
|
||||
if (id === sID || id === lID) {
|
||||
return null;
|
||||
}
|
||||
c1 = getDQValue(dQ, id, sID);
|
||||
|
@ -277,6 +277,7 @@ function NodeReducer(nodes, edges) {
|
|||
res = [],
|
||||
dist = {},
|
||||
dist2 = {},
|
||||
detectSteps = true,
|
||||
sortByDistance = function (a, b) {
|
||||
var d1 = dist[_.min(a,minDist(dist))],
|
||||
d2 = dist[_.min(b,minDist(dist))],
|
||||
|
@ -290,7 +291,9 @@ function NodeReducer(nodes, edges) {
|
|||
throw "Load some nodes first.";
|
||||
}
|
||||
populateValues(dQ, a, heap);
|
||||
while (communityDetectionStep(dQ, a, heap, coms)) {}
|
||||
while (detectSteps) {
|
||||
detectSteps = communityDetectionStep(dQ, a, heap, coms);
|
||||
}
|
||||
res = _.pluck(_.values(coms), "com");
|
||||
if (focus !== undefined) {
|
||||
dist = floatDist(focus._id);
|
||||
|
|
|
@ -64,6 +64,7 @@ function NodeShaper(parent, flags, idfunc) {
|
|||
"use strict";
|
||||
|
||||
var self = this,
|
||||
communityRegEx = /^\*community/,
|
||||
nodes = [],
|
||||
visibleLabels = true,
|
||||
noop = function (node) {
|
||||
|
@ -91,7 +92,17 @@ function NodeShaper(parent, flags, idfunc) {
|
|||
addColor = noop,
|
||||
addShape = noop,
|
||||
addLabel = noop,
|
||||
|
||||
addCommunityShape = function(g) {
|
||||
g.append("polygon")
|
||||
.attr("points", "0,-25 -16,20 23,-10 -23,-10 16,20");
|
||||
},
|
||||
addCommunityLabel = function(g) {
|
||||
g.append("text") // Append a label for the node
|
||||
.attr("text-anchor", "middle") // Define text-anchor
|
||||
.text(function(d) {
|
||||
return d._size;
|
||||
});
|
||||
},
|
||||
unbindEvents = function() {
|
||||
// Hard unbind the dragging
|
||||
self.parent
|
||||
|
@ -120,9 +131,18 @@ function NodeShaper(parent, flags, idfunc) {
|
|||
},
|
||||
|
||||
addQue = function (g) {
|
||||
addShape(g);
|
||||
var community = g.filter(function(n) {
|
||||
return communityRegEx.test(n._id);
|
||||
}),
|
||||
normal = g.filter(function(n) {
|
||||
return !communityRegEx.test(n._id);
|
||||
});
|
||||
addCommunityShape(community);
|
||||
addShape(normal);
|
||||
|
||||
if (visibleLabels) {
|
||||
addLabel(g);
|
||||
addCommunityLabel(community);
|
||||
addLabel(normal);
|
||||
}
|
||||
addColor(g);
|
||||
addEvents(g);
|
||||
|
@ -158,7 +178,12 @@ function NodeShaper(parent, flags, idfunc) {
|
|||
// Append the group and class to all new
|
||||
g.enter()
|
||||
.append("g")
|
||||
.attr("class", "node") // node is CSS class that might be edited
|
||||
.attr("class", function(d) {
|
||||
if (communityRegEx.test(d._id)) {
|
||||
return "node communitynode";
|
||||
}
|
||||
return "node";
|
||||
}) // node is CSS class that might be edited
|
||||
.attr("id", idFunction);
|
||||
// Remove all old
|
||||
g.exit().remove();
|
||||
|
@ -176,7 +201,8 @@ function NodeShaper(parent, flags, idfunc) {
|
|||
case NodeShaper.shapes.CIRCLE:
|
||||
radius = shape.radius || 25;
|
||||
addShape = function (node) {
|
||||
node.append("circle") // Display nodes as circles
|
||||
node
|
||||
.append("circle") // Display nodes as circles
|
||||
.attr("r", radius); // Set radius
|
||||
};
|
||||
break;
|
||||
|
|
|
@ -85,7 +85,7 @@ function GraphViewer(svg, width, height, adapterConfig, config) {
|
|||
},
|
||||
|
||||
nodeLimitCallBack = function(limit) {
|
||||
self.adapter.setNodeLimit(limit);
|
||||
self.adapter.setNodeLimit(limit, self.start);
|
||||
},
|
||||
|
||||
parseZoomConfig = function(config) {
|
||||
|
@ -174,7 +174,7 @@ function GraphViewer(svg, width, height, adapterConfig, config) {
|
|||
edges: edges,
|
||||
nodes: nodes,
|
||||
startCallback: self.start,
|
||||
loadNode: self.adapter.loadNodeFromTreeById,
|
||||
adapter: self.adapter,
|
||||
reshapeNodes: self.nodeShaper.reshapeNodes
|
||||
},
|
||||
drag: {
|
||||
|
|
|
@ -43,7 +43,9 @@ var mocks = mocks || {};
|
|||
patchNode: function(){},
|
||||
createEdge: function(){},
|
||||
deleteEdge: function(){},
|
||||
patchEdge: function(){}
|
||||
patchEdge: function(){},
|
||||
loadNode: function(){},
|
||||
expandCommunity: function(){}
|
||||
};
|
||||
|
||||
}());
|
|
@ -58,6 +58,17 @@
|
|||
checkCallbackFunction = function() {
|
||||
callbackCheck = true;
|
||||
},
|
||||
|
||||
getCommunityNodes = function() {
|
||||
return _.filter(nodes, function(n) {
|
||||
return n._id.match(/^\*community/);
|
||||
});
|
||||
},
|
||||
|
||||
getCommunityNodesIds = function() {
|
||||
return _.pluck(getCommunityNodes(), "_id");
|
||||
},
|
||||
|
||||
nodeWithID = function(id) {
|
||||
return $.grep(nodes, function(e){
|
||||
return e._id === id;
|
||||
|
@ -295,26 +306,40 @@
|
|||
height: 40
|
||||
}
|
||||
);
|
||||
traversalQuery = function(id, nods, edgs) {
|
||||
traversalQuery = function(id, nods, edgs, undirected) {
|
||||
var dir;
|
||||
if (undirected === true) {
|
||||
dir = "any";
|
||||
} else {
|
||||
dir = "outbound";
|
||||
}
|
||||
return JSON.stringify({
|
||||
query: "RETURN TRAVERSAL(@@nodes, @@edges, @id, \"outbound\","
|
||||
query: "RETURN TRAVERSAL(@@nodes, @@edges, @id, @dir,"
|
||||
+ " {strategy: \"depthfirst\",maxDepth: 1,paths: true})",
|
||||
bindVars: {
|
||||
id: id,
|
||||
"@nodes": nods,
|
||||
"@dir": dir,
|
||||
"@edges": edgs
|
||||
}
|
||||
});
|
||||
};
|
||||
filterQuery = function(v, nods, edgs) {
|
||||
filterQuery = function(v, nods, edgs, undirected) {
|
||||
var dir;
|
||||
if (undirected === true) {
|
||||
dir = "any";
|
||||
} else {
|
||||
dir = "outbound";
|
||||
}
|
||||
return JSON.stringify({
|
||||
query: "FOR n IN @@nodes FILTER n.id == @value"
|
||||
+ " RETURN TRAVERSAL(@@nodes, @@edges, n._id, \"outbound\","
|
||||
+ " RETURN TRAVERSAL(@@nodes, @@edges, n._id, @dir,"
|
||||
+ " {strategy: \"depthfirst\",maxDepth: 1,paths: true})",
|
||||
bindVars: {
|
||||
value: v,
|
||||
"@nodes": nods,
|
||||
"@edges": edgs
|
||||
"@dir": dir,
|
||||
"@edges": edgs
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -455,6 +480,12 @@
|
|||
});
|
||||
});
|
||||
|
||||
it('should map loadNode to loadByID', function() {
|
||||
spyOn(adapter, "loadNodeFromTreeById");
|
||||
adapter.loadNode("a", "b");
|
||||
expect(adapter.loadNodeFromTreeById).toHaveBeenCalledWith("a", "b");
|
||||
});
|
||||
|
||||
it('should be able to load a tree node from ArangoDB'
|
||||
+ ' by internal attribute and value', function() {
|
||||
|
||||
|
@ -638,6 +669,40 @@
|
|||
|
||||
});
|
||||
|
||||
it('should be able to switch to different collections and change to directed', function() {
|
||||
|
||||
runs(function() {
|
||||
|
||||
spyOn($, "ajax");
|
||||
|
||||
adapter.changeTo(altNodesCollection, altEdgesCollection, false);
|
||||
|
||||
adapter.loadNode("42");
|
||||
|
||||
expect($.ajax).toHaveBeenCalledWith(
|
||||
requests.cursor(traversalQuery("42", altNodesCollection, altEdgesCollection, false))
|
||||
);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to switch to different collections'
|
||||
+ ' and change to undirected', function() {
|
||||
|
||||
runs(function() {
|
||||
|
||||
spyOn($, "ajax");
|
||||
|
||||
adapter.changeTo(altNodesCollection, altEdgesCollection, true);
|
||||
|
||||
adapter.loadNode("42");
|
||||
|
||||
expect($.ajax).toHaveBeenCalledWith(
|
||||
requests.cursor(traversalQuery("42", altNodesCollection, altEdgesCollection, true))
|
||||
);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('that has already loaded one graph', function() {
|
||||
var c0, c1, c2, c3, c4, c5, c6, c7,
|
||||
|
@ -877,46 +942,58 @@
|
|||
|
||||
runs(function() {
|
||||
adapter.setNodeLimit(6);
|
||||
spyOn(this, "fakeReducerRequest");
|
||||
spyOn(this, "fakeReducerRequest").andCallFake(function() {
|
||||
return [c0];
|
||||
});
|
||||
adapter.loadNodeFromTreeById(c1, checkCallbackFunction);
|
||||
expect(this.fakeReducerRequest).toHaveBeenCalledWith(6, nodeWithID(c1));
|
||||
});
|
||||
});
|
||||
|
||||
it('should not trigger the reducer if the limit is set large enough', function() {
|
||||
spyOn(this, "fakeReducerRequest");
|
||||
adapter.setNodeLimit(10);
|
||||
expect(this.fakeReducerRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should trigger the reducer if the limit is set too small', function() {
|
||||
spyOn(this, "fakeReducerRequest");
|
||||
adapter.setNodeLimit(2);
|
||||
expect(this.fakeReducerRequest).toHaveBeenCalledWith(2);
|
||||
});
|
||||
|
||||
|
||||
describe('checking community nodes', function() {
|
||||
|
||||
it('should create a community node if limit is set too small', function() {
|
||||
var called = false,
|
||||
callback = function() {
|
||||
called = true;
|
||||
};
|
||||
it('should not trigger the reducer if the limit is set large enough', function() {
|
||||
spyOn(this, "fakeReducerRequest").andCallFake(function() {
|
||||
return [c0, c1, c2];
|
||||
return [c0];
|
||||
});
|
||||
adapter.setNodeLimit(2, callback);
|
||||
adapter.setNodeLimit(10);
|
||||
expect(this.fakeReducerRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trigger the reducer if the limit is set too small', function() {
|
||||
spyOn(this, "fakeReducerRequest").andCallFake(function() {
|
||||
return [c0];
|
||||
});
|
||||
adapter.setNodeLimit(2);
|
||||
expect(this.fakeReducerRequest).toHaveBeenCalledWith(2);
|
||||
});
|
||||
|
||||
notExistNodes([c0, c1, c2]);
|
||||
existNode("community_1");
|
||||
existNodes([c3]);
|
||||
expect(nodes.length).toEqual(2);
|
||||
existEdge("community_1", c3);
|
||||
expect(edges.length).toEqual(1);
|
||||
|
||||
expect(called).toBeTruthy();
|
||||
it('should create a community node if limit is set too small', function() {
|
||||
var called;
|
||||
|
||||
runs(function() {
|
||||
callbackCheck = false;
|
||||
spyOn(this, "fakeReducerRequest").andCallFake(function() {
|
||||
return [c0, c1, c2];
|
||||
});
|
||||
adapter.setNodeLimit(2, checkCallbackFunction);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return callbackCheck;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
var commId = getCommunityNodesIds()[0];
|
||||
notExistNodes([c0, c1, c2]);
|
||||
existNode(commId);
|
||||
existNodes([c3, c4]);
|
||||
expect(nodes.length).toEqual(3);
|
||||
existEdge(commId, c3);
|
||||
existEdge(commId, c4);
|
||||
expect(edges.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a community node if too many nodes are added', function() {
|
||||
|
@ -933,20 +1010,312 @@
|
|||
});
|
||||
|
||||
runs(function() {
|
||||
var commId = getCommunityNodesIds()[0];
|
||||
notExistNodes([c0, c1, c2, c3]);
|
||||
existNode("community_1");
|
||||
existNode(commId);
|
||||
existNodes([c4, c5, c6, c7]);
|
||||
expect(nodes.length).toEqual(5);
|
||||
|
||||
existEdge("community_1", c4);
|
||||
existEdge("community_1", c5);
|
||||
existEdge("community_1", c6);
|
||||
existEdge("community_1", c7);
|
||||
existEdge(commId, c4);
|
||||
existEdge(commId, c5);
|
||||
existEdge(commId, c6);
|
||||
existEdge(commId, c7);
|
||||
expect(edges.length).toEqual(4);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('expanding after a while', function() {
|
||||
|
||||
it('should connect edges of internal nodes accordingly', function() {
|
||||
|
||||
var commNode, called, counterCallback,
|
||||
v0, v1, v2, v3, v4,
|
||||
e0_1, e0_2, e1_3, e1_4, e2_3, e2_4;
|
||||
|
||||
runs(function() {
|
||||
var v = "vertices",
|
||||
e = "edges";
|
||||
nodes.length = 0;
|
||||
edges.length = 0;
|
||||
v0 = insertNode(v, 0);
|
||||
v1 = insertNode(v, 1);
|
||||
v2 = insertNode(v, 2);
|
||||
v3 = insertNode(v, 3);
|
||||
v4 = insertNode(v, 4);
|
||||
e0_1 = insertEdge(e, v0, v1);
|
||||
e0_2 = insertEdge(e, v0, v2);
|
||||
e1_3 = insertEdge(e, v1, v3);
|
||||
e1_4 = insertEdge(e, v1, v4);
|
||||
e2_3 = insertEdge(e, v2, v3);
|
||||
e2_4 = insertEdge(e, v2, v4);
|
||||
called = 0;
|
||||
counterCallback = function() {
|
||||
called++;
|
||||
};
|
||||
spyOn(this, "fakeReducerRequest").andCallFake(function() {
|
||||
return [v1, v3, v4];
|
||||
});
|
||||
adapter.setNodeLimit(3);
|
||||
|
||||
adapter.changeTo(v, e);
|
||||
adapter.loadNode(v0, counterCallback);
|
||||
adapter.loadNode(v1, counterCallback);
|
||||
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return called === 2;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
adapter.loadNode(v2, counterCallback);
|
||||
commNode = getCommunityNodes()[0];
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return called === 3;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
var commId = commNode._id;
|
||||
// Check start condition
|
||||
existNodes([commId, v0, v2]);
|
||||
expect(nodes.length).toEqual(3);
|
||||
|
||||
existEdge(v0, v2);
|
||||
existEdge(v0, commId);
|
||||
existEdge(v2, commId);
|
||||
expect(edges.length).toEqual(4);
|
||||
|
||||
adapter.setNodeLimit(20);
|
||||
adapter.expandCommunity(commNode, counterCallback);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return called === 4;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
existNodes([v0, v1, v2, v3, v4]);
|
||||
expect(nodes.length).toEqual(5);
|
||||
|
||||
existEdge(v0, v1);
|
||||
existEdge(v0, v2);
|
||||
existEdge(v1, v3);
|
||||
existEdge(v1, v4);
|
||||
existEdge(v2, v3);
|
||||
existEdge(v2, v4);
|
||||
expect(edges.length).toEqual(6);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('set inbound and outboundcounter correctly', function() {
|
||||
|
||||
var commNode, called, counterCallback,
|
||||
v0, v1, v2, v3, v4,
|
||||
e0_1, e0_2, e1_3, e1_4, e2_3, e2_4;
|
||||
|
||||
runs(function() {
|
||||
var v = "vertices",
|
||||
e = "edges";
|
||||
nodes.length = 0;
|
||||
edges.length = 0;
|
||||
v0 = insertNode(v, 0);
|
||||
v1 = insertNode(v, 1);
|
||||
v2 = insertNode(v, 2);
|
||||
v3 = insertNode(v, 3);
|
||||
v4 = insertNode(v, 4);
|
||||
e0_1 = insertEdge(e, v0, v1);
|
||||
e0_2 = insertEdge(e, v0, v2);
|
||||
e1_3 = insertEdge(e, v1, v3);
|
||||
e1_4 = insertEdge(e, v1, v4);
|
||||
e2_3 = insertEdge(e, v2, v3);
|
||||
e2_4 = insertEdge(e, v2, v4);
|
||||
called = 0;
|
||||
counterCallback = function() {
|
||||
called++;
|
||||
};
|
||||
spyOn(this, "fakeReducerRequest").andCallFake(function() {
|
||||
return [v1, v3, v4];
|
||||
});
|
||||
adapter.setNodeLimit(3);
|
||||
|
||||
adapter.changeTo(v, e);
|
||||
adapter.loadNode(v0, counterCallback);
|
||||
adapter.loadNode(v1, counterCallback);
|
||||
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return called === 2;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
adapter.loadNode(v2, counterCallback);
|
||||
commNode = getCommunityNodes()[0];
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return called === 3;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
adapter.setNodeLimit(20);
|
||||
adapter.expandCommunity(commNode, counterCallback);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return called === 4;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
var checkNodeWithInAndOut = function(id, inbound, outbound) {
|
||||
var n = nodeWithID(id);
|
||||
expect(n._outboundCounter).toEqual(outbound);
|
||||
expect(n._inboundCounter).toEqual(inbound);
|
||||
};
|
||||
checkNodeWithInAndOut(v0, 0, 2);
|
||||
checkNodeWithInAndOut(v1, 1, 2);
|
||||
checkNodeWithInAndOut(v2, 1, 2);
|
||||
checkNodeWithInAndOut(v3, 2, 0);
|
||||
checkNodeWithInAndOut(v4, 2, 0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('that displays a community node already', function() {
|
||||
|
||||
var firstCommId,
|
||||
fakeResult;
|
||||
|
||||
beforeEach(function() {
|
||||
runs(function() {
|
||||
callbackCheck = false;
|
||||
adapter.setNodeLimit(7);
|
||||
fakeResult = [c0, c2];
|
||||
spyOn(this, "fakeReducerRequest").andCallFake(function() {
|
||||
return fakeResult;
|
||||
});
|
||||
adapter.loadNodeFromTreeById(c1, checkCallbackFunction);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return callbackCheck;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
firstCommId = getCommunityNodesIds()[0];
|
||||
});
|
||||
});
|
||||
|
||||
it('should expand a community if enough space is available', function() {
|
||||
runs(function() {
|
||||
adapter.setNodeLimit(10);
|
||||
callbackCheck = false;
|
||||
adapter.expandCommunity(nodeWithID(firstCommId), checkCallbackFunction);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return callbackCheck;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
expect(getCommunityNodes().length).toEqual(0);
|
||||
existNodes([c0, c1, c2, c3, c4, c5, c6, c7]);
|
||||
existEdge(c0, c1);
|
||||
existEdge(c0, c2);
|
||||
existEdge(c0, c3);
|
||||
existEdge(c0, c4);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should expand a community and join another '
|
||||
+ 'one if not enough space is available', function() {
|
||||
runs(function() {
|
||||
fakeResult = [c1, c7];
|
||||
callbackCheck = false;
|
||||
adapter.expandCommunity(nodeWithID(firstCommId), checkCallbackFunction);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return callbackCheck;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
var newCommId = getCommunityNodesIds()[0];
|
||||
expect(getCommunityNodes().length).toEqual(1);
|
||||
existNodes([c0, c2, c3, c4, c5, c6, newCommId]);
|
||||
notExistNodes([c1, c7]);
|
||||
|
||||
existEdge(c0, c2);
|
||||
existEdge(c0, c3);
|
||||
existEdge(c0, c4);
|
||||
|
||||
existEdge(c0, newCommId);
|
||||
existEdge(newCommId, c5);
|
||||
existEdge(newCommId, c6);
|
||||
});
|
||||
});
|
||||
|
||||
it('should join another community if space is further reduced', function() {
|
||||
runs(function() {
|
||||
fakeResult = [c1, c7];
|
||||
callbackCheck = false;
|
||||
adapter.setNodeLimit(6, checkCallbackFunction);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return callbackCheck;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
expect(getCommunityNodes().length).toEqual(2);
|
||||
var ids = getCommunityNodesIds(),
|
||||
newCommId;
|
||||
|
||||
if (firstCommId === ids[0]) {
|
||||
newCommId = ids[1];
|
||||
} else {
|
||||
newCommId = ids[0];
|
||||
}
|
||||
|
||||
existNodes([c3, c4, c5, c6, firstCommId, newCommId]);
|
||||
notExistNodes([c0, c1, c2, c7]);
|
||||
|
||||
existEdge(firstCommId, c3);
|
||||
existEdge(firstCommId, c4);
|
||||
existEdge(firstCommId, newCommId);
|
||||
existEdge(newCommId, c5);
|
||||
existEdge(newCommId, c6);
|
||||
});
|
||||
});
|
||||
|
||||
it('should connect edges to internal nodes', function() {
|
||||
|
||||
runs(function() {
|
||||
insertEdge(edgesCollection, c3, c0);
|
||||
|
||||
adapter.setNodeLimit(20);
|
||||
callbackCheck = false;
|
||||
adapter.loadNode(c3, checkCallbackFunction);
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return callbackCheck;
|
||||
});
|
||||
|
||||
runs(function() {
|
||||
existEdge(c3, firstCommId);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('that has loaded several queries', function() {
|
||||
|
|
|
@ -56,6 +56,7 @@ var describeInterface = function (testee) {
|
|||
});
|
||||
|
||||
// Add functions to load here:
|
||||
expect(testee).toHaveFunction("loadNode", 2);
|
||||
expect(testee).toHaveFunction("loadNodeFromTreeById", 2);
|
||||
expect(testee).toHaveFunction("requestCentralityChildren", 2);
|
||||
expect(testee).toHaveFunction("loadNodeFromTreeByAttributeValue", 3);
|
||||
|
@ -66,6 +67,7 @@ var describeInterface = function (testee) {
|
|||
expect(testee).toHaveFunction("deleteNode", 2);
|
||||
expect(testee).toHaveFunction("patchNode", 3);
|
||||
expect(testee).toHaveFunction("setNodeLimit", 2);
|
||||
expect(testee).toHaveFunction("expandCommunity", 2);
|
||||
});
|
||||
|
||||
};
|
||||
|
|
|
@ -62,6 +62,8 @@
|
|||
spyOn(adapter, "createEdge");
|
||||
spyOn(adapter, "patchEdge");
|
||||
spyOn(adapter, "deleteEdge");
|
||||
spyOn(adapter, "loadNode");
|
||||
spyOn(adapter, "expandCommunity");
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
|
@ -74,9 +76,6 @@
|
|||
nodes = [];
|
||||
edges = [];
|
||||
|
||||
this.loadNode = function() {};
|
||||
spyOn(this, "loadNode");
|
||||
|
||||
defaultPosition = {
|
||||
x: 1,
|
||||
y: 1,
|
||||
|
@ -87,7 +86,7 @@
|
|||
edges: edges,
|
||||
nodes: nodes,
|
||||
startCallback: function() {},
|
||||
loadNode: this.loadNode,
|
||||
adapter: adapter,
|
||||
reshapeNodes: function() {}
|
||||
};
|
||||
|
||||
|
@ -437,7 +436,7 @@
|
|||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return this.loadNode.wasCalled;
|
||||
return adapter.loadNode.wasCalled;
|
||||
}, 1000, "The loadNode function should have been called.");
|
||||
|
||||
runs(function() {
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
spyOn(adapter, "createEdge");
|
||||
spyOn(adapter, "patchEdge");
|
||||
spyOn(adapter, "deleteEdge");
|
||||
spyOn(adapter, "loadNode");
|
||||
spyOn(adapter, "expandCommunity");
|
||||
};
|
||||
|
||||
|
||||
|
@ -87,15 +89,13 @@
|
|||
}];
|
||||
adapter = mocks.adapter;
|
||||
layouter = mocks.layouter;
|
||||
this.loadNode = function() {};
|
||||
spyOn(this, "loadNode");
|
||||
addSpies();
|
||||
|
||||
var expandConfig = {
|
||||
edges: edges,
|
||||
nodes: nodes,
|
||||
startCallback: function() {},
|
||||
loadNode: this.loadNode,
|
||||
adapter: adapter,
|
||||
reshapeNodes: function() {}
|
||||
},
|
||||
|
||||
|
@ -307,7 +307,7 @@
|
|||
|
||||
helper.simulateMouseEvent("click", "1");
|
||||
|
||||
expect(this.loadNode).toHaveBeenCalledWith(nodes[0]._id, jasmine.any(Function));
|
||||
expect(adapter.loadNode).toHaveBeenCalledWith(nodes[0]._id, jasmine.any(Function));
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true */
|
||||
/*global beforeEach, afterEach */
|
||||
/*global describe, it, expect */
|
||||
/*global describe, it, expect, jasmine */
|
||||
/*global runs, spyOn, waitsFor */
|
||||
/*global window, eb, loadFixtures, document, $ */
|
||||
/*global EventLibrary*/
|
||||
|
@ -40,13 +40,15 @@
|
|||
|
||||
var eventLib,
|
||||
nodeShaperDummy = {},
|
||||
edgeShaperDummy = {};
|
||||
edgeShaperDummy = {},
|
||||
adapterDummy = {};
|
||||
|
||||
beforeEach(function() {
|
||||
eventLib = new EventLibrary();
|
||||
nodeShaperDummy.reshapeNodes = function() {};
|
||||
edgeShaperDummy.reshapeEdges = function() {};
|
||||
|
||||
adapterDummy.loadNode = function() {};
|
||||
adapterDummy.expandCommunity = function() {};
|
||||
spyOn(nodeShaperDummy, "reshapeNodes");
|
||||
spyOn(edgeShaperDummy, "reshapeEdges");
|
||||
});
|
||||
|
@ -59,10 +61,6 @@
|
|||
edges,
|
||||
loadedNodes,
|
||||
started,
|
||||
loadNodeCallback = function(node) {
|
||||
loaded++;
|
||||
loadedNodes.push(node);
|
||||
},
|
||||
reshapeNodesCallback = function() {
|
||||
reshaped++;
|
||||
},
|
||||
|
@ -84,7 +82,7 @@
|
|||
edges: edges,
|
||||
nodes: nodes,
|
||||
startCallback: startCallback,
|
||||
loadNode: loadNodeCallback,
|
||||
adapter: adapterDummy,
|
||||
reshapeNodes: reshapeNodesCallback
|
||||
};
|
||||
});
|
||||
|
@ -96,6 +94,11 @@
|
|||
_inboundCounter: 0
|
||||
};
|
||||
nodes.push(node);
|
||||
spyOn(adapterDummy, "loadNode").andCallFake(function(node) {
|
||||
loaded++;
|
||||
loadedNodes.push(node);
|
||||
});
|
||||
//config.adapter = adapterDummy.loadNode;
|
||||
testee = eventLib.Expand(config);
|
||||
testee(node);
|
||||
|
||||
|
@ -206,6 +209,124 @@
|
|||
expect(c2._outboundCounter).toEqual(1);
|
||||
});
|
||||
|
||||
describe('with community nodes', function() {
|
||||
|
||||
it('should expand a community node properly', function() {
|
||||
var comm = {
|
||||
_id: "*community_1"
|
||||
};
|
||||
nodes.push(comm);
|
||||
|
||||
spyOn(adapterDummy, "expandCommunity");
|
||||
|
||||
testee = eventLib.Expand(config);
|
||||
testee(comm);
|
||||
|
||||
expect(adapterDummy.expandCommunity).toHaveBeenCalledWith(comm, jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should remove a community if last pointer to it is collapsed', function() {
|
||||
|
||||
runs(function() {
|
||||
var c0 = {
|
||||
_id: 0,
|
||||
_outboundCounter: 1,
|
||||
_inboundCounter: 0
|
||||
},
|
||||
c1 = {
|
||||
_id: 1,
|
||||
_expanded: true,
|
||||
_outboundCounter: 1,
|
||||
_inboundCounter: 1
|
||||
},
|
||||
comm = {
|
||||
_id: "*community_1",
|
||||
_outboundCounter: 1,
|
||||
_inboundCounter: 1
|
||||
},
|
||||
c2 = {
|
||||
_id: 1,
|
||||
_outboundCounter: 0,
|
||||
_inboundCounter: 1
|
||||
},
|
||||
e0 = {
|
||||
source: c0,
|
||||
target: c1
|
||||
},
|
||||
e1 = {
|
||||
source: c1,
|
||||
target: comm
|
||||
},
|
||||
e2 = {
|
||||
source: comm,
|
||||
target: c2
|
||||
};
|
||||
nodes.push(c0);
|
||||
nodes.push(c1);
|
||||
nodes.push(comm);
|
||||
nodes.push(c2);
|
||||
edges.push(e0);
|
||||
edges.push(e1);
|
||||
edges.push(e2);
|
||||
|
||||
testee = eventLib.Expand(config);
|
||||
testee(c1);
|
||||
|
||||
expect(nodes).toEqual([c0, c1]);
|
||||
expect(edges).toEqual([e0]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should not remove a community if a pointer to it still exists', function() {
|
||||
|
||||
runs(function() {
|
||||
var c0 = {
|
||||
_id: 0,
|
||||
_outboundCounter: 2,
|
||||
_inboundCounter: 0
|
||||
},
|
||||
c1 = {
|
||||
_id: 1,
|
||||
_expanded: true,
|
||||
_outboundCounter: 1,
|
||||
_inboundCounter: 1
|
||||
},
|
||||
comm = {
|
||||
_id: "*community_1",
|
||||
_outboundCounter: 0,
|
||||
_inboundCounter: 2
|
||||
},
|
||||
e0 = {
|
||||
source: c0,
|
||||
target: c1
|
||||
},
|
||||
e1 = {
|
||||
source: c0,
|
||||
target: comm
|
||||
},
|
||||
e2 = {
|
||||
source: c1,
|
||||
target: comm
|
||||
};
|
||||
nodes.push(c0);
|
||||
nodes.push(c1);
|
||||
nodes.push(comm);
|
||||
edges.push(e0);
|
||||
edges.push(e1);
|
||||
edges.push(e2);
|
||||
|
||||
testee = eventLib.Expand(config);
|
||||
testee(c1);
|
||||
|
||||
expect(nodes).toEqual([c0, c1, comm]);
|
||||
expect(edges).toEqual([e0, e1]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -248,14 +369,14 @@
|
|||
function() {
|
||||
eventLib.Expand(testConfig);
|
||||
}
|
||||
).toThrow("A callback to load a node has to be defined");
|
||||
).toThrow("An adapter to load data has to be defined");
|
||||
});
|
||||
|
||||
it('should throw an error if reshape node callback is not given', function() {
|
||||
testConfig.edges = [];
|
||||
testConfig.nodes = [];
|
||||
testConfig.startCallback = function(){};
|
||||
testConfig.loadNode = function(){};
|
||||
testConfig.adapter = adapterDummy;
|
||||
expect(
|
||||
function() {
|
||||
eventLib.Expand(testConfig);
|
||||
|
|
|
@ -153,7 +153,7 @@ describe("Graph Viewer", function() {
|
|||
edges: [],
|
||||
nodes: [],
|
||||
startCallback: jasmine.any(Function),
|
||||
loadNode: jasmine.any(Function),
|
||||
adapter: jasmine.any(Object),
|
||||
reshapeNodes: jasmine.any(Function)
|
||||
},
|
||||
drag: {
|
||||
|
@ -172,7 +172,7 @@ describe("Graph Viewer", function() {
|
|||
edges: [],
|
||||
nodes: [],
|
||||
startCallback: jasmine.any(Function),
|
||||
loadNode: jasmine.any(Function),
|
||||
adapter: jasmine.any(Object),
|
||||
reshapeNodes: jasmine.any(Function)
|
||||
});
|
||||
expect(viewer.dispatcherConfig.drag).toEqual({
|
||||
|
@ -270,6 +270,15 @@ describe("Graph Viewer", function() {
|
|||
expect(viewer.adapter.setNodeLimit).wasCalled();
|
||||
});
|
||||
|
||||
it('should trigger the start function if node limit is reduced to far', function() {
|
||||
spyOn(viewer.adapter, "setNodeLimit").andCallFake(function(l, callback) {
|
||||
callback();
|
||||
});
|
||||
spyOn(viewer, "start");
|
||||
helper.simulateScrollUpMouseEvent("outersvg");
|
||||
expect(viewer.start).wasCalled();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@
|
|||
edges.push(helper.createSimpleEdge(nodes, 5, 7));
|
||||
|
||||
var com = reducer.getCommunity(6);
|
||||
expect(com).toContainNodes([0, 1, 2]);
|
||||
expect(com).toContainNodes([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -988,6 +988,76 @@
|
|||
expect(n.attr("transform")).toEqual("translate(10,10)scale(1)");
|
||||
});
|
||||
});
|
||||
|
||||
describe('testing community nodes', function() {
|
||||
var shaper;
|
||||
|
||||
beforeEach(function() {
|
||||
shaper = new NodeShaper(d3.select("svg"));
|
||||
});
|
||||
|
||||
it('should render community nodes', function() {
|
||||
var nodes = helper.createSimpleNodes([0, 1, 2]),
|
||||
commNode = {
|
||||
_id: "*community_42",
|
||||
_inboundCounter: 0,
|
||||
_outboundCounter: 0,
|
||||
position: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
z: 1
|
||||
}
|
||||
};
|
||||
nodes.push(commNode);
|
||||
shaper.drawNodes(nodes);
|
||||
expect($("svg .node").length).toEqual(4);
|
||||
expect($("svg #\\*community_42")[0]).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render communtiy nodes as stars', function() {
|
||||
var nodes = helper.createSimpleNodes([0, 1, 2]),
|
||||
commNode = {
|
||||
_id: "*community_42",
|
||||
_size: 4,
|
||||
_inboundCounter: 0,
|
||||
_outboundCounter: 0,
|
||||
position: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
z: 1
|
||||
}
|
||||
},
|
||||
star;
|
||||
nodes.push(commNode);
|
||||
shaper.drawNodes(nodes);
|
||||
expect($("svg .communitynode").length).toEqual(1);
|
||||
expect($("svg #\\*community_42")[0]).toBeDefined();
|
||||
star = $("svg #\\*community_42 polygon");
|
||||
expect(star.length).toEqual(1);
|
||||
expect(star.attr("points")).toEqual("0,-25 -16,20 23,-10 -23,-10 16,20");
|
||||
});
|
||||
|
||||
it('should print the size of the capsulated community', function() {
|
||||
var nodes = helper.createSimpleNodes([0, 1, 2]),
|
||||
commNode = {
|
||||
_id: "*community_42",
|
||||
_size: 4,
|
||||
_inboundCounter: 0,
|
||||
_outboundCounter: 0,
|
||||
position: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
z: 1
|
||||
}
|
||||
},
|
||||
text;
|
||||
nodes.push(commNode);
|
||||
shaper.drawNodes(nodes);
|
||||
text = $("svg #\\*community_42 text")[0].textContent;
|
||||
expect(text).toEqual("4");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -479,8 +479,9 @@ nv.models.axis = function() {
|
|||
.attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' })
|
||||
.attr('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end');
|
||||
}
|
||||
axisLabel.enter().append('text').attr('class', 'nv-axislabel')
|
||||
axisLabel.enter().append('text').attr('class', 'nv-axislabel nv-x-axislabel')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('class', 'heikotestclass')
|
||||
.attr('y', xLabelMargin);
|
||||
var w = (scale.range().length==2) ? scale.range()[1] : (scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]));
|
||||
axisLabel
|
||||
|
@ -565,7 +566,7 @@ nv.models.axis = function() {
|
|||
.attr('text-anchor', rotateYLabel ? 'middle' : 'end')
|
||||
.attr('transform', rotateYLabel ? 'rotate(-90)' : '')
|
||||
//Edited 25 in next line -> origin was 12
|
||||
.attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 28) : -10); //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
|
||||
.attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 40) : -10); //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
|
||||
axisLabel
|
||||
.attr('x', rotateYLabel ? (-scale.range()[0] / 2) : -axis.tickPadding());
|
||||
if (showMaxMin) {
|
||||
|
|
|
@ -8,17 +8,66 @@
|
|||
|
||||
<ul class="dropdown-menu">
|
||||
<li class="nav-header">Type</li>
|
||||
<li><a href="#"><label class="checkbox"><input type="checkbox" id="checkSystem">System</label></a></li>
|
||||
<li><a href="#"><label class="checkbox"><input type="checkbox" id="checkDocument">Document</label></a></li>
|
||||
<li><a href="#"><label class="checkbox"><input type="checkbox" id="checkEdge">Edge</label></a></li>
|
||||
<li><a href="#">
|
||||
<label class="checkbox checkboxLabel">
|
||||
<input class="css-checkbox" type="checkbox" id="checkSystem">
|
||||
<label class="css-label"></label>System
|
||||
</label>
|
||||
</a></li>
|
||||
|
||||
<li><a href="#">
|
||||
<label class="checkbox checkboxLabel">
|
||||
<input class="css-checkbox" type="checkbox" id="checkDocument">
|
||||
<label class="css-label"></label>Document
|
||||
</label>
|
||||
</a></li>
|
||||
|
||||
<li><a href="#">
|
||||
<label class="checkbox checkboxLabel">
|
||||
<input class="css-checkbox" type="checkbox" id="checkEdge">
|
||||
<label class="css-label"></label>Edge
|
||||
</label>
|
||||
</a></li>
|
||||
|
||||
<li class="divider"></li>
|
||||
<li class="nav-header">Status</li>
|
||||
<li><a href="#"><label class="checkbox"><input type="checkbox" id="checkLoaded">Loaded</label></a></li>
|
||||
<li><a href="#"><label class="checkbox"><input type="checkbox" id="checkUnloaded">Unloaded</label></a></li>
|
||||
|
||||
<li><a href="#">
|
||||
<label class="checkbox checkboxLabel">
|
||||
<input class="css-checkbox" type="checkbox" id="checkLoaded">
|
||||
<label class="css-label"></label>Loaded
|
||||
</label>
|
||||
</a></li>
|
||||
|
||||
<li><a href="#">
|
||||
<label class="checkbox checkboxLabel">
|
||||
<input class="css-checkbox" type="checkbox" id="checkUnloaded">
|
||||
<label class="css-label"></label>Unloaded
|
||||
</label>
|
||||
</a></li>
|
||||
|
||||
<li class="nav-header">Sorting</li>
|
||||
<li><a href="#"><label class="radio"><input type="radio" id="sortName">Sort by name</label></a></li>
|
||||
<li><a href="#"><label class="radio"><input type="radio" id="sortType">Sort by type</label></a></li>
|
||||
<li><a href="#"><label class="checkbox"><input type="checkbox" id="sortOrder">Sort descending</label></a></li>
|
||||
|
||||
<li><a href="#">
|
||||
<label class="radio">
|
||||
<input type="radio" id="sortName">
|
||||
<label><span></span>Sort by name</label>
|
||||
</label>
|
||||
</a></li>
|
||||
|
||||
<li><a href="#">
|
||||
<label class="radio">
|
||||
<input type="radio" id="sortType">
|
||||
<label><span></span>Sort by type</label>
|
||||
</label>
|
||||
</a></li>
|
||||
|
||||
<li><a href="#">
|
||||
<label class="checkbox checkboxLabel">
|
||||
<input class="css-checkbox" type="checkbox" id="sortOrder">
|
||||
<label class="css-label"></label>Sort descending
|
||||
</label>
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /btn-group -->
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
|
||||
<ul class="dropdown-menu interval-dropdown">
|
||||
<li class="nav-header">Update every:</li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every5seconds" value="5">5 seconds</label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every15seconds" value="15">15 seconds</label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every30seconds" value="30">30 seconds</label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every60seconds" value="60">60 seconds</label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every120seconds" value="120">120 seconds</label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every5seconds" value="5"><label><span></span>5 seconds</label></label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every15seconds" value="15"><label><span></span>15 seconds</label></label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every30seconds" value="30"><label><span></span>30 seconds</label></label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every60seconds" value="60"><label><span></span>60 seconds</label></label></a></li>
|
||||
<li><a><label class="radio"><input type="radio" name="updateInterval" id="every120seconds" value="120"><label><span></span>120 seconds</label></label></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /btn-group -->
|
||||
|
@ -35,6 +35,16 @@
|
|||
</ul>
|
||||
|
||||
<ul class="thumbnails">
|
||||
<li id="detailCollections" class="statSingleClient" style="margin-bottom: 13px !important;">
|
||||
<div class="boxHeader">
|
||||
<h6 id="detailCollectionsHeader" class="dashboardH6">Collections</h6>
|
||||
<i id="db-collectionMinimize" class="icon-white icon-minus"></i>
|
||||
</div>
|
||||
<div id="detailCollectionsChart" class="statChart">
|
||||
<svg class="svgCollections"/>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li id="detailGraph" class="statSingleClient">
|
||||
<div class="boxHeader">
|
||||
<h6 id="detailGraphHeader" class="dashboardH6">User Time</h6>
|
||||
|
|
|
@ -1,27 +1,44 @@
|
|||
var dashboardView = Backbone.View.extend({
|
||||
el: '#content',
|
||||
updateInterval: 1000, // 1 second, constant
|
||||
updateInterval: 500, // 0.5 second, constant
|
||||
updateFrequency: 5, // the actual update rate (5 s)
|
||||
updateCounter: 0,
|
||||
arraySize: 99, // how many values will we keep per figure?
|
||||
arraySize: 20, // how many values will we keep per figure?
|
||||
seriesData: {},
|
||||
charts: {},
|
||||
units: [],
|
||||
updateNOW: false,
|
||||
collectionsStats: {
|
||||
"corrupted": 0,
|
||||
"new born collection" : 0,
|
||||
"unloaded" : 0,
|
||||
"loaded" : 0,
|
||||
"in the process of being unloaded" : 0,
|
||||
"deleted" : 0
|
||||
},
|
||||
detailGraph: "userTime",
|
||||
|
||||
initialize: function () {
|
||||
var self = this;
|
||||
|
||||
this.initUnits();
|
||||
self.addCustomCharts();
|
||||
|
||||
this.collection.fetch({
|
||||
success: function() {
|
||||
self.countCollections();
|
||||
self.calculateSeries();
|
||||
self.renderCharts();
|
||||
|
||||
window.setInterval(function() {
|
||||
self.updateCounter++;
|
||||
|
||||
if (self.updateNOW === true) {
|
||||
self.calculateSeries();
|
||||
self.renderCharts();
|
||||
self.updateNOW = false;
|
||||
}
|
||||
|
||||
if (self.updateCounter < self.updateFrequency) {
|
||||
return false;
|
||||
}
|
||||
|
@ -47,20 +64,32 @@ var dashboardView = Backbone.View.extend({
|
|||
|
||||
events: {
|
||||
"click .dashboard-dropdown li" : "checkEnabled",
|
||||
"click .interval-dropdown li" : "checkInterval",
|
||||
"click .db-zoom" : "renderDetailChart",
|
||||
"click .db-minimize" : "checkDetailChart",
|
||||
"click .db-hide" : "hideChart"
|
||||
"click .interval-dropdown li" : "checkInterval",
|
||||
"click .db-zoom" : "renderDetailChart",
|
||||
"click .db-minimize" : "checkDetailChart",
|
||||
"click .db-hide" : "hideChart",
|
||||
"click .group-close" : "hideGroup",
|
||||
"click .group-open" : "showGroup"
|
||||
},
|
||||
|
||||
template: new EJS({url: 'js/templates/dashboardView.ejs'}),
|
||||
|
||||
countCollections: function() {
|
||||
var self = this;
|
||||
$.each(window.arangoCollectionsStore.models, function(k,v) {
|
||||
if ( self.collectionsStats[this.attributes.status] === undefined ) {
|
||||
self.collectionsStats[this.attributes.status] = 0;
|
||||
}
|
||||
self.collectionsStats[this.attributes.status]++;
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
$(this.el).html(this.template.text);
|
||||
|
||||
//Client calculated charts
|
||||
self.genCustomCategories();
|
||||
/*self.genCustomCategories();
|
||||
self.genCustomChartDescription(
|
||||
"userTime + systemTime",
|
||||
"custom",
|
||||
|
@ -68,17 +97,21 @@ var dashboardView = Backbone.View.extend({
|
|||
"Total Time (User+System)",
|
||||
"accumulated",
|
||||
"seconds"
|
||||
);
|
||||
);*/
|
||||
|
||||
var counter = 1;
|
||||
$.each(this.options.description.models[0].attributes.groups, function () {
|
||||
$('.thumbnails').append(
|
||||
'<ul class="statGroups" id="' + this.group + '">' +
|
||||
'<i class="group-close icon-minus icon-white"></i>' +
|
||||
'<h4 class="statsHeader">' + this.name + '</h4>' +
|
||||
'</ul>');
|
||||
$('#menuGroups').append(
|
||||
'<li class="nav-header">' + this.name + '</li>' +
|
||||
'<li class="divider" id="' + this.group + 'Divider"></li>'
|
||||
);
|
||||
$('#menuGroups').append('<li class="nav-header">' + this.name + '</li>');
|
||||
$('#menuGroups').append('<li class="divider" id="' + this.group + 'Divider"></li>');
|
||||
if (self.options.description.models[0].attributes.groups.length === counter) {
|
||||
$('#'+this.group+'Divider').addClass('dbNotVisible');
|
||||
}
|
||||
counter++;
|
||||
});
|
||||
|
||||
$.each(this.options.description.models[0].attributes.figures, function () {
|
||||
|
@ -105,45 +138,45 @@ var dashboardView = Backbone.View.extend({
|
|||
}
|
||||
return this;
|
||||
},
|
||||
//generate function for all custom categories
|
||||
genCustomCategories: function () {
|
||||
this.genCustomCategory("Client calculated charts", "custom", "Customized Charts");
|
||||
},
|
||||
//generate a custom category
|
||||
genCustomCategory: function(description, group, name) {
|
||||
this.options.description.models[0].attributes.groups.push({
|
||||
"description":description,
|
||||
"group":group,
|
||||
"name":name
|
||||
});
|
||||
},
|
||||
//generate a custom description
|
||||
genCustomChartDescription: function (description, group, identifier, name, type, units) {
|
||||
var figure = {
|
||||
"description" : description,
|
||||
"group" : group,
|
||||
"identifier" : identifier,
|
||||
"name" : name,
|
||||
"type" : type,
|
||||
"units" : units
|
||||
};
|
||||
this.options.description.models[0].attributes.figures.push(figure);
|
||||
this.renderFigure(figure);
|
||||
},
|
||||
//calculate customized chart value functions here
|
||||
updateCustomChartValues: function () {
|
||||
this.totalTime2();
|
||||
},
|
||||
|
||||
//custom chart value calculation for totalTime2
|
||||
totalTime2: function () {
|
||||
var val1 = this.collection.models[0].attributes.system.userTime;
|
||||
var val2 = this.collection.models[0].attributes.system.systemTime;
|
||||
var totalTime2Value = val1+val2;
|
||||
this.collection.models[0].attributes["custom"] = {"totalTime2":totalTime2Value};
|
||||
addCustomCharts: function () {
|
||||
var self = this;
|
||||
var figure = {
|
||||
"description" : "my custom chart",
|
||||
"group" : "custom",
|
||||
"identifier" : "custom1",
|
||||
"name" : "Custom1",
|
||||
"type" : "accumulated",
|
||||
"units" : "seconds",
|
||||
"exec" : function () {
|
||||
var val1 = self.collection.models[0].attributes.system.userTime;
|
||||
var val2 = self.collection.models[0].attributes.system.systemTime;
|
||||
var totalTime2Value = val1+val2;
|
||||
return totalTime2Value;
|
||||
}
|
||||
};
|
||||
|
||||
var addGroup = true;
|
||||
|
||||
$.each(this.options.description.models[0].attributes.groups, function(k, v) {
|
||||
if (self.options.description.models[0].attributes.groups[k].group === figure.group) {
|
||||
addGroup = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (addGroup == true) {
|
||||
self.options.description.models[0].attributes.groups.push({
|
||||
"description" : "custom",
|
||||
"group" : "custom",
|
||||
"name" : "custom"
|
||||
});
|
||||
}
|
||||
|
||||
this.options.description.models[0].attributes.figures.push(figure);
|
||||
},
|
||||
|
||||
checkInterval: function (a) {
|
||||
var self = this;
|
||||
this.updateFrequency = a.target.value;
|
||||
self.calculateSeries();
|
||||
self.renderCharts();
|
||||
|
@ -210,6 +243,20 @@ var dashboardView = Backbone.View.extend({
|
|||
}
|
||||
},
|
||||
|
||||
hideGroup: function (a) {
|
||||
var group = $(a.target).parent();
|
||||
$(a.target).removeClass('icon-minus group-close');
|
||||
$(a.target).addClass('icon-plus group-open');
|
||||
$(group).addClass("groupHidden");
|
||||
},
|
||||
|
||||
showGroup: function (a) {
|
||||
var group = $(a.target).parent();
|
||||
$(a.target).removeClass('icon-plus group-open');
|
||||
$(a.target).addClass('icon-minus group-close');
|
||||
$(group).removeClass("groupHidden");
|
||||
},
|
||||
|
||||
hideChart: function (a) {
|
||||
var figure = $(a.target).attr("value");
|
||||
$('#'+figure+'Checkbox').prop('checked', false);
|
||||
|
@ -222,20 +269,56 @@ var dashboardView = Backbone.View.extend({
|
|||
$.each(this.options.description.models[0].attributes.figures, function () {
|
||||
if(this.identifier === self.detailGraph) {
|
||||
$('#detailGraphHeader').text(this.name);
|
||||
self.calculateSeries();
|
||||
self.renderCharts();
|
||||
$("html, body").animate({ scrollTop: 0 }, "slow");
|
||||
$('#detailGraphChart').show();
|
||||
$('#detailGraph').height(300);
|
||||
$('#dbHideSwitch').addClass('icon-minus');
|
||||
$('#dbHideSwitch').removeClass('icon-plus');
|
||||
self.updateNOW = true;
|
||||
self.calculateSeries();
|
||||
self.renderCharts();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
renderCollectionsChart: function () {
|
||||
var self = this;
|
||||
nv.addGraph(function() {
|
||||
var chart = nv.models.pieChart()
|
||||
.x(function(d) { return d.label })
|
||||
.y(function(d) { return d.value })
|
||||
.showLabels(true);
|
||||
|
||||
d3.select("#detailCollectionsChart svg")
|
||||
.datum(self.convertCollections())
|
||||
.transition().duration(1200)
|
||||
.call(chart);
|
||||
|
||||
return chart;
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
convertCollections: function () {
|
||||
var self = this;
|
||||
var collValues = [];
|
||||
$.each(self.collectionsStats, function(k,v) {
|
||||
collValues.push({
|
||||
"label" : k,
|
||||
"value" : v,
|
||||
});
|
||||
});
|
||||
|
||||
return [{
|
||||
key: "Collections Status",
|
||||
values: collValues
|
||||
}];
|
||||
},
|
||||
|
||||
renderCharts: function () {
|
||||
var self = this;
|
||||
$('#every'+self.updateFrequency+'seconds').prop('checked',true);
|
||||
self.renderCollectionsChart();
|
||||
|
||||
$.each(self.options.description.models[0].attributes.figures, function () {
|
||||
var figure = this;
|
||||
|
@ -284,22 +367,25 @@ var dashboardView = Backbone.View.extend({
|
|||
}
|
||||
if (self.detailGraph === identifier) {
|
||||
d3.select("#detailGraphChart svg")
|
||||
.call(chart)
|
||||
.datum([ { values: self.seriesData[identifier].values, key: identifier, color: "#8AA051" } ])
|
||||
.transition().duration(500);
|
||||
|
||||
}
|
||||
|
||||
d3.select("#" + identifier + "Chart svg")
|
||||
.call(chart)
|
||||
.datum([ { values: self.seriesData[identifier].values, key: identifier, color: "#8AA051" } ])
|
||||
.transition().duration(500);
|
||||
}
|
||||
else {
|
||||
}
|
||||
|
||||
//disable ticks for small charts
|
||||
//disable label for small charts
|
||||
|
||||
d3.select("#" + identifier + "Chart svg")
|
||||
.call(chart)
|
||||
.datum([ { values: self.seriesData[identifier].values, key: identifier, color: "#8AA051" } ])
|
||||
.transition().duration(500);
|
||||
});
|
||||
},
|
||||
|
||||
calculateSeries: function (flush) {
|
||||
var self = this;
|
||||
self.updateCustomChartValues();
|
||||
|
||||
var timeStamp = Math.round(new Date() * 10);
|
||||
|
||||
|
@ -320,7 +406,14 @@ var dashboardView = Backbone.View.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
var responseValue = self.collection.models[0].attributes[figure.group][identifier];
|
||||
var responseValue;
|
||||
|
||||
if (figure.exec) {
|
||||
responseValue = figure.exec();
|
||||
}
|
||||
else {
|
||||
responseValue = self.collection.models[0].attributes[figure.group][identifier];
|
||||
}
|
||||
|
||||
if (responseValue !== undefined && responseValue !== null) {
|
||||
if (responseValue.sum !== undefined) {
|
||||
|
@ -381,8 +474,10 @@ var dashboardView = Backbone.View.extend({
|
|||
);
|
||||
|
||||
$('#' + figure.group + 'Divider').before(
|
||||
'<li><a><label class="checkbox">'+
|
||||
'<input type="checkbox" id=' + figure.identifier + 'Checkbox checked>' + figure.name + '</label></a></li>'
|
||||
'<li><a><label class="checkbox checkboxLabel">'+
|
||||
'<input class="css-checkbox" type="checkbox" id=' + figure.identifier + 'Checkbox checked/>' +
|
||||
'<label class="css-label"/>' +
|
||||
figure.name + '</label></a></li>'
|
||||
);
|
||||
$('.db-info').tooltip({
|
||||
placement: "top"
|
||||
|
|
|
@ -241,7 +241,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -235,7 +235,7 @@ function post_api_collection (req, res) {
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result, headers);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -668,7 +668,7 @@ function put_api_collection_load (req, res, collection) {
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,7 +720,7 @@ function put_api_collection_unload (req, res, collection) {
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,7 +750,7 @@ function put_api_collection_truncate (req, res, collection) {
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -812,7 +812,7 @@ function put_api_collection_properties (req, res, collection) {
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -870,7 +870,7 @@ function put_api_collection_rename (req, res, collection) {
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -979,7 +979,7 @@ function delete_api_collection (req, res) {
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1012,7 +1012,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -235,7 +235,7 @@ function POST_api_cursor(req, res) {
|
|||
|
||||
// error occurred
|
||||
if (cursor instanceof Error) {
|
||||
actions.resultException(req, res, cursor);
|
||||
actions.resultException(req, res, cursor, undefined, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -420,7 +420,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -131,7 +131,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -137,7 +137,7 @@ function POST_api_explain (req, res) {
|
|||
var result = EXPLAIN(json.query, json.bindVars);
|
||||
|
||||
if (result instanceof Error) {
|
||||
actions.resultException(req, res, result);
|
||||
actions.resultException(req, res, result, undefined, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1770,7 +1770,7 @@ function post_graph_vertex_edges (req, res, g) {
|
|||
|
||||
// error occurred
|
||||
if (cursor instanceof Error) {
|
||||
actions.resultException(req, res, cursor);
|
||||
actions.resultException(req, res, cursor, undefined, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2039,7 +2039,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -890,7 +890,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -126,7 +126,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -115,7 +115,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -193,7 +193,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -312,7 +312,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -430,7 +430,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -522,7 +522,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -611,7 +611,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -688,7 +688,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -734,7 +734,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -828,7 +828,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -904,7 +904,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -990,7 +990,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1083,7 +1083,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -141,7 +141,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -362,7 +362,7 @@ actions.defineHttp({
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -611,7 +611,7 @@ actions.defineHttp({
|
|||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -456,7 +456,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -341,7 +341,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -428,7 +428,7 @@ actions.defineHttp({
|
|||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
"../../../html/admin/js/modules/org/arangodb/arango-collection-common.js",
|
||||
"../../../html/admin/js/modules/org/arangodb/arango-collection.js",
|
||||
"../../../html/admin/js/modules/org/arangodb/arango-database.js",
|
||||
"../../../html/admin/js/modules/org/arangodb/arango-error-common.js",
|
||||
"../../../html/admin/js/modules/org/arangodb/arango-error.js",
|
||||
"../../../html/admin/js/modules/org/arangodb/arango-query-cursor.js",
|
||||
"../../../html/admin/js/modules/org/arangodb/arango-statement-common.js",
|
||||
"../../../html/admin/js/modules/org/arangodb/arango-statement.js",
|
||||
|
|
|
@ -1198,7 +1198,7 @@ function resultError (req, res, httpReturnCode, errorNum, errorMessage, headers,
|
|||
|
||||
res.body = JSON.stringify(result);
|
||||
|
||||
if (headers !== undefined) {
|
||||
if (headers !== undefined && headers !== null) {
|
||||
res.headers = headers;
|
||||
}
|
||||
}
|
||||
|
@ -1806,36 +1806,42 @@ function indexNotFound (req, res, collection, index, headers) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates an error for an exception
|
||||
///
|
||||
/// @FUN{actions.resultException(@FA{req}, @FA{res}, @FA{err}, @FA{headers})}
|
||||
/// @FUN{actions.resultException(@FA{req}, @FA{res}, @FA{err}, @FA{headers}, @FA{verbose})}
|
||||
///
|
||||
/// The function generates an error response.
|
||||
/// The function generates an error response. If @FA{verbose} is set to
|
||||
/// @LIT{true} or not specified (the default), then the error stack trace will
|
||||
/// be included in the error message if available.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function resultException (req, res, err, headers) {
|
||||
function resultException (req, res, err, headers, verbose) {
|
||||
'use strict';
|
||||
|
||||
var code;
|
||||
var msg;
|
||||
var num;
|
||||
|
||||
if (verbose || verbose === undefined) {
|
||||
msg = String(err.stack || err);
|
||||
}
|
||||
else {
|
||||
msg = String(err);
|
||||
}
|
||||
|
||||
if (err instanceof internal.ArangoError) {
|
||||
num = err.errorNum;
|
||||
msg = err.errorMessage;
|
||||
code = exports.HTTP_BAD;
|
||||
|
||||
if (num === 0) {
|
||||
num = arangodb.ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
if (msg === "") {
|
||||
msg = String(err.stack || err);
|
||||
if (err.errorMessage !== "" && ! verbose) {
|
||||
msg = err.errorMessage;
|
||||
}
|
||||
else {
|
||||
msg += ": " + String(err.stack || err);
|
||||
}
|
||||
|
||||
|
||||
switch (num) {
|
||||
case arangodb.ERROR_INTERNAL:
|
||||
case arangodb.ERROR_OUT_OF_MEMORY:
|
||||
code = exports.HTTP_SERVER_ERROR;
|
||||
break;
|
||||
|
||||
|
@ -1844,23 +1850,17 @@ function resultException (req, res, err, headers) {
|
|||
code = exports.HTTP_CONFLICT;
|
||||
break;
|
||||
}
|
||||
|
||||
resultError(req, res, code, num, msg, headers);
|
||||
}
|
||||
else if (err instanceof TypeError) {
|
||||
num = arangodb.ERROR_TYPE_ERROR;
|
||||
code = exports.HTTP_BAD;
|
||||
msg = String(err.stack || err);
|
||||
|
||||
resultError(req, res, code, num, msg, headers);
|
||||
}
|
||||
|
||||
else {
|
||||
resultError(req, res,
|
||||
exports.HTTP_SERVER_ERROR, arangodb.ERROR_HTTP_SERVER_ERROR,
|
||||
String(err.stack || err),
|
||||
headers);
|
||||
num = arangodb.ERROR_HTTP_SERVER_ERROR;
|
||||
code = exports.HTTP_SERVER_ERROR;
|
||||
}
|
||||
|
||||
resultError(req, res, code, num, msg, headers);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -343,6 +343,32 @@ function ahuacatlQueryVariablesTestSuite () {
|
|||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collect and return (should omit any temporary variables)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTemporaryVariables : function () {
|
||||
var data = [ { name: "baz" }, { name: "bar" } ];
|
||||
var expected = [ { "criteria" : "bar", "g" : [ { "y" : { "test" : "test", "name" : "bar" } } ] }, { "criteria" : "baz", "g" : [ { "y" : { "test" : "test", "name" : "baz" } } ] } ];
|
||||
|
||||
var query = "FOR y IN (FOR x IN " + JSON.stringify(data) + " LET object = (FOR a IN [ '1', '2' ] RETURN a) RETURN { test: \"test\", name: x.name }) COLLECT criteria = y.name INTO g RETURN { criteria: criteria, g: g }";
|
||||
|
||||
var actual = getQueryResults("LET result = (" + query + ") RETURN result");
|
||||
assertEqual([ expected ], actual);
|
||||
|
||||
actual = getQueryResults(query);
|
||||
assertEqual(expected, actual);
|
||||
|
||||
// omit creating sub-objects
|
||||
query = "FOR y IN (FOR x IN " + JSON.stringify(data) + " RETURN { test: \"test\", name: x.name }) COLLECT criteria = y.name INTO g RETURN { criteria: criteria, g: g }";
|
||||
|
||||
actual = getQueryResults("LET result = (" + query + ") RETURN result");
|
||||
assertEqual([ expected ], actual);
|
||||
|
||||
actual = getQueryResults(query);
|
||||
assertEqual(expected, actual);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -373,24 +373,6 @@
|
|||
return true;
|
||||
});
|
||||
|
||||
// set up the collection _ids
|
||||
addTask("setupIds", "setup _ids collection", function () {
|
||||
return createSystemCollection("_ids", { waitForSync : false });
|
||||
});
|
||||
|
||||
// create a cap constraint for _ids
|
||||
addTask("ensureIdsCap", "ensureCapConstraint for _ids collection", function () {
|
||||
var ids = getCollection("_ids");
|
||||
|
||||
if (! ids) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ids.ensureCapConstraint(50);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// set up the collection _trx
|
||||
addTask("setupTrx", "setup _trx collection", function () {
|
||||
return createSystemCollection("_trx", { waitForSync : false });
|
||||
|
|
|
@ -84,7 +84,7 @@ bool RestVersionHandler::isDirect () {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& RestVersionHandler::queue () {
|
||||
string const& RestVersionHandler::queue () const {
|
||||
return _queue;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ namespace triagens {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& queue ();
|
||||
string const& queue () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the server version number
|
||||
|
|
|
@ -182,6 +182,14 @@ namespace triagens {
|
|||
return TRI_EndStringBuffer(&_buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns pointer to the end of the character buffer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char * end () {
|
||||
return const_cast<char*>(TRI_EndStringBuffer(&_buffer));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns length of the character buffer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -190,6 +198,14 @@ namespace triagens {
|
|||
return TRI_LengthStringBuffer(&_buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief increases length of the character buffer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void increaseLength (size_t n) {
|
||||
TRI_IncreaseLengthStringBuffer(&_buffer, n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns true if buffer is empty
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -257,7 +273,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- STRING AND CHARATCER APPENDERS
|
||||
// --SECTION-- STRING AND CHARACTER APPENDERS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -167,6 +167,9 @@ static void RemoveAllLockedFiles (void) {
|
|||
TRI_RemoveVector(&FileDescriptors, i);
|
||||
}
|
||||
|
||||
TRI_DestroyVectorString(&FileNames);
|
||||
TRI_DestroyVector(&FileDescriptors);
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&FileNamesLock);
|
||||
}
|
||||
|
||||
|
|
|
@ -1770,6 +1770,8 @@ void TRI_InitialiseLogging (bool threaded) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_ShutdownLogging () {
|
||||
size_t i, j;
|
||||
|
||||
if (! Initialised) {
|
||||
return ThreadedLogging;
|
||||
}
|
||||
|
@ -1798,6 +1800,20 @@ bool TRI_ShutdownLogging () {
|
|||
|
||||
TRI_UnlockSpin(&OutputPrefixLock);
|
||||
|
||||
// cleanup output buffers
|
||||
TRI_LockMutex(&BufferLock);
|
||||
|
||||
for (i = 0; i < OUTPUT_LOG_LEVELS; i++) {
|
||||
for (j = 0; j < OUTPUT_BUFFER_SIZE; j++) {
|
||||
if (BufferOutput[i][j]._text != NULL) {
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, BufferOutput[i][j]._text);
|
||||
BufferOutput[i][j]._text = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&BufferLock);
|
||||
|
||||
// cleanup locks
|
||||
TRI_DestroySpin(&OutputPrefixLock);
|
||||
TRI_DestroySpin(&AppendersLock);
|
||||
|
|
|
@ -288,6 +288,15 @@ size_t TRI_LengthStringBuffer (TRI_string_buffer_t const * self) {
|
|||
return (size_t) (self->_current - self->_buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief increases length of the character buffer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_IncreaseLengthStringBuffer (TRI_string_buffer_t * self, size_t n)
|
||||
{
|
||||
self->_current += n;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns true if buffer is empty
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -164,6 +164,12 @@ char const * TRI_EndStringBuffer (TRI_string_buffer_t const * self);
|
|||
|
||||
size_t TRI_LengthStringBuffer (TRI_string_buffer_t const * self);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief increases length of the character buffer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_IncreaseLengthStringBuffer (TRI_string_buffer_t * self, size_t n);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns true if buffer is empty
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -230,8 +230,8 @@ void ApplicationEndpointServer::setupOptions (map<string, ProgramOptionsDescript
|
|||
("server.cafile", &_cafile, "file containing the CA certificates of clients")
|
||||
("server.ssl-protocol", &_sslProtocol, "1 = SSLv2, 2 = SSLv23, 3 = SSLv3, 4 = TLSv1")
|
||||
("server.ssl-cache", &_sslCache, "use SSL session caching")
|
||||
("server.ssl-options", &_sslOptions, "ssl options, see OpenSSL documentation")
|
||||
("server.ssl-cipher-list", &_sslCipherList, "ssl cipher list, see OpenSSL documentation")
|
||||
("server.ssl-options", &_sslOptions, "SSL options, see OpenSSL documentation")
|
||||
("server.ssl-cipher-list", &_sslCipherList, "SSL cipher list, see OpenSSL documentation")
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ Job::JobType Handler::type () {
|
|||
/// @brief returns the queue name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& Handler::queue () {
|
||||
string const& Handler::queue () const {
|
||||
static string standard = "STANDARD";
|
||||
return standard;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ namespace triagens {
|
|||
/// @brief returns the queue name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual string const& queue ();
|
||||
virtual string const& queue () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief sets the thread which currently dealing with the job
|
||||
|
|
|
@ -552,8 +552,7 @@ void HttpResponse::setCookie (string const& name, string const& value,
|
|||
}
|
||||
|
||||
char const* l = StringUtils::duplicate(buffer->c_str());
|
||||
buffer->clear();
|
||||
free(buffer);
|
||||
delete buffer;
|
||||
_cookies.push_back(l);
|
||||
|
||||
_freeables.push_back(l);
|
||||
|
|
|
@ -67,7 +67,6 @@ SocketTask::SocketTask (TRI_socket_t socket, double keepAliveTimeout)
|
|||
ownBuffer(true),
|
||||
writeLength(0) {
|
||||
_readBuffer = new StringBuffer(TRI_UNKNOWN_MEM_ZONE);
|
||||
tmpReadBuffer = new char[READ_BLOCK_SIZE];
|
||||
|
||||
ConnectionStatisticsAgent::acquire();
|
||||
ConnectionStatisticsAgentSetStart(this);
|
||||
|
@ -102,8 +101,6 @@ SocketTask::~SocketTask () {
|
|||
|
||||
delete _readBuffer;
|
||||
|
||||
delete[] tmpReadBuffer;
|
||||
|
||||
ConnectionStatisticsAgentSetEnd(this);
|
||||
ConnectionStatisticsAgent::release();
|
||||
}
|
||||
|
@ -151,12 +148,19 @@ void SocketTask::setKeepAliveTimeout (double timeout) {
|
|||
bool SocketTask::fillReadBuffer (bool& closed) {
|
||||
closed = false;
|
||||
|
||||
// reserve some memory for reading
|
||||
if (_readBuffer->reserve(READ_BLOCK_SIZE) == TRI_ERROR_OUT_OF_MEMORY) {
|
||||
// out of memory
|
||||
LOGGER_TRACE("out of memory");
|
||||
|
||||
int nr = TRI_READ_SOCKET(_commSocket, tmpReadBuffer, READ_BLOCK_SIZE, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
int nr = TRI_READ_SOCKET(_commSocket, _readBuffer->end(), READ_BLOCK_SIZE, 0);
|
||||
|
||||
|
||||
if (nr > 0) {
|
||||
_readBuffer->appendText(tmpReadBuffer, nr);
|
||||
_readBuffer->increaseLength(nr);
|
||||
return true;
|
||||
}
|
||||
else if (nr == 0) {
|
||||
|
|
|
@ -374,12 +374,6 @@ namespace triagens {
|
|||
|
||||
TRI_tid_t tid;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief temporary static buffer for read requests
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char * tmpReadBuffer;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -231,9 +231,13 @@ bool ClientConnection::readClientConnection (StringBuffer& stringBuffer) {
|
|||
assert(_socket.fileHandle > 0);
|
||||
|
||||
do {
|
||||
char buffer[READBUFFER_SIZE];
|
||||
// reserve some memory for reading
|
||||
if (stringBuffer.reserve(READBUFFER_SIZE) == TRI_ERROR_OUT_OF_MEMORY) {
|
||||
// out of memory
|
||||
return false;
|
||||
}
|
||||
|
||||
int lenRead = TRI_READ_SOCKET(_socket, buffer, READBUFFER_SIZE - 1, 0);
|
||||
int lenRead = TRI_READ_SOCKET(_socket, stringBuffer.end(), READBUFFER_SIZE - 1, 0);
|
||||
|
||||
if (lenRead == -1) {
|
||||
// error occurred
|
||||
|
@ -245,7 +249,7 @@ bool ClientConnection::readClientConnection (StringBuffer& stringBuffer) {
|
|||
break;
|
||||
}
|
||||
|
||||
stringBuffer.appendText(buffer, lenRead);
|
||||
stringBuffer.increaseLength(lenRead);
|
||||
}
|
||||
while (readable());
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ bool SslClientConnection::writeClientConnection (void* buffer, size_t length, si
|
|||
case SSL_ERROR_WANT_CONNECT:
|
||||
case SSL_ERROR_SYSCALL:
|
||||
default: {
|
||||
/* fallthrough */
|
||||
/* fall through */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,13 +244,17 @@ bool SslClientConnection::readClientConnection (StringBuffer& stringBuffer) {
|
|||
}
|
||||
|
||||
do {
|
||||
char buffer[READBUFFER_SIZE];
|
||||
// reserve some memory for reading
|
||||
if (stringBuffer.reserve(READBUFFER_SIZE) == TRI_ERROR_OUT_OF_MEMORY) {
|
||||
// out of memory
|
||||
return false;
|
||||
}
|
||||
|
||||
int lenRead = SSL_read(_ssl, buffer, READBUFFER_SIZE - 1);
|
||||
int lenRead = SSL_read(_ssl, stringBuffer.end(), READBUFFER_SIZE - 1);
|
||||
|
||||
switch (SSL_get_error(_ssl, lenRead)) {
|
||||
case SSL_ERROR_NONE:
|
||||
stringBuffer.appendText(buffer, lenRead);
|
||||
stringBuffer.increaseLength(lenRead);
|
||||
break;
|
||||
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
#ifndef _ZLIBIOAPI64_H
|
||||
#define _ZLIBIOAPI64_H
|
||||
|
||||
#ifdef _Z_OF
|
||||
#undef OF
|
||||
#define OF _Z_OF
|
||||
#endif
|
||||
|
||||
#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
|
||||
|
||||
// Linux needs this to support file operation on files larger then 4+GB
|
||||
|
|
Loading…
Reference in New Issue