Commits

Aristarkh Zagorodnikov committed f0d2ab6

Disabled unnecessary index creation (writer should do this, not reader)
Added support for custom GridFS collection prefixes

Comments (0)

Files changed (4)

 Grab MongoDB C++ driver from http://dl.mongodb.org/dl/cxx-driver (2.1+ required, don't use *-latest and unreleased versions), unpack it and go to its directory
 Fix the driver build environment (build static library with PIC to allow module to be built as a shared library):
 	echo 'env.Append(CCFLAGS="-fPIC")' >> SConstruct
-Apply the GridFS read preference patch:
-	patch -d src/mongo/client < /path/to/mod_gridfs/patches/gridfs-readpref
+Apply the GridFS patch:
+	patch -d src/mongo/client < /path/to/mod_gridfs/patches/gridfs
 Build the driver:
 	scons
 
 rm mongodb-linux-x86_64-2.2.2.tgz
 mv mongo-cxx-driver-v2.2 mongo-cxx-driver
 echo 'env.Append(CCFLAGS="-fPIC")' >> mongo-cxx-driver/SConstruct
-patch -d mongo-cxx-driver/src/mongo/client < patches/gridfs-readpref
+patch -d mongo-cxx-driver/src/mongo/client < patches/gridfs
 scons -C mongo-cxx-driver
 make -C gridfs
 
 Configuration:
 GridFSConnection -- sets connection string ("host[:port]" for single hosts, "replicaSetName/host[:port],[host[:port], ...]" for replica sets)
 GridFSDatabase <database> -- sets database name
-GridFSCacheMaxAge <maxAge> -- optional, sets cache max age in seconds (default is 1 week, maximum is 10 years), set to 0 to disable expiration caching (see Notes below)
+GridFSCollectionPrefix <collection prefix> -- optional, sets collection prefix (default is "fs")
+GridFSCacheMaxAge <max age> -- optional, sets cache max age in seconds (default is 1 week, maximum is 10 years), set to 0 to disable expiration caching (see Notes below)
 GridFSConnectTimeout <timeout> -- optional, sets MongoDB connection timeout in seconds (default is 5 seconds)
 GridFSReadPrefMode <mode> -- optional, sets MongoDB read preference mode (MongoDB v2.2+, see http://docs.mongodb.org/manual/applications/replication/#read-preference-modes)
 GridFSUsername <username> -- optional, sets MongoDB authentication user name

gridfs/mod_gridfs.cpp

 //	Retry delay in milliseconds
 const int RETRY_DELAY = 300;
 
+//	Default prefix
+static const std::string DEFAULT_COLLECTION_PREFIX = "fs";
+
 //	Module configuration
 struct gridfs_config
 {
 	const std::string *connection_string;
 	const std::string *database;
+	const std::string *collection_prefix;
 	const std::string *username;
 	const std::string *password;
 	int cache_max_age;
 	const gridfs_config *const add = static_cast<const gridfs_config *>(addv);
 	config->connection_string = add->connection_string != 0 ? add->connection_string : base->connection_string;
 	config->database = add->database != 0 ? add->database : base->database;
+	config->collection_prefix = add->collection_prefix != 0 ? add->collection_prefix : base->collection_prefix;
 	config->username = add->username != 0 ? add->username : base->username;
 	config->password = add->password != 0 ? add->password : base->password;
 	config->cache_max_age = add->cache_max_age_set ? add->cache_max_age : base->cache_max_age;
 	return 0;
 }
 
+//	Handles "GridFSCollectionPrefix <collection prefix>" command
+static const char *gridfs_collection_prefix_command(cmd_parms *const command, void *const module_config, const char *const argument)
+{
+	gridfs_config *const config = static_cast<gridfs_config *>(module_config);
+	void *const collection_prefix_data = apr_palloc(command->pool, sizeof(std::string));
+	if (collection_prefix_data == 0)
+		return "GridFSCollectionPrefix failed to allocate data.";
+	std::string *collection_prefix;
+	try
+	{
+		collection_prefix = new (collection_prefix_data) std::string(argument);
+	}
+	catch (...)
+	{
+		return "GridFSCollectionPrefix exception.";
+	}
+	config->collection_prefix = collection_prefix;
+	return 0;
+}
+
 //	Handles "GridFSUsername <username>" command
 static const char *gridfs_username_command(cmd_parms *const command, void *const module_config, const char *const argument)
 {
 					}
 				}
 
-				const mongo::GridFS gridfs(client, database);
+				const std::string& collection_prefix = config->collection_prefix != 0 ? *config->collection_prefix : DEFAULT_COLLECTION_PREFIX;
+				const mongo::GridFS gridfs(client, database, collection_prefix, false);
 				const bool read_pref_mode_set = config->read_pref_mode != 0;
 				mongo::GridFile gridfile = read_pref_mode_set ?
 					gridfs.findFile(filename, *config->read_pref_mode) :
 {
 	AP_INIT_TAKE1("GridFSConnection", reinterpret_cast<cmd_func>(gridfs_connection_command), 0, OR_FILEINFO, "GridFS connection string."),
 	AP_INIT_TAKE1("GridFSDatabase", reinterpret_cast<cmd_func>(gridfs_database_command), 0, OR_FILEINFO, "GridFS database name."),
+	AP_INIT_TAKE1("GridFSCollectionPrefix", reinterpret_cast<cmd_func>(gridfs_collection_prefix_command), 0, OR_FILEINFO, "GridFS collection prefix."),
 	AP_INIT_TAKE1("GridFSUsername", reinterpret_cast<cmd_func>(gridfs_username_command), 0, OR_FILEINFO, "GridFS database authentication username."),
 	AP_INIT_TAKE1("GridFSPassword", reinterpret_cast<cmd_func>(gridfs_password_command), 0, OR_FILEINFO, "GridFS database authentication password."),	
 	AP_INIT_TAKE1("GridFSCacheMaxAge", reinterpret_cast<cmd_func>(gridfs_cache_max_age_command), 0, OR_FILEINFO, "GridFS cache max age (seconds, 0 to disable expiration)."),
+--- mongo-cxx-driver/src/mongo/client/gridfs.h	2012-08-13 21:38:00.000000000 +0400
++++ mongo-cxx-driver/src/mongo/client/gridfs.h	2012-12-20 15:26:10.000000000 +0400
+@@ -60,7 +60,7 @@
+          * @param dbName - root database name
+          * @param prefix - if you want your data somewhere besides <dbname>.fs
+          */
+-        GridFS( DBClientBase& client , const string& dbName , const string& prefix="fs" );
++        GridFS( DBClientBase& client , const string& dbName , const string& prefix="fs" , bool ensureIndexes = true );
+         ~GridFS();
+ 
+         /**
+@@ -103,22 +103,22 @@
+         /**
+          * returns a file object matching the query
+          */
+-        GridFile findFile( BSONObj query ) const;
++        GridFile findFile( BSONObj query , const string& readPrefMode = "" ) const;
+ 
+         /**
+          * equiv to findFile( { filename : filename } )
+          */
+-        GridFile findFile( const string& fileName ) const;
++        GridFile findFile( const string& fileName , const string& readPrefMode = "" ) const;
+ 
+         /**
+          * convenience method to get all the files
+          */
+-        auto_ptr<DBClientCursor> list() const;
++        auto_ptr<DBClientCursor> list( const string& readPrefMode = "" ) const;
+ 
+         /**
+          * convenience method to get all the files with a filter
+          */
+-        auto_ptr<DBClientCursor> list( BSONObj query ) const;
++        auto_ptr<DBClientCursor> list( BSONObj query , const string& readPrefMode = "" ) const;
+ 
+     private:
+         DBClientBase& _client;
+@@ -194,12 +194,13 @@
+         gridfs_offset write( const string& where ) const;
+ 
+     private:
+-        GridFile(const GridFS * grid , BSONObj obj );
++        GridFile(const GridFS * grid , BSONObj obj , const string& readPrefMode );
+ 
+         void _exists() const;
+ 
+         const GridFS * _grid;
+         BSONObj        _obj;
++        string         _readPrefMode;
+ 
+         friend class GridFS;
+     };
+--- mongo-cxx-driver/src/mongo/client/gridfs.cpp	2012-08-13 21:38:00.000000000 +0400
++++ mongo-cxx-driver/src/mongo/client/gridfs.cpp	2012-12-20 15:26:32.000000000 +0400
+@@ -52,13 +52,15 @@
+     }
+ 
+ 
+-    GridFS::GridFS( DBClientBase& client , const string& dbName , const string& prefix ) : _client( client ) , _dbName( dbName ) , _prefix( prefix ) {
++    GridFS::GridFS( DBClientBase& client , const string& dbName , const string& prefix , const bool ensureIndexes ) : _client( client ) , _dbName( dbName ) , _prefix( prefix ) {
+         _filesNS = dbName + "." + prefix + ".files";
+         _chunksNS = dbName + "." + prefix + ".chunks";
+         _chunkSize = DEFAULT_CHUNK_SIZE;
+ 
+-        client.ensureIndex( _filesNS , BSON( "filename" << 1 ) );
+-        client.ensureIndex( _chunksNS , BSON( "files_id" << 1 << "n" << 1 ) );
++        if (ensureIndexes) {
++            client.ensureIndex( _filesNS , BSON( "filename" << 1 ) );
++            client.ensureIndex( _chunksNS , BSON( "files_id" << 1 << "n" << 1 ) );
++        }
+     }
+ 
+     GridFS::~GridFS() {
+@@ -184,25 +186,35 @@
+         }
+     }
+ 
+-    GridFile::GridFile(const GridFS * grid , BSONObj obj ) {
++    GridFile::GridFile(const GridFS * grid , BSONObj obj , const string& readPrefMode ) {
+         _grid = grid;
+         _obj = obj;
++        _readPrefMode = readPrefMode;
+     }
+ 
+-    GridFile GridFS::findFile( const string& fileName ) const {
+-        return findFile( BSON( "filename" << fileName ) );
++    GridFile GridFS::findFile( const string& fileName, const string& readPrefMode ) const {
++        return findFile( BSON( "filename" << fileName ) , readPrefMode );
+     };
+ 
+-    GridFile GridFS::findFile( BSONObj query ) const {
+-        query = BSON("query" << query << "orderby" << BSON("uploadDate" << -1));
+-        return GridFile( this , _client.findOne( _filesNS.c_str() , query ) );
++    GridFile GridFS::findFile( BSONObj query, const string& readPrefMode ) const {
++        BSONObjBuilder b;
++        b.append("query", query);
++        b.append("orderby", BSON("uploadDate" << -1));
++        if (!readPrefMode.empty()) {
++            b.append("$readPreference", BSON("mode" << readPrefMode));
++        }
++        query = b.obj();
++        return GridFile( this , _client.findOne( _filesNS.c_str() , query ) , readPrefMode );
+     }
+ 
+-    auto_ptr<DBClientCursor> GridFS::list() const {
+-        return _client.query( _filesNS.c_str() , BSONObj() );
++    auto_ptr<DBClientCursor> GridFS::list( const string& readPrefMode ) const {
++        return list( BSONObj() , readPrefMode );
+     }
+ 
+-    auto_ptr<DBClientCursor> GridFS::list( BSONObj o ) const {
++    auto_ptr<DBClientCursor> GridFS::list( BSONObj o, const string& readPrefMode ) const {
++        if (!readPrefMode.empty()) {
++        	o = BSON("query" << o << "$readPreference" << BSON("mode" << readPrefMode));
++        }
+         return _client.query( _filesNS.c_str() , o );
+     }
+ 
+@@ -220,8 +232,12 @@
+         BSONObjBuilder b;
+         b.appendAs( _obj["_id"] , "files_id" );
+         b.append( "n" , n );
++        BSONObj q = b.obj();
++        if (!_readPrefMode.empty()) {
++        	q = BSON("query" << q << "$readPreference" << BSON("mode" << _readPrefMode));
++        }
+ 
+-        BSONObj o = _grid->_client.findOne( _grid->_chunksNS.c_str() , b.obj() );
++        BSONObj o = _grid->_client.findOne( _grid->_chunksNS.c_str() , q );
+         uassert( 10014 ,  "chunk is empty!" , ! o.isEmpty() );
+         return GridFSChunk(o);
+     }

patches/gridfs-readpref

---- mongo-cxx-driver/src/mongo/client/gridfs.h	2012-08-13 21:38:00.000000000 +0400
-+++ mongo-cxx-driver/src/mongo/client/gridfs.h	2012-12-18 14:13:46.000000000 +0400
-@@ -103,22 +103,22 @@
-         /**
-          * returns a file object matching the query
-          */
--        GridFile findFile( BSONObj query ) const;
-+        GridFile findFile( BSONObj query , const string& readPrefMode = "" ) const;
- 
-         /**
-          * equiv to findFile( { filename : filename } )
-          */
--        GridFile findFile( const string& fileName ) const;
-+        GridFile findFile( const string& fileName , const string& readPrefMode = "" ) const;
- 
-         /**
-          * convenience method to get all the files
-          */
--        auto_ptr<DBClientCursor> list() const;
-+        auto_ptr<DBClientCursor> list( const string& readPrefMode = "" ) const;
- 
-         /**
-          * convenience method to get all the files with a filter
-          */
--        auto_ptr<DBClientCursor> list( BSONObj query ) const;
-+        auto_ptr<DBClientCursor> list( BSONObj query , const string& readPrefMode = "" ) const;
- 
-     private:
-         DBClientBase& _client;
-@@ -194,12 +194,13 @@
-         gridfs_offset write( const string& where ) const;
- 
-     private:
--        GridFile(const GridFS * grid , BSONObj obj );
-+        GridFile(const GridFS * grid , BSONObj obj , const string& readPrefMode );
- 
-         void _exists() const;
- 
-         const GridFS * _grid;
-         BSONObj        _obj;
-+        string         _readPrefMode;
- 
-         friend class GridFS;
-     };
---- mongo-cxx-driver/src/mongo/client/gridfs.cpp	2012-08-13 21:38:00.000000000 +0400
-+++ mongo-cxx-driver/src/mongo/client/gridfs.cpp	2012-12-18 17:35:05.000000000 +0400
-@@ -184,25 +184,35 @@
-         }
-     }
- 
--    GridFile::GridFile(const GridFS * grid , BSONObj obj ) {
-+    GridFile::GridFile(const GridFS * grid , BSONObj obj , const string& readPrefMode ) {
-         _grid = grid;
-         _obj = obj;
-+        _readPrefMode = readPrefMode;
-     }
- 
--    GridFile GridFS::findFile( const string& fileName ) const {
--        return findFile( BSON( "filename" << fileName ) );
-+    GridFile GridFS::findFile( const string& fileName, const string& readPrefMode ) const {
-+        return findFile( BSON( "filename" << fileName ) , readPrefMode );
-     };
- 
--    GridFile GridFS::findFile( BSONObj query ) const {
--        query = BSON("query" << query << "orderby" << BSON("uploadDate" << -1));
--        return GridFile( this , _client.findOne( _filesNS.c_str() , query ) );
-+    GridFile GridFS::findFile( BSONObj query, const string& readPrefMode ) const {
-+        BSONObjBuilder b;
-+        b.append("query", query);
-+        b.append("orderby", BSON("uploadDate" << -1));
-+        if (!readPrefMode.empty()) {
-+            b.append("$readPreference", BSON("mode" << readPrefMode));
-+        }
-+        query = b.obj();
-+        return GridFile( this , _client.findOne( _filesNS.c_str() , query ) , readPrefMode );
-     }
- 
--    auto_ptr<DBClientCursor> GridFS::list() const {
--        return _client.query( _filesNS.c_str() , BSONObj() );
-+    auto_ptr<DBClientCursor> GridFS::list( const string& readPrefMode ) const {
-+        return list( BSONObj() , readPrefMode );
-     }
- 
--    auto_ptr<DBClientCursor> GridFS::list( BSONObj o ) const {
-+    auto_ptr<DBClientCursor> GridFS::list( BSONObj o, const string& readPrefMode ) const {
-+        if (!readPrefMode.empty()) {
-+        	o = BSON("query" << o << "$readPreference" << BSON("mode" << readPrefMode));
-+        }
-         return _client.query( _filesNS.c_str() , o );
-     }
- 
-@@ -220,8 +230,12 @@
-         BSONObjBuilder b;
-         b.appendAs( _obj["_id"] , "files_id" );
-         b.append( "n" , n );
-+        BSONObj q = b.obj();
-+        if (!_readPrefMode.empty()) {
-+        	q = BSON("query" << q << "$readPreference" << BSON("mode" << _readPrefMode));
-+        }
- 
--        BSONObj o = _grid->_client.findOne( _grid->_chunksNS.c_str() , b.obj() );
-+        BSONObj o = _grid->_client.findOne( _grid->_chunksNS.c_str() , q );
-         uassert( 10014 ,  "chunk is empty!" , ! o.isEmpty() );
-         return GridFSChunk(o);
-     }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.