Browse code

- added a new plugin type "logging facility" for plugins which want to receive all log messages - changed AmArg to own the objects put into it to avoid nasty problems with pointers to short-lived objects becoming invalid - implemented di_log plugin, a plugin able to output or dump to disk the last x lines of debug log messages

git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@319 8eb893ce-cfd4-0310-b710-fb5ebe64c474

Stefan Keller authored on 02/05/2007 16:10:10
Showing 7 changed files
... ...
@@ -76,3 +76,7 @@ AmSIPEventHandler::AmSIPEventHandler(const string& name)
76 76
 {
77 77
 }
78 78
 
79
+AmLoggingFacility::AmLoggingFacility(const string& name) 
80
+  : AmPluginFactory(name) 
81
+{
82
+}
... ...
@@ -34,6 +34,8 @@
34 34
 #include "AmConfig.h"
35 35
 #include "AmArg.h"
36 36
 
37
+#include <stdarg.h>
38
+
37 39
 #include <string>
38 40
 #include <map>
39 41
 using std::map;
... ...
@@ -44,7 +46,7 @@ using std::string;
44 46
  */
45 47
 class AmDynInvoke
46 48
 {
47
-public:
49
+ public:
48 50
   /** \brief NotImplemented result for DI API calls */
49 51
   struct NotImplemented {
50 52
     string what;
... ...
@@ -64,7 +66,7 @@ class AmPluginFactory
64 66
 {
65 67
   string plugin_name;
66 68
 
67
-public:
69
+ public:
68 70
   AmPluginFactory(const string& name)
69 71
     : plugin_name(name) {}
70 72
 
... ...
@@ -89,7 +91,7 @@ public:
89 91
  */
90 92
 class AmDynInvokeFactory: public AmPluginFactory
91 93
 {
92
-public:
94
+ public:
93 95
   AmDynInvokeFactory(const string& name);
94 96
   virtual AmDynInvoke* getInstance()=0;
95 97
 };
... ...
@@ -102,7 +104,7 @@ class AmSessionEventHandler;
102 104
  */
103 105
 class AmSessionEventHandlerFactory: public AmPluginFactory
104 106
 {
105
-public:
107
+ public:
106 108
   AmSessionEventHandlerFactory(const string& name);
107 109
 
108 110
   virtual AmSessionEventHandler* getHandler(AmSession*)=0;
... ...
@@ -119,14 +121,14 @@ class AmSessionFactory: public AmPluginFactory
119 121
 
120 122
   AmSessionTimerConfig mod_conf;
121 123
 
122
-protected:
124
+ protected:
123 125
   /**
124 126
    * This reads the module configuration from 
125 127
    * cfg into the modules mod_conf.
126 128
    */
127 129
   int configureModule(AmConfigReader& cfg);
128 130
 
129
-public:
131
+ public:
130 132
   /**
131 133
    * This function applys the module configuration 
132 134
    */
... ...
@@ -174,7 +176,7 @@ public:
174 176
 class AmSIPEventHandler : public AmPluginFactory 
175 177
 {
176 178
 
177
-public:
179
+ public:
178 180
   AmSIPEventHandler(const string& name);
179 181
   virtual ~AmSIPEventHandler() { }
180 182
 
... ...
@@ -188,6 +190,21 @@ public:
188 190
   virtual bool onSipReply(const AmSipReply& rep) = 0;
189 191
 };
190 192
 
193
+/** \brief Interface for plugins that implement a
194
+ *     logging facility
195
+ */
196
+class AmLoggingFacility : public AmPluginFactory
197
+{
198
+
199
+ public:
200
+  AmLoggingFacility(const string& name);
201
+  virtual ~AmLoggingFacility() { }
202
+
203
+  /** will be called on logging messages
204
+   */
205
+  virtual void log(int level, const char* fmt, va_list ap) = 0;
206
+};
207
+
191 208
 #if  __GNUC__ < 3
192 209
 #define EXPORT_FACTORY(fctname,class_name,args...) \
193 210
             extern "C" void* fctname()\
... ...
@@ -231,4 +248,9 @@ typedef void* (*FactoryCreate)();
231 248
 #define EXPORT_SIP_EVENT_HANDLER_FACTORY(class_name,app_name) \
232 249
             EXPORT_FACTORY(FACTORY_SIP_EVENT_HANDLER_EXPORT,class_name,app_name)
233 250
 
251
+#define FACTORY_LOG_FACILITY_EXPORT     log_facilty_factory_create
252
+#define FACTORY_LOG_FACILITY_EXPORT_STR XSTR(FACTORY_LOG_FACILITY_EXPORT)
253
+
254
+#define EXPORT_LOG_FACILITY_FACTORY(class_name,app_name) \
255
+            EXPORT_FACTORY(FACTORY_LOG_FACILITY_EXPORT,class_name,app_name)
234 256
 #endif
... ...
@@ -29,6 +29,7 @@
29 29
 #define _AmArg_h_
30 30
 
31 31
 #include <assert.h>
32
+#include <string.h>
32 33
 
33 34
 #include <vector>
34 35
 using std::vector;
... ...
@@ -37,6 +38,7 @@ using std::vector;
37 38
 class ArgObject {
38 39
  public:
39 40
   ArgObject() { }
41
+  virtual ArgObject* clone() { return new ArgObject(*this); }
40 42
   virtual ~ArgObject() { }
41 43
 };
42 44
 
... ...
@@ -51,7 +53,8 @@ class AmArg
51 53
     Int,
52 54
     Double,
53 55
     CStr,
54
-    AObject
56
+    AObject,
57
+    APointer		// for passing pointers that are not owned by AmArg
55 58
   };
56 59
 
57 60
  private:
... ...
@@ -65,6 +68,7 @@ class AmArg
65 68
     double      v_double;
66 69
     const char* v_cstr;
67 70
     ArgObject* v_obj;
71
+    void*		v_ptr;
68 72
   };
69 73
 
70 74
  public:
... ...
@@ -74,8 +78,9 @@ class AmArg
74 78
     switch(type){
75 79
     case Int: v_int = v.v_int; break;
76 80
     case Double: v_double = v.v_double; break;
77
-    case CStr: v_cstr = v.v_cstr; break;
78
-    case AObject: v_obj = v.v_obj; break;
81
+    case CStr: v_cstr = strdup(v.v_cstr); break;
82
+    case AObject: v_obj = v.v_obj->clone(); break;
83
+    case APointer: v_ptr = v.v_ptr; break;
79 84
     default: assert(0);
80 85
     }
81 86
   }
... ...
@@ -91,15 +96,26 @@ class AmArg
91 96
     {}
92 97
 
93 98
   AmArg(const char* v)
94
-    : type(CStr),
95
-    v_cstr(v)
96
-    {}
99
+    : type(CStr)
100
+    {
101
+      v_cstr = strdup(v);
102
+    }
97 103
 
98 104
   AmArg(ArgObject* v)
99
-    : type(AObject),
100
-    v_obj(v)
101
-    {}
105
+    : type(AObject)
106
+    {
107
+      v_obj = v->clone();
108
+    }
109
+
110
+  AmArg(void* v)
111
+    : type(APointer),
112
+    v_ptr(v)
113
+    { }
102 114
 
115
+  ~AmArg() {
116
+    if(type == CStr) free((void*)v_cstr);
117
+    else if(type == AObject) delete v_obj;
118
+  }
103 119
 
104 120
   short getType() const { return type; }
105 121
 
... ...
@@ -107,6 +123,7 @@ class AmArg
107 123
   double      asDouble() const { return v_double; }
108 124
   const char* asCStr()   const { return v_cstr; }
109 125
   ArgObject*  asObject() const { return v_obj; }
126
+  void*       asPointer() const { return v_ptr; }
110 127
 };
111 128
 
112 129
 /** \brief array of variable args for DI APIs*/
... ...
@@ -202,6 +202,16 @@ int AmPlugIn::load(const string& directory, const string& plugins)
202 202
     AmReplyHandler::get()->registerReplyHandler(it->second);
203 203
   }
204 204
 
205
+  // init logging facilities
206
+  for(map<string,AmLoggingFacility*>::iterator it = name2logfac.begin();
207
+      it != name2logfac.end(); it++){
208
+    err = it->second->onLoad();
209
+    if(err)
210
+      break;
211
+    // register for receiving logging messages
212
+    register_logging_fac(it->second);
213
+  }
214
+
205 215
     
206 216
   map<string,AmSessionFactory*> apps(name2app);
207 217
   for(map<string,AmSessionFactory*>::iterator it = apps.begin();
... ...
@@ -260,6 +270,12 @@ int AmPlugIn::loadPlugIn(const string& file)
260 270
     has_sym=true;
261 271
   }
262 272
 
273
+  if((fc = (FactoryCreate)dlsym(h_dl,FACTORY_LOG_FACILITY_EXPORT_STR)) != NULL){
274
+    if(loadLogFacPlugIn((AmPluginFactory*)fc()))
275
+      goto error;
276
+    has_sym=true;
277
+  }
278
+
263 279
   if(!has_sym){
264 280
     ERROR("Plugin type could not be detected (%s)(%s)\n",file.c_str(),dlerror());
265 281
     goto error;
... ...
@@ -364,6 +380,14 @@ AmSIPEventHandler* AmPlugIn::getFactory4SIPeh(const string& name)
364 380
   return 0;
365 381
 }
366 382
 
383
+AmLoggingFacility* AmPlugIn::getFactory4LogFaclty(const string& name)
384
+{
385
+  map<string,AmLoggingFacility*>::iterator it = name2logfac.find(name);
386
+  if(it != name2logfac.end())
387
+    return it->second;
388
+  return 0;
389
+}
390
+
367 391
 int AmPlugIn::loadAudioPlugIn(amci_exports_t* exports)
368 392
 {
369 393
   if(!exports){
... ...
@@ -488,6 +512,29 @@ int AmPlugIn::loadSIPehPlugIn(AmPluginFactory* f)
488 512
   return -1;
489 513
 }
490 514
 
515
+int AmPlugIn::loadLogFacPlugIn(AmPluginFactory* f)
516
+{
517
+  AmLoggingFacility* sf = dynamic_cast<AmLoggingFacility*>(f);
518
+  if(!sf){
519
+    ERROR("invalid logging facility plug-in!\n");
520
+    goto error;
521
+  }
522
+
523
+  if(name2logfac.find(sf->getName()) != name2logfac.end()){
524
+    ERROR("logging facility '%s' already loaded !\n",
525
+	  sf->getName().c_str());
526
+    goto error;
527
+  }
528
+      
529
+  name2logfac.insert(std::make_pair(sf->getName(),sf));
530
+  DBG("logging facility component '%s' loaded.\n",sf->getName().c_str());
531
+
532
+  return 0;
533
+
534
+ error:
535
+  return -1;
536
+}
537
+
491 538
 int AmPlugIn::addCodec(amci_codec_t* c)
492 539
 {
493 540
   if(codecs.find(c->id) != codecs.end()){
... ...
@@ -41,6 +41,7 @@ class AmSessionFactory;
41 41
 class AmSessionEventHandlerFactory;
42 42
 class AmDynInvokeFactory;
43 43
 class AmSIPEventHandler;
44
+class AmLoggingFacility;
44 45
 
45 46
 struct amci_exports_t;
46 47
 struct amci_codec_t;
... ...
@@ -73,6 +74,7 @@ class AmPlugIn
73 74
   map<string,AmSessionEventHandlerFactory*> name2seh;
74 75
   map<string,AmDynInvokeFactory*> name2di;
75 76
   map<string,AmSIPEventHandler*> name2sipeh;
77
+  map<string,AmLoggingFacility*> name2logfac;
76 78
 
77 79
   int dynamic_pl; // range: 96->127, see RFC 1890
78 80
     
... ...
@@ -86,6 +88,7 @@ class AmPlugIn
86 88
   int loadSehPlugIn(AmPluginFactory* cb);
87 89
   int loadDiPlugIn(AmPluginFactory* cb);
88 90
   int loadSIPehPlugIn(AmPluginFactory* f);
91
+  int loadLogFacPlugIn(AmPluginFactory* f);
89 92
 
90 93
   int addCodec(amci_codec_t* c);
91 94
   int addPayload(amci_payload_t* p);
... ...
@@ -158,6 +161,13 @@ class AmPlugIn
158 161
    */
159 162
   AmSIPEventHandler* getFactory4SIPeh(const string& name);
160 163
 
164
+  /**
165
+   * logging facility lookup function
166
+   * @param name application name
167
+   * @return NULL if failed (-> handler not found).
168
+   */
169
+  AmLoggingFacility* getFactory4LogFaclty(const string& name);
170
+
161 171
   /** @return true if this record has been inserted. */
162 172
   bool registerFactory4App(const string& app_name, AmSessionFactory* f);
163 173
 };
... ...
@@ -30,9 +30,15 @@
30 30
 #include <unistd.h>
31 31
 #include <stdarg.h>
32 32
 #include <stdio.h>
33
+#include <assert.h>
34
+
35
+#include <vector>
36
+#include "AmApi.h"
33 37
 
34 38
 int log_level=L_INFO;
35 39
 int log_stderr=0;
40
+vector<AmLoggingFacility*> log_hooks;
41
+
36 42
 
37 43
 inline const char* level2txt(int level)
38 44
 {
... ...
@@ -65,7 +71,7 @@ void dprint(int level, const char* fct, char* file, int line, char* fmt, ...)
65 71
 void log_print (int level, char* fmt, ...)
66 72
 {
67 73
   va_list ap;
68
-    
74
+
69 75
   fprintf(stderr, "(%i) %s: ",(int)getpid(),level2txt(level));
70 76
   va_start(ap, fmt);
71 77
   vfprintf(stderr,fmt,ap);
... ...
@@ -73,3 +79,26 @@ void log_print (int level, char* fmt, ...)
73 79
   va_end(ap);
74 80
 }
75 81
 
82
+void log_fac_print(int level, const char* fct, char* file, int line, char* fmt, ...)
83
+{
84
+  va_list ap;
85
+  char logline[512];
86
+
87
+  if(log_hooks.empty()) return;
88
+
89
+  snprintf(logline, sizeof(logline), "(%i) %s: %s (%s:%i): ",(int)getpid(), level2txt(level), fct, file, line);
90
+  strncat(logline, fmt, sizeof(logline));
91
+
92
+  va_start(ap, fmt);
93
+  for(unsigned i=0; i<log_hooks.size(); i++) log_hooks[i]->log(logline, ap);
94
+  va_end(ap);
95
+}
96
+
97
+void register_logging_fac(void* vp)
98
+{
99
+  AmLoggingFacility* lf = static_cast<AmLoggingFacility*>(vp);
100
+#ifdef _DEBUG
101
+  assert(lf != NULL);
102
+#endif
103
+  log_hooks.push_back(lf);
104
+}
... ...
@@ -53,12 +53,15 @@ extern "C" {
53 53
 
54 54
   void dprint (int level, const char* fct, char* file, int line, char* fmt, ...);
55 55
   void log_print (int level, char* fmt, ...);
56
+  void register_logging_fac(void*);
57
+  void log_fac_print(int level, const char* fct, char* file, int line, char* fmt, ...);
56 58
 
57 59
 #ifdef _DEBUG
58 60
 #define LOG_PRINT(level, args... ) dprint( level, __FUNCTION__, __FILE__, __LINE__, ##args )
59 61
 #else
60 62
 #define LOG_PRINT(level, args... ) log_print( level , ##args )
61 63
 #endif
64
+#define LOG_FAC_PRINT(level, args... ) log_fac_print( level, __FUNCTION__, __FILE__, __LINE__, ##args )
62 65
 
63 66
 #if  __GNUC__ < 3
64 67
 #define _LOG(level,fmt...) LOG_PRINT(level,##fmt)
... ...
@@ -85,6 +88,7 @@ extern "C" {
85 88
 		      }\
86 89
 		  }\
87 90
               }\
91
+              LOG_FAC_PRINT( level, fmt, ##args );\
88 92
 	  }while(0)
89 93
 #endif
90 94