1
0
Fork 0

Merge branch 'sharding' of https://github.com/triAGENS/ArangoDB into sharding

This commit is contained in:
Jan Steemann 2014-01-16 17:03:23 +01:00
commit 9cbc6d55ca
11 changed files with 282 additions and 87 deletions

View File

@ -828,6 +828,7 @@ int ClusterInfo::createCollectionCoordinator (string const& databaseName,
while (TRI_microtime() <= endtime) { while (TRI_microtime() <= endtime) {
res = ac.getValues(where, true); res = ac.getValues(where, true);
if (res.successful() && res.parse(where+"/", false)) { if (res.successful() && res.parse(where+"/", false)) {
cout << "Seeing " << res._values.size() << "shards." << endl;
if (res._values.size() == numberOfShards) { if (res._values.size() == numberOfShards) {
map<string, AgencyCommResultEntry>::iterator it; map<string, AgencyCommResultEntry>::iterator it;
string tmpMsg = ""; string tmpMsg = "";

View File

@ -241,7 +241,8 @@ static char const* GetCurrentDatabaseName () {
#ifdef TRI_ENABLE_CLUSTER #ifdef TRI_ENABLE_CLUSTER
static TRI_vocbase_col_t* CollectionInfoToVocBaseCol (TRI_vocbase_t* vocbase, static TRI_vocbase_col_t* CollectionInfoToVocBaseCol (TRI_vocbase_t* vocbase,
CollectionInfo const& ci) { CollectionInfo const& ci,
char const* dbname) {
TRI_vocbase_col_t* c = (TRI_vocbase_col_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_vocbase_col_t), false); TRI_vocbase_col_t* c = (TRI_vocbase_col_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_vocbase_col_t), false);
if (c == 0) { if (c == 0) {
@ -262,7 +263,7 @@ static TRI_vocbase_col_t* CollectionInfoToVocBaseCol (TRI_vocbase_t* vocbase,
memset(c->_path, 0, TRI_COL_PATH_LENGTH + 1); memset(c->_path, 0, TRI_COL_PATH_LENGTH + 1);
memset(c->_dbName, 0, TRI_COL_NAME_LENGTH + 1); memset(c->_dbName, 0, TRI_COL_NAME_LENGTH + 1);
memcpy(c->_dbName, vocbase->_name, strlen(vocbase->_name)); memcpy(c->_dbName, dbname, strlen(dbname));
c->_canDrop = true; c->_canDrop = true;
c->_canUnload = true; c->_canUnload = true;
@ -287,7 +288,8 @@ static TRI_vector_pointer_t GetCollectionsCluster (TRI_vocbase_t* vocbase,
const std::vector<CollectionInfo>& collections = ClusterInfo::instance()->getCollections(database); const std::vector<CollectionInfo>& collections = ClusterInfo::instance()->getCollections(database);
for (size_t i = 0, n = collections.size(); i < n; ++i) { for (size_t i = 0, n = collections.size(); i < n; ++i) {
TRI_vocbase_col_t* c = CollectionInfoToVocBaseCol(vocbase, collections[i]); TRI_vocbase_col_t* c = CollectionInfoToVocBaseCol(vocbase, collections[i],
database);
if (c != 0) { if (c != 0) {
TRI_PushBackVectorPointer(&result, c); TRI_PushBackVectorPointer(&result, c);
@ -1796,7 +1798,8 @@ static v8::Handle<v8::Value> CreateCollectionCoordinator (
v8::Arguments const& argv, v8::Arguments const& argv,
TRI_col_type_e collectionType, TRI_col_type_e collectionType,
std::string const& databaseName, std::string const& databaseName,
TRI_col_info_t& parameter) { TRI_col_info_t& parameter,
TRI_vocbase_t* vocbase) {
v8::HandleScope scope; v8::HandleScope scope;
const string name = TRI_ObjectToString(argv[0]); const string name = TRI_ObjectToString(argv[0]);
@ -1907,7 +1910,11 @@ static v8::Handle<v8::Value> CreateCollectionCoordinator (
if (myerrno != TRI_ERROR_NO_ERROR) { if (myerrno != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION_MESSAGE(scope, myerrno, errorMsg); TRI_V8_EXCEPTION_MESSAGE(scope, myerrno, errorMsg);
} }
return scope.Close(v8::True()); ci->loadCurrentCollections();
CollectionInfo const& c = ci->getCollection( databaseName, cid );
TRI_vocbase_col_t* newcoll = CollectionInfoToVocBaseCol(vocbase, c,
databaseName.c_str());
return scope.Close(TRI_WrapCollection(newcoll));
} }
#endif #endif
@ -2023,7 +2030,7 @@ static v8::Handle<v8::Value> CreateVocBase (v8::Arguments const& argv,
TRI_V8_EXCEPTION_PARAMETER(scope, "selected database is not a cluster database"); TRI_V8_EXCEPTION_PARAMETER(scope, "selected database is not a cluster database");
} }
v8::Handle<v8::Value> result = CreateCollectionCoordinator(argv, collectionType, originalDatabase, parameter); v8::Handle<v8::Value> result = CreateCollectionCoordinator(argv, collectionType, originalDatabase, parameter, vocbase);
TRI_FreeCollectionInfoOptions(&parameter); TRI_FreeCollectionInfoOptions(&parameter);
return scope.Close(result); return scope.Close(result);
@ -7407,7 +7414,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> name,
} }
CollectionInfo const& ci = ClusterInfo::instance()->getCollection(originalDatabase, std::string(key)); CollectionInfo const& ci = ClusterInfo::instance()->getCollection(originalDatabase, std::string(key));
collection = CollectionInfoToVocBaseCol(vocbase, ci); collection = CollectionInfoToVocBaseCol(vocbase, ci, originalDatabase);
} }
else { else {
// look up the collection regularly // look up the collection regularly

View File

@ -95,6 +95,14 @@ button {
background-color: #F89406; background-color: #F89406;
} }
.btn-inactive {
background-color: lightgrey;
}
.btn-inactive:hover {
background-color: grey;
}
.btn-group > .btn + .dropdown-toggle { .btn-group > .btn + .dropdown-toggle {
box-shadow: 1px 0 0 rgba(255, 255, 255, 0.125) inset, 0 1px 0 rgba(255, 255, 255, 0.2) inset; box-shadow: 1px 0 0 rgba(255, 255, 255, 0.125) inset, 0 1px 0 rgba(255, 255, 255, 0.2) inset;
} }
@ -271,6 +279,14 @@ button.gv-zoom-btn.pan-bottom{
background-image:url("../img/gv_arrow_bottom.png"); background-image:url("../img/gv_arrow_bottom.png");
} }
button.btn-overview { /* Cluster View */
button.btn-overview, button.btn-server {
margin: 5px; margin: 5px;
} }
button.btn-server {
width: 120px;
}

View File

@ -15,6 +15,14 @@ h3.clusterColumnHeader {
text-align: center; text-align: center;
} }
h4.domino-header {
margin: 0px;
padding-top: 10px;
padding-bottom: 10px;
padding-right: 0px;
padding-left: 0px;
}
div.clusterAmounts { div.clusterAmounts {
position: absolute; position: absolute;
left: 0px; left: 0px;
@ -50,26 +58,30 @@ div.tile-right {
margin-left: 20px; margin-left: 20px;
} }
.btn-success { div.domino {
background: #8AA051; float: left;
text-align: center;
background-color: #f4f3f3;
cursor: pointer;
margin: 5px;
width: 210px;
} }
.btn-success:hover { hr.domino-line {
background: #788F3D; margin: 0px 5px;
border-width: 1px;
border-top-color: #686766;
border-bottom-color: #333232;
} }
.btn-danger { div.domino-upper, div.domino-lower {
background-color: #DA4F49; height: 100px;
margin: 5px;
}
div.domino-upper {
margin-bottom: 0px;
}
div.domino-lower {
margin-top: 0px;
} }
.btn-danger:hover {
background-color: #BE342E;
}
.btn-warning {
background-color: #FAA732;
}
.btn-warning:hover {
background-color: #F89406;
}

View File

@ -1,4 +1,19 @@
<% var statusClass = function(s) {
switch (s) {
case "ok":
return "success";
case "warning":
return "warning";
case "critical":
return "danger";
}
};
%>
<h3 class="clusterColumnHeader">Databases</h3> <h3 class="clusterColumnHeader">Databases</h3>
<button id="_system" class="database">_system</button> <ul>
<button id="myDatabase" class="database">myDatabase</button> <% _.each(databases, function(v) { %>
<button id="otherDatabase" class="database">otherDatabase</button> <li>
<button id="<%=v.name %>" class="btn btn-server btn-<%=statusClass(v.status)%> database"><%=v.name %></button>
</li>
<% }); %>
</ul>

View File

@ -1,10 +1,21 @@
<% var statusClass = function(s) {
switch (s) {
case "ok":
return "success";
case "warning":
return "warning";
case "critical":
return "danger";
}
};
%>
<h3 class="clusterColumnHeader">DB Server</h3> <h3 class="clusterColumnHeader">DB Server</h3>
<% if (minify) { %> <% if (minify) { %>
<div> <div>
<ul> <ul>
<% _.each(servers, function(v) { %> <% _.each(servers, function(v) { %>
<li> <li>
<button id="<%=v.primary.name %>" class="server"><%=v.primary.name %></button> <button id="<%=v.primary.name %>" class="btn btn-server btn-<%=statusClass(v.primary.status)%> server"><%=v.primary.name %></button>
</li> </li>
<% }); %> <% }); %>
</ul> </ul>
@ -12,11 +23,20 @@
<% } else { %> <% } else { %>
<% _.each(servers, function(v) { %> <% _.each(servers, function(v) { %>
<div id="<%=v.primary.name %>" class="domino server"> <div id="<%=v.primary.name %>" class="domino server">
<span><%=v.primary.name%></span> <div class="domino-upper btn-<%=statusClass(v.primary.status)%>">
<span><%=v.primary.url%></span> <h4 class="domino-header"><%=v.primary.name%></h4>
<span><%=v.primary.url%></span>
</div>
<hr class="domino-line"/>
<% if (v.secondary) { %> <% if (v.secondary) { %>
<span><%=v.secondary.name%></span> <div class="domino-lower btn-<%=statusClass(v.secondary.status)%>">
<span><%=v.secondary.url%></span> <h4 class="domino-header"><%=v.secondary.name%></h4>
<span><%=v.secondary.url%></span>
</div>
<% } else {%>
<div class="domino-lower btn-inactive">
<h4 class="domino-header">Not configured</h4>
</div>
<% } %> <% } %>
</div> </div>
<% }); %> <% }); %>

View File

@ -16,6 +16,22 @@
initialize: function() { initialize: function() {
this.colView = new window.ClusterCollectionView(); this.colView = new window.ClusterCollectionView();
this.fakeData = {
databases: [
{
name: "_system",
status: "ok"
},
{
name: "myDatabase",
status: "warning"
},
{
name: "otherDatabase",
status: "critical"
}
]
};
}, },
loadDatabase: function(e) { loadDatabase: function(e) {
@ -24,7 +40,9 @@
}, },
render: function(){ render: function(){
$(this.el).html(this.template.render({})); $(this.el).html(this.template.render({
databases: this.fakeData.databases
}));
return this; return this;
} }

View File

@ -52,6 +52,14 @@ var uiMatchers = uiMatchers || {};
return el.hasClass(name); return el.hasClass(name);
}, },
toNotHaveClass: function(name) {
var el = $(this.actual);
this.message = function() {
return "Expected \"" + el.attr("class") + "\" to not contain " + name;
};
return !el.hasClass(name);
},
toBeADropdownMenu: function() { toBeADropdownMenu: function() {
var div = this.actual, var div = this.actual,
btn = div.children[0], btn = div.children[0],

View File

@ -1,7 +1,7 @@
/*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true, browser: true*/ /*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true, browser: true*/
/*global describe, beforeEach, afterEach, it, */ /*global describe, beforeEach, afterEach, it, */
/*global spyOn, expect*/ /*global spyOn, expect*/
/*global templateEngine, $*/ /*global templateEngine, $, uiMatchers*/
(function() { (function() {
"use strict"; "use strict";
@ -16,6 +16,7 @@
render: function(){} render: function(){}
}; };
spyOn(window, "ClusterCollectionView").andReturn(colView); spyOn(window, "ClusterCollectionView").andReturn(colView);
uiMatchers.define(this);
}); });
afterEach(function() { afterEach(function() {
@ -33,46 +34,81 @@
describe("rendering", function() { describe("rendering", function() {
var db1, db2, db3, databases,
checkButtonContent = function(db, cls) {
var btn = document.getElementById(db.name);
expect(btn).toBeOfClass("btn");
expect(btn).toBeOfClass("btn-server");
expect(btn).toBeOfClass("database");
expect(btn).toBeOfClass("btn-" + cls);
expect($(btn).text()).toEqual(db.name);
};
beforeEach(function() { beforeEach(function() {
spyOn(colView, "render"); spyOn(colView, "render");
db1 = {
name: "_system",
status: "ok"
};
db2 = {
name: "myDatabase",
status: "warning"
};
db3 = {
name: "otherDatabase",
status: "critical"
};
databases = [
db1,
db2,
db3
];
view = new window.ClusterDatabaseView(); view = new window.ClusterDatabaseView();
view.fakeData.databases = databases;
view.render();
}); });
it("should not render the Server view", function() { it("should not render the Server view", function() {
view.render();
expect(colView.render).not.toHaveBeenCalled(); expect(colView.render).not.toHaveBeenCalled();
}); });
});
describe("user actions", function() { it("should render the ok database", function() {
var db; checkButtonContent(db1, "success");
beforeEach(function() {
spyOn(colView, "render");
view = new window.ClusterDatabaseView();
view.render();
}); });
it("should be able to navigate to _system", function() { it("should render the warning database", function() {
db = "_system"; checkButtonContent(db2, "warning");
$("#" + db).click();
expect(colView.render).toHaveBeenCalledWith(db);
}); });
it("should be able to navigate to myDatabase", function() { it("should render the error database", function() {
db = "myDatabase"; checkButtonContent(db3, "danger");
$("#" + db).click();
expect(colView.render).toHaveBeenCalledWith(db);
}); });
it("should be able to navigate to otherDatabase", function() { describe("user actions", function() {
db = "otherDatabase"; var db;
$("#" + db).click();
expect(colView.render).toHaveBeenCalledWith(db); it("should be able to navigate to _system", function() {
db = "_system";
$("#" + db).click();
expect(colView.render).toHaveBeenCalledWith(db);
});
it("should be able to navigate to myDatabase", function() {
db = "myDatabase";
$("#" + db).click();
expect(colView.render).toHaveBeenCalledWith(db);
});
it("should be able to navigate to otherDatabase", function() {
db = "otherDatabase";
$("#" + db).click();
expect(colView.render).toHaveBeenCalledWith(db);
});
}); });
}); });
}); });
}()); }());

View File

@ -1,7 +1,7 @@
/*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true, browser: true*/ /*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true, browser: true*/
/*global describe, beforeEach, afterEach, it, */ /*global describe, beforeEach, afterEach, it, */
/*global spyOn, expect*/ /*global spyOn, expect*/
/*global templateEngine, $, _*/ /*global templateEngine, $, _, uiMatchers*/
(function() { (function() {
"use strict"; "use strict";
@ -20,33 +20,7 @@
}; };
spyOn(window, "ClusterServerView").andReturn(serverView); spyOn(window, "ClusterServerView").andReturn(serverView);
spyOn(window, "ClusterCoordinatorView").andReturn(coordinatorView); spyOn(window, "ClusterCoordinatorView").andReturn(coordinatorView);
this.addMatchers({ uiMatchers.define(this);
toBeTag: function(name) {
var el = this.actual;
this.message = function() {
return "Expected " + el.tagName.toLowerCase() + " to be a " + name;
};
return el.tagName.toLowerCase() === name;
},
toBeOfClass: function(name) {
var el = $(this.actual);
this.message = function() {
return "Expected \"" + el.attr("class") + "\" to contain " + name;
};
return el.hasClass(name);
},
toNotHaveClass: function(name) {
var el = $(this.actual);
this.message = function() {
return "Expected \"" + el.attr("class") + "\" to not contain " + name;
};
return !el.hasClass(name);
}
});
}); });
afterEach(function() { afterEach(function() {

View File

@ -1,7 +1,7 @@
/*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true, browser: true*/ /*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true, browser: true*/
/*global describe, beforeEach, afterEach, it, */ /*global describe, beforeEach, afterEach, it, */
/*global spyOn, expect*/ /*global spyOn, expect*/
/*global templateEngine, $, _*/ /*global templateEngine, $, _, uiMatchers*/
(function() { (function() {
"use strict"; "use strict";
@ -16,6 +16,7 @@
render: function(){} render: function(){}
}; };
spyOn(window, "ClusterDatabaseView").andReturn(dbView); spyOn(window, "ClusterDatabaseView").andReturn(dbView);
uiMatchers.define(this);
}); });
afterEach(function() { afterEach(function() {
@ -58,6 +59,20 @@
}); });
}); });
},
checkDominoLayout = function(tile) {
var tileElements = tile.children,
upper = tileElements[0],
line = tileElements[1],
lower = tileElements[2];
expect(tile).toBeOfClass("domino");
expect(tile).toBeOfClass("server");
expect(upper).toBeOfClass("domino-upper");
expect(line).toBeOfClass("domino-line");
expect(lower).toBeOfClass("domino-lower");
expect(upper.children[0]).toBeOfClass("domino-header");
expect(lower.children[0]).toBeOfClass("domino-header");
}; };
beforeEach(function() { beforeEach(function() {
@ -134,6 +149,13 @@
describe("minified version", function() { describe("minified version", function() {
var checkButtonContent = function(btn, pair, cls) {
expect(btn).toBeOfClass("btn");
expect(btn).toBeOfClass("server");
expect(btn).toBeOfClass("btn-" + cls);
expect($(btn).text()).toEqual(pair.primary.name);
};
beforeEach(function() { beforeEach(function() {
view.render(true); view.render(true);
}); });
@ -142,13 +164,58 @@
expect($("button", $(div)).length).toEqual(4); expect($("button", $(div)).length).toEqual(4);
}); });
// TODO it("should render the good pair", function() {
checkButtonContent(
document.getElementById(okPair.primary.name),
okPair,
"success"
);
});
it("should render the single primary", function() {
checkButtonContent(
document.getElementById(noBkp.primary.name),
noBkp,
"success"
);
});
it("should render the dead secondary", function() {
checkButtonContent(
document.getElementById(deadBkp.primary.name),
deadBkp,
"success"
);
});
it("should render the dead primary", function() {
checkButtonContent(
document.getElementById(deadPrim.primary.name),
deadPrim,
"danger"
);
});
checkUserActions(); checkUserActions();
}); });
describe("maximised version", function() { describe("maximised version", function() {
var checkDominoContent = function(tile, pair, btn1, btn2) {
var upper = tile.children[0],
lower = tile.children[2];
expect(upper).toBeOfClass("btn-" + btn1);
expect($(upper.children[0]).text()).toEqual(pair.primary.name);
expect($(upper.children[1]).text()).toEqual(pair.primary.url);
expect(lower).toBeOfClass("btn-" + btn2);
if (pair.secondary) {
expect($(lower.children[0]).text()).toEqual(pair.secondary.name);
expect($(lower.children[1]).text()).toEqual(pair.secondary.url);
} else {
expect($(lower.children[0]).text()).toEqual("Not configured");
}
};
beforeEach(function() { beforeEach(function() {
view.render(); view.render();
}); });
@ -159,8 +226,29 @@
it("should render the good pair", function() { it("should render the good pair", function() {
var tile = getTile(okPair.primary.name); var tile = getTile(okPair.primary.name);
checkDominoLayout(tile);
checkDominoContent(tile, okPair, "success", "success");
}); });
it("should render the single primary", function() {
var tile = getTile(noBkp.primary.name);
checkDominoLayout(tile);
checkDominoContent(tile, noBkp, "success", "inactive");
});
it("should render the dead secondary pair", function() {
var tile = getTile(deadBkp.primary.name);
checkDominoLayout(tile);
checkDominoContent(tile, deadBkp, "success", "danger");
});
it("should render the dead primary pair", function() {
var tile = getTile(deadPrim.primary.name);
checkDominoLayout(tile);
checkDominoContent(tile, deadPrim, "danger", "success");
});
checkUserActions(); checkUserActions();
}); });