1 /**
2 	MongoClient class doing connection management. Usually this is a main entry point
3 	for client code.
4 
5 	Copyright: © 2012 RejectedSoftware e.K.
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 conections 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 
68 		// force a connection to cause an exception for wrong URLs
69 		lockConnection();
70 	}
71 
72 	package this(MongoClientSettings settings)
73 	{
74 		m_connections = new ConnectionPool!MongoConnection({
75 			auto ret = new MongoConnection(settings);
76 			ret.connect();
77 			return ret;
78 		});
79 
80 		// force a connection to cause an exception for wrong URLs
81 		lockConnection();
82 	}
83 
84 	/**
85 		Accesses a collection using an absolute path.
86 
87 		The full database.collection path must be specified. To access
88 		collections using a path relative to their database, use getDatabase in
89 		conjunction with MongoDatabase.opIndex.
90 
91 		Returns:
92 			MongoCollection for the given combined database and collectiion name(path)
93 
94 		Examples:
95 			---
96 			auto col = client.getCollection("test.collection");
97 			---
98    */
99 	MongoCollection getCollection(string path)
100 	{
101 		return MongoCollection(this, path);
102 	}
103 
104 	/**
105 		Returns an object representing the specified database.
106 
107 		The returned object allows to access the database entity (which contains
108 		a set of collections). There are two main use cases:
109 
110 		1. Accessing collections using a relative path
111 
112 		2. Performing service commands on the database itself
113 
114 		Note that there is no performance gain in accessing collections via a
115 		relative path compared to getCollection and an absolute path.
116 
117 		Returns:
118 			MongoDatabase instance representing requested database
119 
120 		Examples:
121 			---
122 			auto db = client.getDatabase("test");
123 			auto coll = db["collection"];
124 			---
125 	*/
126 	MongoDatabase getDatabase(string dbName)
127 	{
128 		return MongoDatabase(this, dbName);
129 	}
130 
131 
132 
133 	/**
134 	 	Return a handle to all databases of the server.
135 
136 	 	Returns:
137 	 		An input range of $(D MongoDatabase) objects.
138 
139 	 	Examples:
140 	 		---
141 	 		auto names = client.getDatabaseNames();
142 	 		writeln("Current databases are: ", names);
143 	 		---
144 	 */
145 	auto getDatabases()()
146 	{
147 		import std.algorithm : map;
148 		return lockConnection.listDatabases()
149 			.map!(info => MongoDatabase(this, info.name));
150 	}
151 
152 	package auto lockConnection() { return m_connections.lockConnection(); }
153 }