Source

mod_gridfs / gridfs / mod_gridfs.cpp

Diff from to

gridfs/mod_gridfs.cpp

 	bool cache_max_age_set;
 	int connect_timeout;
 	bool connect_timeout_set;
-	bool slave_ok;
-	bool slave_ok_set;
+	const std::string *read_pref_mode;
 	const std::string *context;
 };
 
 	config->cache_max_age_set = add->cache_max_age_set || base->cache_max_age_set;
 	config->connect_timeout = add->connect_timeout_set ? add->connect_timeout : base->connect_timeout;
 	config->connect_timeout_set = add->connect_timeout_set || base->connect_timeout_set;
-	config->slave_ok = add->slave_ok_set ? add->slave_ok : base->slave_ok;
-	config->slave_ok_set = add->slave_ok_set || base->slave_ok_set;
+	config->read_pref_mode = add->read_pref_mode != 0 ? add->read_pref_mode : base->read_pref_mode;
 	config->context = add->context != 0 ? add->context : base->context;
 	return config;
 }
 	return 0;
 }
 
-//	Handles "GridFSSlaveOk <On|Off>" command
-static const char *gridfs_slave_ok_command(cmd_parms *const command, void *const module_config, int flag)
+//	Handles "GridFSReadPrefMode <read preference mode>" command
+static const char *gridfs_read_pref_mode_command(cmd_parms *const command, void *const module_config, const char *const argument)
 {
 	gridfs_config *const config = static_cast<gridfs_config *>(module_config);
-	config->slave_ok = flag != 0;
-	config->slave_ok_set = true;
+	void *const read_pref_mode_data = apr_palloc(command->pool, sizeof(std::string));
+	if (read_pref_mode_data == 0)
+		return "GridFSReadPrefMode failed to allocate data.";
+	std::string *read_pref_mode;
+	try
+	{
+		read_pref_mode = new (read_pref_mode_data) std::string(argument);
+	}
+	catch (...)
+	{
+		return "GridFSReadPrefMode exception.";
+	}
+	config->read_pref_mode = read_pref_mode;
 	return 0;
 }
 
 		return HTTP_INTERNAL_SERVER_ERROR;
 	}
 	request->filename = const_cast<char *>(filename);
+	const std::string& database = *config->database;
 	int result;
 	apr_bucket_brigade *brigade = 0;
 	try
 			try
 			{
 				std::auto_ptr<mongo::ScopedDbConnection> connection(mongo::ScopedDbConnection::getScopedDbConnection(*config->connection_string, config->connect_timeout));
-				const std::string& database = *config->database;
 
 				mongo::DBClientBase& client = connection->conn();
 				if (config->username != 0 && config->password != 0)
 					if (!client.auth(database, username, *config->password, errmsg))
 					{
 						connection->done();
-						ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: Failed to authenticate user '%s' with database '%s': %s.", 
+						ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: Failed to authenticate user '%s' (database: '%s'): %s.", 
 							username.c_str(), database.c_str(), errmsg.c_str());
 						return HTTP_INTERNAL_SERVER_ERROR;
 					}
 				}
 
 				const mongo::GridFS gridfs(client, database);
-				mongo::GridFile gridfile = gridfs.findFile(filename, config->slave_ok);
+				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) :
+					gridfs.findFile(filename);
 				if (!gridfile.exists())
 				{
-					if (config->slave_ok)
+					if (read_pref_mode_set && *config->read_pref_mode != "primary")
 					{
-						gridfile = gridfs.findFile(filename, false);
+						gridfile = gridfs.findFile(filename);
 						if (!gridfile.exists())
 						{
 							connection->done();
 					if (num_chunks == 0)
 					{
 						connection->done();
-						ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: No chunks available for file '%s'.", filename); 
+						ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: No chunks available for file '%s' (database: '%s').", filename, database.c_str()); 
 						return HTTP_INTERNAL_SERVER_ERROR;
 					}
 					if (brigade == 0)
 					if (content_length != file_length)
 					{
 						connection->done();
-						ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, result, request, "mod_gridfs: Mismatching files/chunks length for file '%s' (difference: %d).", filename, static_cast<int>(file_length - content_length));
+						ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, result, request, "mod_gridfs: Mismatching files/chunks length for file '%s' (difference: %d, database: '%s').", filename, static_cast<int>(file_length - content_length), database.c_str());
 						return HTTP_INTERNAL_SERVER_ERROR;
 					}
 				}
 				case 10009:	//	ReplicaSetMonitor no master found for set
 				case 10276:	//	DBClientBase::findN: transport error
 				case 11002:	//	pool socket exception
-					ap_log_rerror(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, result, request, "mod_gridfs: Retrying after MongoDB exception for file '%s' (code: %d): %s.", filename, code, exception.what()); 
+					ap_log_rerror(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, result, request, "mod_gridfs: Retrying after MongoDB exception for file '%s' (code: %d, database: '%s'): %s.", filename, code, database.c_str(), exception.what()); 
 					break;
 
 				default:
 	}
 	catch (const mongo::DBException& exception)
 	{
-		ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: Unhandled MongoDB exception occured for file '%s' (code: %d): %s.", filename, exception.getCode(), exception.what()); 
+		ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: Unhandled MongoDB exception occured for file '%s' (code: %d, database: '%s'): %s.", filename, exception.getCode(), database.c_str(), exception.what()); 
 		return HTTP_INTERNAL_SERVER_ERROR;
 	}
 	catch (const std::exception& exception)
 	{
-		ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: Unhandled exception occured for file '%s': %s.", filename, exception.what()); 
+		ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: Unhandled exception occured for file '%s' (database: '%s'): %s.", filename, database.c_str(), exception.what()); 
 		return HTTP_INTERNAL_SERVER_ERROR;
 	}
 	catch (...)
 	{
-		ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: Unknown unhandled exception occured for file '%s'.", filename); 
+		ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, request, "mod_gridfs: Unknown unhandled exception occured for file '%s' (database: '%s').", filename, database.c_str()); 
 		return HTTP_INTERNAL_SERVER_ERROR;
 	}
 	if (brigade != 0)
 	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)."),
 	AP_INIT_TAKE1("GridFSConnectTimeout", reinterpret_cast<cmd_func>(gridfs_connect_timeout_command), 0, OR_FILEINFO, "GridFS connect timeout (seconds, 0 for infinite)."),
-	AP_INIT_FLAG("GridFSSlaveOk", reinterpret_cast<cmd_func>(gridfs_slave_ok_command), 0, OR_FILEINFO, "GridFS slaveOk flag."),
+	AP_INIT_TAKE1("GridFSReadPrefMode", reinterpret_cast<cmd_func>(gridfs_read_pref_mode_command), 0, OR_FILEINFO, "GridFS read preference mode."),	
 	{0}
 };