1 /** 2 MongoClient class doing connection management. Usually this is a main entry point 3 for client code. 4 5 Copyright: © 2012 Sönke Ludwig 6 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 7 Authors: Sönke Ludwig 8 */ 9 module vibe.db.mongo.client; 10 11 public import vibe.db.mongo.collection; 12 public import vibe.db.mongo.database; 13 14 import vibe.core.connectionpool; 15 import vibe.core.log; 16 import vibe.db.mongo.connection; 17 import vibe.db.mongo.settings; 18 19 import core.thread; 20 21 import std.conv; 22 import std.string; 23 import std.range; 24 25 /** 26 Represents a connection to a MongoDB server. 27 28 Note that this class uses a ConnectionPool internally to create and reuse 29 network connections to the server as necessary. It should be reused for all 30 fibers in a thread for optimum performance in high concurrency scenarios. 31 */ 32 final class MongoClient { 33 @safe: 34 35 private { 36 ConnectionPool!MongoConnection m_connections; 37 } 38 39 package this(string host, ushort port) 40 { 41 this("mongodb://" ~ host ~ ":" ~ to!string(port) ~ "/?safe=true"); 42 } 43 44 /** 45 Initializes a MongoDB client using a URL. 46 47 The URL must be in the form documented at 48 $(LINK http://www.mongodb.org/display/DOCS/Connections) which is: 49 50 mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] 51 52 Throws: 53 An exception if the URL cannot be parsed as a valid MongoDB URL. 54 */ 55 package this(string url) 56 { 57 MongoClientSettings settings; 58 auto goodUrl = parseMongoDBUrl(settings, url); 59 60 if(!goodUrl) throw new Exception("Unable to parse mongodb URL: " ~ url); 61 62 m_connections = new ConnectionPool!MongoConnection(() @safe { 63 auto ret = new MongoConnection(settings); 64 ret.connect(); 65 return ret; 66 }, 67 settings.maxConnections 68 ); 69 70 // force a connection to cause an exception for wrong URLs 71 lockConnection(); 72 } 73 74 package this(MongoClientSettings settings) 75 { 76 m_connections = new ConnectionPool!MongoConnection({ 77 auto ret = new MongoConnection(settings); 78 ret.connect(); 79 return ret; 80 }, 81 settings.maxConnections 82 ); 83 84 // force a connection to cause an exception for wrong URLs 85 lockConnection(); 86 } 87 88 /** Disconnects all currently unused connections to the server. 89 */ 90 void cleanupConnections() 91 { 92 m_connections.removeUnused((conn) nothrow @safe { 93 try conn.disconnect(); 94 catch (Exception e) { 95 logWarn("Error thrown during MongoDB connection close: %s", e.msg); 96 try () @trusted { logDebug("Full error: %s", e.toString()); } (); 97 catch (Exception e) {} 98 } 99 }); 100 } 101 102 /** 103 Accesses a collection using an absolute path. 104 105 The full database.collection path must be specified. To access 106 collections using a path relative to their database, use getDatabase in 107 conjunction with MongoDatabase.opIndex. 108 109 Returns: 110 MongoCollection for the given combined database and collection name (path) 111 112 Examples: 113 --- 114 auto col = client.getCollection("test.collection"); 115 --- 116 */ 117 MongoCollection getCollection(string path) 118 { 119 return MongoCollection(this, path); 120 } 121 122 /** 123 Returns an object representing the specified database. 124 125 The returned object allows to access the database entity (which contains 126 a set of collections). There are two main use cases: 127 128 1. Accessing collections using a relative path 129 130 2. Performing service commands on the database itself 131 132 Note that there is no performance gain in accessing collections via a 133 relative path compared to getCollection and an absolute path. 134 135 Returns: 136 MongoDatabase instance representing requested database 137 138 Examples: 139 --- 140 auto db = client.getDatabase("test"); 141 auto coll = db["collection"]; 142 --- 143 */ 144 MongoDatabase getDatabase(string dbName) 145 { 146 return MongoDatabase(this, dbName); 147 } 148 149 150 151 /** 152 Return a handle to all databases of the server. 153 154 Returns: 155 An input range of $(D MongoDatabase) objects. 156 157 Examples: 158 --- 159 auto names = client.getDatabaseNames(); 160 writeln("Current databases are: ", names); 161 --- 162 */ 163 auto getDatabases()() 164 { 165 import std.algorithm : map; 166 return lockConnection.listDatabases() 167 .map!(info => MongoDatabase(this, info.name)); 168 } 169 170 package auto lockConnection() { return m_connections.lockConnection(); } 171 }