/** * Copyright (C) 2010 EdgyTech LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.edgytech.umongo; import com.edgytech.swingfast.EnumListener; import com.edgytech.swingfast.XmlComponentUnit; import com.edgytech.swingfast.XmlUnit; import com.mongodb.BasicDBObject; import com.mongodb.CommandResult; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.Mongo; import java.util.ArrayList; import javax.swing.JPanel; import com.edgytech.umongo.ReplSetPanel.Item; import com.edgytech.swingfast.*; import com.mongodb.*; import java.util.logging.Level; /** * * @author antoine */ public class ReplSetPanel extends BasePanel implements EnumListener<Item> { enum Item { refresh, name, replicas, reconfigure, reconfConfig, addReplica, rsConfig, rsStatus, rsOplogInfo, compareReplicas, crStat, queryOplog, qoStart, qoEnd, qoQuery, sharding, manageTags, tagList, addTag, atTag, removeTag } public ReplSetPanel() { setEnumBinding(Item.values(), this); } public ReplSetNode getReplSetNode() { return (ReplSetNode) node; } @Override protected void updateComponentCustom(JPanel comp) { try { if (getReplSetNode().getShardName() == null) { ((Menu)getBoundUnit(Item.sharding)).enabled = false; } setStringFieldValue(Item.name, getReplSetNode().getName()); String replicas = ""; for (String replica : getReplSetNode().getReplicaNames()) { replicas += replica + ","; } replicas = replicas.substring(0, replicas.length() - 1); setStringFieldValue(Item.replicas, replicas); } catch (Exception e) { UMongo.instance.showError(this.getClass().getSimpleName() + " update", e); } } @Override public void actionPerformed(Item enm, XmlComponentUnit unit, Object src) { } public void rsConfig(ButtonBase button) { final DBCollection col = getReplSetNode().getMongoClient().getDB("local").getCollection("system.replset"); CollectionPanel.doFind(col, null); } public void rsStatus(ButtonBase button) { new DbJobCmd(getReplSetNode().getMongoClient().getDB("admin"), "replSetGetStatus").addJob(); } public void rsOplogInfo(ButtonBase button) { new DbJob() { @Override public Object doRun() { return MongoUtils.getReplicaSetInfo(getReplSetNode().getMongoClient()); } @Override public String getNS() { return null; } @Override public String getShortName() { return "Oplog Info"; } }.addJob(); } public void reconfigure(ButtonBase button) { final DBCollection col = getReplSetNode().getMongoClient().getDB("local").getCollection("system.replset"); DBObject oldConf = col.findOne(); if (oldConf == null) { new InfoDialog(null, "reconfig error", null, "No existing replica set configuration").show(); return; } ((DocBuilderField)getBoundUnit(Item.reconfConfig)).setDBObject(oldConf); if (!((MenuItem)getBoundUnit(Item.reconfigure)).getDialog().show()) return; DBObject config = ((DocBuilderField)getBoundUnit(Item.reconfConfig)).getDBObject(); reconfigure(getReplSetNode(), config); } static public void reconfigure(final ReplSetNode rsNode, DBObject config) { final DBCollection col = rsNode.getMongoClient().getDB("local").getCollection("system.replset"); DBObject oldConf = col.findOne(); int version = ((Integer) oldConf.get("version")) + 1; config.put("version", version); // reconfig usually triggers an error as connections are bounced.. try to absorb it final DBObject cmd = new BasicDBObject("replSetReconfig", config); final DB admin = rsNode.getMongoClient().getDB("admin"); new DbJob() { @Override public Object doRun() { Object res = null; try { res = admin.command(cmd); } catch (MongoException.Network e) { res = new BasicDBObject("msg", "Operation was likely successful, but connection was bounced"); } try { // sleep a bit since it takes time for driver to see change Thread.sleep(6000); } catch (InterruptedException ex) { getLogger().log(Level.WARNING, null, ex); } return res; } @Override public String getNS() { return null; } @Override public String getShortName() { return "RS Reconfig"; } @Override public DBObject getRoot(Object result) { return cmd; } @Override public void wrapUp(Object res) { // try to restructure but changes arent seen for a few seconds super.wrapUp(res); rsNode.structureComponent(); } }.addJob(); } public void addReplica(ButtonBase button) { final DBCollection col = getReplSetNode().getMongoClient().getDB("local").getCollection("system.replset"); DBObject config = col.findOne(); if (config == null) { new InfoDialog(null, "reconfig error", null, "No existing replica set configuration").show(); return; } BasicDBList members = (BasicDBList) config.get("members"); int max = 0; for (int i = 0; i < members.size(); ++i) { int id = (Integer)((DBObject)members.get(i)).get("_id"); if (id > max) max = id; } ReplicaDialog dia = UMongo.instance.getGlobalStore().getReplicaDialog(); if (!dia.show()) return; BasicDBObject conf = dia.getReplicaConfig(max + 1); members.add(conf); reconfigure(getReplSetNode(), config); } public void compareReplicas(ButtonBase button) { final String stat = getStringFieldValue(Item.crStat); new DbJob() { @Override public Object doRun() { ReplSetNode node = getReplSetNode(); if (!node.hasChildren()) return null; ArrayList<MongoClient> svrs = new ArrayList<MongoClient>(); for (XmlUnit unit : node.getChildren()) { ServerNode svr = (ServerNode) unit; MongoClient svrm = svr.getServerMongoClient(); try { svrm.getDatabaseNames(); } catch (Exception e) { continue; } svrs.add(svrm); } BasicDBObject res = new BasicDBObject(); MongoClient m = getReplSetNode().getMongoClient(); for (String dbname : m.getDatabaseNames()) { DB db = m.getDB(dbname); BasicDBObject dbres = new BasicDBObject(); for (String colname: db.getCollectionNames()) { DBCollection col = db.getCollection(colname); BasicDBObject colres = new BasicDBObject(); BasicDBObject values = new BasicDBObject(); boolean same = true; long ref = -1; for (MongoClient svrm : svrs) { DBCollection svrcol = svrm.getDB(dbname).getCollection(colname); long value = 0; if (stat.startsWith("Count")) { value = svrcol.count(); } else if (stat.startsWith("Data Size")) { CommandResult stats = svrcol.getStats(); value = stats.getLong("size"); } values.append(svrm.getConnectPoint(), value); if (ref < 0) ref = value; else if (ref != value) same = false; } if (!same) { colres.append("values", values); dbres.append(colname, colres); } } if (!dbres.isEmpty()) { res.append(dbname, dbres); } } return res; } @Override public String getNS() { return "*"; } @Override public String getShortName() { return "Compare Replicas"; } }.addJob(); } public void queryOplog(ButtonBase button) { final DBCollection oplog = getReplSetNode().getMongoClient().getDB("local").getCollection("oplog.rs"); DBObject start = ((DocBuilderField) getBoundUnit(Item.qoStart)).getDBObject(); DBObject end = ((DocBuilderField) getBoundUnit(Item.qoEnd)).getDBObject(); DBObject extra = ((DocBuilderField) getBoundUnit(Item.qoQuery)).getDBObject(); BasicDBObject query = new BasicDBObject(); BasicDBObject range = new BasicDBObject(); if (start != null) range.put("$gte", start.get("ts")); if (end != null) range.put("$lte", end.get("ts")); query.put("ts", range); if (extra != null) query.putAll(extra); CollectionPanel.doFind(oplog, query, null, null, 0, 0, 0, false, null, Bytes.QUERYOPTION_OPLOGREPLAY); } void refreshTagList() { String shardName = getReplSetNode().getShardName(); if (shardName == null) return; ListArea list = (ListArea) getBoundUnit(Item.tagList); final DB db = ((RouterNode)getReplSetNode().getParentNode()).getMongoClient().getDB("config"); DBObject shard = db.getCollection("shards").findOne(new BasicDBObject("_id", shardName)); if (shard.containsField("tags")) { BasicDBList tags = (BasicDBList) shard.get("tags"); if (tags.size() > 0) { String[] array = new String[tags.size()]; int i = 0; for (Object tag : tags) { array[i++] = (String) tag; } list.items = array; list.structureComponent(); return; } } list.items = null; list.structureComponent(); } public void manageTags(ButtonBase button) { FormDialog dialog = (FormDialog) ((MenuItem) getBoundUnit(Item.manageTags)).getDialog(); refreshTagList(); dialog.show(); } public void addTag(ButtonBase button) { final DB config = ((RouterNode)getReplSetNode().getParentNode()).getMongoClient().getDB("config"); final DBCollection col = config.getCollection("shards"); ((DynamicComboBox)getBoundUnit(Item.atTag)).items = TagRangeDialog.getExistingTags(config); FormDialog dia = (FormDialog) button.getDialog(); if (!dia.show()) return; final String tag = getStringFieldValue(Item.atTag); final DBObject query = new BasicDBObject("_id", getReplSetNode().getShardName()); final DBObject update = new BasicDBObject("$addToSet", new BasicDBObject("tags", tag)); new DbJob() { @Override public Object doRun() { return col.update(query, update); } @Override public String getNS() { return col.getFullName(); } @Override public String getShortName() { return "Add Tag"; } @Override public DBObject getRoot(Object result) { BasicDBObject obj = new BasicDBObject("query", query); obj.put("update", update); return obj; } @Override public void wrapUp(Object res) { super.wrapUp(res); refreshTagList(); } }.addJob(); } public void removeTag(ButtonBase button) { final DB db = ((RouterNode)getReplSetNode().getParentNode()).getMongoClient().getDB("config"); final DBCollection col = db.getCollection("shards"); final String tag = getComponentStringFieldValue(Item.tagList); if (tag == null) return; final DBObject query = new BasicDBObject("_id", getReplSetNode().getShardName()); final DBObject update = new BasicDBObject("$pull", new BasicDBObject("tags", tag)); new DbJob() { @Override public Object doRun() { return col.update(query, update); } @Override public String getNS() { return col.getFullName(); } @Override public String getShortName() { return "Remove Tag"; } @Override public DBObject getRoot(Object result) { BasicDBObject obj = new BasicDBObject("query", query); obj.put("update", update); return obj; } @Override public void wrapUp(Object res) { super.wrapUp(res); refreshTagList(); } }.addJob(); } }