Commits

Aristarkh Zagorodnikov  committed 2dde0f4

More C++ improvements

  • Participants
  • Parent commits 64d661a
  • Branches cxx-driver

Comments (0)

Files changed (1)

File gridfs/mod_gridfs.cpp

 //	Maximum cache age in seconds
 const int MAX_CACHE_MAX_AGE = 86400 * 365 * 10;
 
+//	Maximum connect timeout in seconds
+const int MAX_CONNECT_TIMEOUT = 300;
+
 //	Module configuration
 struct gridfs_config
 {
-	mongo::ConnectionString* connection_string;
-	const char* db_name;
+	mongo::ConnectionString *connection_string;
+	const std::string *database;
 	int cache_max_age;
-	int cache_max_age_set;
+	bool cache_max_age_set;
 	int connect_timeout;
-	int connect_timeout_set;
+	bool connect_timeout_set;
 };
 
 //	Creates module configuration
-static void* gridfs_create_config(apr_pool_t* pool, char* dummy)
+static void *gridfs_create_config(apr_pool_t *const pool, char *const dummy)
 {
-    gridfs_config* config = (gridfs_config*)apr_pcalloc(pool, sizeof(gridfs_config));
-    if (!config)
-    	return 0;
-   	config->cache_max_age = DEFAULT_CACHE_MAX_AGE;
-    config->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
-    return config;
+	gridfs_config *const config = static_cast<gridfs_config *>(apr_pcalloc(pool, sizeof(gridfs_config)));
+	if (!config)
+		return 0;
+	config->cache_max_age = DEFAULT_CACHE_MAX_AGE;
+	config->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
+	return config;
 }
 
 //	Merges module configuration
-static void* gridfs_merge_config(apr_pool_t* pool, void *basev, void *addv)
+static void *gridfs_merge_config(apr_pool_t *const pool, void *const basev, void *const addv)
 {
-    gridfs_config* config = (gridfs_config*)apr_pcalloc(pool, sizeof(gridfs_config));
-    if (!config)
-    	return 0;
-    gridfs_config *base = (gridfs_config*) basev;
-    gridfs_config *add = (gridfs_config*) addv;
-    config->db_name = add->db_name ? add->db_name : base->db_name;
-    config->connection_string = add->connection_string ? add->connection_string : base->connection_string;
-    config->cache_max_age = add->cache_max_age_set ? add->cache_max_age : base->cache_max_age;
-    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;
-    return config;
+	gridfs_config *const config = static_cast<gridfs_config *>(apr_palloc(pool, sizeof(gridfs_config)));
+	if (!config)
+		return 0;
+	const gridfs_config *const base = static_cast<const gridfs_config *>(basev);
+	const gridfs_config *const add = static_cast<const gridfs_config *>(addv);
+	config->connection_string = add->connection_string ? add->connection_string : base->connection_string;
+	config->database = add->database ? add->database : base->database;
+	config->cache_max_age = add->cache_max_age_set ? add->cache_max_age : base->cache_max_age;
+	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;
+	return config;
 }
 
 //	Handles "GridFSConnection <connection string>" command
-static const char* gridfs_connection_command(cmd_parms* command, void* module_config, const char* argument)
+static const char *gridfs_connection_command(cmd_parms *const command, void *const module_config, const char *const argument)
 {
-    gridfs_config* config = (gridfs_config*)module_config;
-    mongo::ConnectionString* connection_string = new mongo::ConnectionString(argument, mongo::ConnectionString::SET);
-    if (!connection_string)
-    	return "failed to allocate connection string";
-    if (!connection_string->isValid())
-    {
-    	delete connection_string;
-    	return "invalid connection string";
-    }
-    delete config->connection_string;
-    config->connection_string = connection_string;
-    return 0;
+	gridfs_config *const config = static_cast<gridfs_config *>(module_config);
+	mongo::ConnectionString *const connection_string = static_cast<mongo::ConnectionString *>(apr_palloc(command->pool, sizeof(mongo::ConnectionString)));
+	if (!connection_string)
+		return "failed to allocate connection string";
+	new (connection_string) mongo::ConnectionString(argument, mongo::ConnectionString::SET);
+	if (!connection_string->isValid())
+		return "invalid connection string";
+	config->connection_string = connection_string;
+	return 0;
+}
+
+//	Handles "GridFSDatabase <database name>" command
+static const char *gridfs_database_command(cmd_parms *const command, void *const module_config, const char *const argument)
+{
+	gridfs_config *const config = static_cast<gridfs_config *>(module_config);
+	std::string *const database = static_cast<std::string *>(apr_palloc(command->pool, sizeof(std::string)));
+	if (!database)
+		return "failed to allocate database string";
+	new (database) std::string(argument);
+	config->database = database;
+	return 0;
 }
 
 //	Handles "GridFSCacheMaxAge <cache max age>" command
-static const char* gridfs_cache_max_age_command(cmd_parms* command, void* module_config, const char* argument)
+static const char *gridfs_cache_max_age_command(cmd_parms *const command, void *const module_config, const char *const argument)
 {
-    gridfs_config* config = (gridfs_config*)module_config;
-    int cache_max_age = atoi(argument);
-    if (cache_max_age < 0 || cache_max_age > MAX_CACHE_MAX_AGE)
-    	return "max age out of range";
-    config->cache_max_age = cache_max_age;
-    config->cache_max_age_set = 1;
-    return 0;
+	gridfs_config *const config = static_cast<gridfs_config *>(module_config);
+	const int cache_max_age = std::atoi(argument);
+	if (cache_max_age < 0 || cache_max_age > MAX_CACHE_MAX_AGE)
+		return "max age out of range";
+	config->cache_max_age = cache_max_age;
+	config->cache_max_age_set = true;
+	return 0;
 }
 
 //	Handles "GridFSConnectTimeout <connect timeout>" command
-static const char* gridfs_connect_timeout_command(cmd_parms* command, void* module_config, const char* argument)
+static const char *gridfs_connect_timeout_command(cmd_parms *const command, void *const module_config, const char *const argument)
 {
-    gridfs_config* config = (gridfs_config*)module_config;
-    int connect_timeout = atoi(argument);
-    if (connect_timeout <= 0 || connect_timeout > 300)
-    	return "timeout out of range (1-300s)";
-    config->connect_timeout = connect_timeout;
-    config->connect_timeout_set = 1;
-    return 0;
+	gridfs_config *const config = static_cast<gridfs_config *>(module_config);
+	int connect_timeout = atoi(argument);
+	if (connect_timeout < 0 || connect_timeout > MAX_CONNECT_TIMEOUT)
+		return "timeout out of range";
+	config->connect_timeout = connect_timeout;
+	config->connect_timeout_set = true;
+	return 0;
 }
 
 //	Handles request
-static int gridfs_handler(request_rec* request)
+static int gridfs_handler(request_rec *const request)
 {
-    gridfs_config* config = (gridfs_config*)ap_get_module_config(request->per_dir_config, &gridfs_module);
-	if (!config->connection_string || !config->db_name)
+	const gridfs_config *const config = static_cast<gridfs_config *>(ap_get_module_config(request->per_dir_config, &gridfs_module));
+	if (!config->connection_string || !config->database)
 		return DECLINED;
-    if (request->method_number != M_GET)
+	if (request->method_number != M_GET)
 		return HTTP_NOT_IMPLEMENTED;
-	int length = strlen(request->uri);
-	if (length <= 1)
+	if (*request->uri != '/')
 		return HTTP_NOT_FOUND;
-	char* filename = apr_pstrdup(request->pool, request->uri + 1);
+	const char *const filename = apr_pstrdup(request->pool, request->uri + 1);
 	if (!filename)
 	{
 		ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, request, "mod_gridfs: Failed to allocate filename memory."); 
 		return HTTP_INTERNAL_SERVER_ERROR;
 	}
 	mongo::ScopedDbConnection connection(*config->connection_string, config->connect_timeout);
-	mongo::GridFS gridfs(connection.conn(), config->db_name);
-	mongo::GridFile gridfile = gridfs.findFile(filename);
-	if (!gridfile.exists())
+	try
+	{
+		const mongo::GridFS gridfs(connection.conn(), *config->database);
+		const mongo::GridFile& gridfile = gridfs.findFile(filename);
+		if (!gridfile.exists())
+		{
+			connection.done();
+			return HTTP_NOT_FOUND;
+		}
+		const mongo::gridfs_offset file_length = gridfile.getContentLength();
+		const mongo::Date_t upload_date = gridfile.getUploadDate();
+		const std::string& md5 = gridfile.getMD5();
+		const std::string& content_type = gridfile.getContentType();
+		request->mtime = apr_time_from_sec(upload_date.toTimeT());
+		ap_set_last_modified(request);
+		if (!md5.empty())
+			apr_table_set(request->headers_out, "Etag", md5.c_str());
+		if (ap_meets_conditions(request) == HTTP_NOT_MODIFIED)
+		{
+			if (!md5.empty())
+				apr_table_unset(request->headers_out, "Etag");
+			connection.done();
+			return HTTP_NOT_MODIFIED;
+		}
+		if (!request->header_only)
+		{
+			const int num_chunks = gridfile.getNumChunks();
+			for (int chunk_index = 0;chunk_index < num_chunks;chunk_index++) 
+			{
+				mongo::GridFSChunk chunk = gridfile.getChunk(chunk_index);
+				int chunk_length;
+				const char* chunk_data = chunk.data(chunk_length);
+				if (chunk_length != 0)
+					ap_rwrite(chunk_data, chunk_length, request);
+			}
+		}
+		else
+			ap_set_content_length(request, file_length);
+		if (content_type.empty())
+		{
+			request->finfo.filetype = APR_REG;
+			request->filename = const_cast<char *>(filename);
+			ap_run_type_checker(request);
+		}
+		else
+			ap_set_content_type(request, content_type.c_str());
+	}
+	catch (...)
 	{
 		connection.done();
-		return HTTP_NOT_FOUND;
+		throw;
 	}
-	mongo::gridfs_offset file_length = gridfile.getContentLength();
-	std::string md5 = gridfile.getMD5();
-	std::string content_type = gridfile.getContentType();
-    request->mtime = apr_time_from_sec(gridfile.getUploadDate().toTimeT());
-    ap_set_last_modified(request);
-	if (!md5.empty())
-		apr_table_set(request->headers_out, "Etag", md5.c_str());
-	if (ap_meets_conditions(request) == HTTP_NOT_MODIFIED)
-	{
-		if (!md5.empty())
-			apr_table_unset(request->headers_out, "Etag");
-		connection.done();
-		return HTTP_NOT_MODIFIED;
-	}
-	if (!request->header_only)
-	{
-		int num_chunks = gridfile.getNumChunks();
-        for (int chunk_index = 0;chunk_index < num_chunks;chunk_index++) 
-        {
-        	mongo::GridFSChunk chunk = gridfile.getChunk(chunk_index);
-        	int chunk_length;
-        	const char* chunk_data = chunk.data(chunk_length);
-        	if (chunk_length != 0)
-				ap_rwrite(chunk_data, chunk_length, request);
-        }
-	}
-	else
-		ap_set_content_length(request, file_length);
 	connection.done();
 	if (config->cache_max_age)
 	{
 		snprintf(cache_control, sizeof(cache_control) - 1, "public, max-age=%d", config->cache_max_age);
 		apr_table_set(request->headers_out, "Cache-Control", cache_control);
 		apr_time_t expires_time = request->request_time + apr_time_from_sec(config->cache_max_age);
-	    char datestr[APR_RFC822_DATE_LEN];
-	    apr_rfc822_date(datestr, expires_time);
+		char datestr[APR_RFC822_DATE_LEN];
+		apr_rfc822_date(datestr, expires_time);
 		apr_table_set(request->headers_out, "Expires", datestr);
 	}
-	if (content_type.empty())
-	{
-		request->finfo.filetype = APR_REG;
-		request->filename = filename;
-		ap_run_type_checker(request);
-	}
-	else
-		ap_set_content_type(request, content_type.c_str());
-    return OK;
+	return OK;
 }
 
-//	Registers httpd hooks
-static void gridfs_register_hooks(apr_pool_t *p)
+//	Registers hooks
+static void gridfs_register_hooks(apr_pool_t *const pool)
 {
-    ap_hook_handler(gridfs_handler, 0, 0, APR_HOOK_MIDDLE);
+	ap_hook_handler(gridfs_handler, 0, 0, APR_HOOK_MIDDLE);
 }
 
 //	Describes module configuration commands
 static const command_rec gridfs_commands[] =
 {
-    AP_INIT_TAKE1("GridFSConnection", (cmd_func)gridfs_connection_command, 0, OR_FILEINFO, "GridFS connection string."),
-    AP_INIT_TAKE1("GridFSDatabase", (cmd_func)ap_set_string_slot, (void *)APR_OFFSETOF(gridfs_config, db_name), OR_FILEINFO, "GridFS database name."),
-    AP_INIT_TAKE1("GridFSCacheMaxAge", (cmd_func)gridfs_cache_max_age_command, 0, OR_FILEINFO, "GridFS cache max age (seconds, 0 to disable expiration)."),
-    AP_INIT_TAKE1("GridFSConnectTimeout", (cmd_func)gridfs_connect_timeout_command, 0, OR_FILEINFO, "GridFS connection timeout (seconds)."),
-    {0}
+	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("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 connection timeout (seconds, 0 for infinite)."),
+	{0}
 };
 
 //	Defines module
 {
 	module AP_MODULE_DECLARE_DATA gridfs_module =
 	{
-	    STANDARD20_MODULE_STUFF,
-	    gridfs_create_config,
-	    gridfs_merge_config,
-	    0,
-	    0,
-	    gridfs_commands,
-	    gridfs_register_hooks
+		STANDARD20_MODULE_STUFF,
+		gridfs_create_config,
+		gridfs_merge_config,
+		0,
+		0,
+		gridfs_commands,
+		gridfs_register_hooks
 	};
-}
+}