aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Kropf <josh@slashdev.ca>2007-07-30 21:17:52 (GMT)
committerJosh Kropf <josh@slashdev.ca>2007-07-30 21:17:52 (GMT)
commita4393dc3e62856eb4feb5cfe040a7b0f4dd212f8 (patch)
tree7468ebb58912b30513d593a725e91e4c8cd63cfc
parent805292d633f3a035fb3a7701a65d52109cc9696a (diff)
downloadecho-server-a4393dc3e62856eb4feb5cfe040a7b0f4dd212f8.zip
echo-server-a4393dc3e62856eb4feb5cfe040a7b0f4dd212f8.tar.gz
echo-server-a4393dc3e62856eb4feb5cfe040a7b0f4dd212f8.tar.bz2
Completely refactored the action mapping logic
- removed singleton pattern - action library auto-mapping macros Fixed some make file errors
-rw-r--r--Makefile4
-rw-r--r--action/action.cpp58
-rw-r--r--action/action.h71
-rw-r--r--fcgi/dispatcher.cpp12
-rw-r--r--modules/Makefile2
5 files changed, 88 insertions, 59 deletions
diff --git a/Makefile b/Makefile
index 7420683..a82e8ab 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
CXXFLAGS=-Wall -g -I./common -I./action
-LDFLAGS=-lstdc++ -lfcgi++ -lcgicc -lconfuse
+LDFLAGS=-lstdc++ -lfcgi -lfcgi++ -lcgicc -lconfuse -ldl
OBJS=common/config.o action/action.o fcgi/fcgi_io.o fcgi/dispatcher.o
all: dispatcher.fcgi
dispatcher.fcgi: $(OBJS)
- $(CXX) $(LDFLAGS) -o $@ $^
+ $(CXX) $^ $(LDFLAGS) -o $@
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
diff --git a/action/action.cpp b/action/action.cpp
index adf0e7c..3f837a5 100644
--- a/action/action.cpp
+++ b/action/action.cpp
@@ -5,16 +5,11 @@
using namespace std;
using namespace action;
-ActionMapping* ActionMapping::instance()
-{
- static ActionMapping instance;
- return &instance;
-}
-
-ActionMapping::ActionMapping()
+ActionFactory::ActionFactory()
{
void* handle;
- void* func;
+ typedef int (*count_func_t)();
+ typedef void (*mapping_func_t)(int, char*, create_t, destroy_t);
Config config;
vector<string> v = config.modules();
@@ -24,25 +19,44 @@ ActionMapping::ActionMapping()
if (!handle) throw action_error(dlerror());
- // run the auto mapping function
- void* func = dlsym(handle, "DL_MAPPING_SYMBOL");
- if (!func) throw action_error(dlerror());
+ // function that returns action count
+ count_func_t count_f = (count_func_t)dlsym(handle, "COUNT_FUNC");
+ if (!count_f) throw action_error(dlerror());
- ((void (*)())func)();
+ // function for getting action mapping
+ mapping_func_t mapping_f = (mapping_func_t)dlsym(handle, "MAPPING_FUNC");
+ if (!mapping_f) throw action_error(dlerror());
+
+ int count = count_f();
+
+ // for each action, call the mapping function
+ for (int i=0; i<count; i++) {
+ char* key; // action key string
+ factory f; // create/destroy function pointers
+
+ mapping_f(i, key, f.create, f.destroy);
+
+ _factory_map[key] = f;
+ }
+
+ // save the handle for use in the destructor
+ _handles.push_back(handle);
}
}
-void ActionMapping::reg(string key, create_ptr ptr)
+ActionFactory::~ActionFactory()
{
- _mapping[key] = ptr;
+ // close all action module libraries
+ for (vector<void*>::iterator i = _handles.begin(); i != _handles.end(); i++) {
+ dlclose(*i);
+ }
}
-bool ActionMapping::contains(string key) const
-{
- return _mapping.count(key) != 0;
-}
+bool ActionFactory::contains(const char* key) const
+{ return _factory_map.count(key) != 0; }
-Action* ActionMapping::get(string key)
-{
- return (*_mapping[key])();
-}
+Action* ActionFactory::create(const char* key)
+{ return (*_factory_map[key].create)(); }
+
+void ActionFactory::destroy(const char* key, Action* action)
+{ (*_factory_map[key].destroy)(action); }
diff --git a/action/action.h b/action/action.h
index ee6e5ea..262b3aa 100644
--- a/action/action.h
+++ b/action/action.h
@@ -2,20 +2,27 @@
#include <iostream>
#include <exception>
#include <string>
+#include <vector>
#include <map>
#ifndef _ACTION_H_
#define _ACTION_H_
/**
- * These macros must be used by action modules to define the
- * auto-mapping function. This function is called by the
- * action mapping class for each dynamic library listed
- * in the configuration file.
+ * These macros must be used by action modules to define the auto-mapping
+ * functions. These functions are called by the action factory class to
+ * discover the
*/
-#define DL_MAPPING_SYMBOL __action_mapping
-#define BEGIN_DL_MAPPING extern "C" void DL_MAPPING_SYMBOL() {
-#define END_DL_MAPPING }
+
+// function symbol that returns number of actions in the module
+#define COUNT_FUNC __action_count
+
+// function symbol that return action key and create/destroy functions
+#define MAPPING_FUNC __action_mapping
+
+#define BEGIN_MAPPING_FUNC extern "C" void MAPPING_FUNC(int i, char* key, create_t create, destroy_t destroy) {
+#define BEGIN_COUNT_FUNC extern "C" int COUNT_FUNC() {
+#define END_FUNC }
namespace action {
@@ -29,7 +36,6 @@ private:
public:
action_error(const char* msg) { _msg = msg; }
-
virtual const char* what() { return _msg; }
};
@@ -39,7 +45,7 @@ public:
*/
class Action {
public:
- virtual ~Action();
+ virtual ~Action() { }
/**
* Executes the action. Actions are passed the cgicc object containing request
@@ -52,50 +58,57 @@ public:
};
/**
- * Typedef for a pointer to the create method in action
+ * Function pointer types for action factory functions (create/destroy
*/
-typedef Action* (*create_ptr)();
+typedef Action* (*create_t)();
+typedef void (*destroy_t)(Action*);
/**
* Registry of action mapping.
*/
-class ActionMapping {
+class ActionFactory {
private:
- std::map<std::string, create_ptr> _mapping;
-
-protected:
- /**
- * Reads a list of modules from the config file and loads the dynamic library.
- * Each library has a callback function to register is action handlers.
- */
- ActionMapping();
+ typedef struct factory {
+ create_t create;
+ destroy_t destroy;
+ };
+
+ std::map<const char*, factory> _factory_map;
+
+ std::vector<void*> _handles;
public:
/**
- * Returns singleton instance of action mapping class
+ * Reads a list of modules from the config file and loads the dynamic library.
+ * Each library must define the required auto-mapping functions.
*/
- static ActionMapping* instance();
+ ActionFactory();
/**
- * Registers mapping between action create method pointer and string identifier.
- * @param key string identifier
- * @param ptr action create method pointer
+ * Closes all of the option action module libraries
*/
- void reg(std::string key, create_ptr ptr);
+ ~ActionFactory();
/**
* Returns true if the registry contains an action for the given key
* @param key string identifier
* @return true if registry contains an action for the key, false otherwise
*/
- bool contains(std::string key) const;
+ bool contains(const char* key) const;
/**
* Instantiates the action for the given key and returns it
* @param key string identifier
- * @return instance of action class
+ * @return pointer to instance of action class
+ */
+ Action* create(const char* key);
+
+ /**
+ * Deletes the action instance
+ * @param key string identifier
+ * @param action pointer to action
*/
- Action* get(std::string key);
+ void destroy(const char* key, Action* action);
};
} /* end namespace */
diff --git a/fcgi/dispatcher.cpp b/fcgi/dispatcher.cpp
index a2c1009..e615eb7 100644
--- a/fcgi/dispatcher.cpp
+++ b/fcgi/dispatcher.cpp
@@ -11,7 +11,7 @@ using namespace action;
int main (void)
{
- ActionMapping* mapping = ActionMapping::instance();
+ ActionFactory factory;
FCGX_Request request;
@@ -23,6 +23,7 @@ int main (void)
Cgicc cgi(&io);
Action* action = NULL;
+ const char* key = NULL;
// script name is the full path of the request
string script = cgi.getEnvironment().getScriptName();
@@ -37,16 +38,17 @@ int main (void)
// if another / wasn't found, use size as end index
if (end == string::npos) end = script.size();
- string key = script.substr(begin, end-begin);
+ key = script.substr(begin, end-begin).c_str();
- if (mapping->contains(key)) {
- action = mapping->get(key);
+ if (factory.contains(key)) {
+ action = factory.create(key);
}
}
if (action != NULL) {
action->execute(cgi, io);
- delete action;
+
+ factory.destroy(key, action);
} else {
io << HTTPStatusHeader(404, "action not found");
}
diff --git a/modules/Makefile b/modules/Makefile
index 0838804..e84a051 100644
--- a/modules/Makefile
+++ b/modules/Makefile
@@ -2,7 +2,7 @@ CXXFLAGS=-Wall -fpic -g -I../../action
LDFLAGS=-shared
$(TARGET): $(OBJS)
- $(CXX) $(LDFLAGS) -o $@ $?
+ $(CXX) $(LDFLAGS) $^ -o $@
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@