The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
discovery.c
Go to the documentation of this file.
1 
24 #include <projectcommon.h>
25 #define DISCOVERY_SUBCLASS
26 #include <discovery.h>
27 #include <intframe.h>
28 #include <cstringframe.h>
29 #include <frametypes.h>
30 #include <fsprotocol.h>
31 #include <string.h>
32 #include <assert.h>
37 
38 FSTATIC char * _discovery_instancename(const Discovery* self);
41 FSTATIC gboolean _discovery_rediscover(gpointer vself);
42 FSTATIC void _discovery_ghash_destructor(gpointer gdiscovery);
43 FSTATIC void _discovery_sendjson(Discovery* self, char * jsonout, gsize jsonlen);
44 
46 
48 FSTATIC char *
50 {
51  return self->_instancename;
52 }
53 
55 FSTATIC void
57 {
58  (void)self;
59 }
60 
62 FSTATIC guint
64 {
65  (void)self;
66  return 0;
67 }
68 static GHashTable * _discovery_timers = NULL;
69 
71 FSTATIC void
73 {
74  Discovery* self = CASTTOCLASS(Discovery, gself);
75  char * instancename = self->_instancename;
76 
77  if (self->_timerid > 0) {
78  g_source_remove(self->_timerid);
79  self->_timerid = 0;
80  }
81  if (self->_config) {
82  UNREF(self->_config);
83  }
84  if (_discovery_timers && instancename) {
85  self->_instancename = NULL; // Avoid infinite recursion...
86  g_hash_table_remove(_discovery_timers, instancename);
87  }
88  if (instancename) {
89  g_free(instancename);
90  self->_instancename = instancename = NULL;
91  }
92 
93  FREECLASSOBJ(self); self=NULL;
94 }
95 
100 FSTATIC void
101 _discovery_ghash_destructor(gpointer gdiscovery)
102 {
103  Discovery* self = CASTTOCLASS(Discovery, gdiscovery);
104  // We take steps in discovery_finalize() to avoid infinite recursion...
105  if (self->_instancename) {
106  // In particular it sets instancename to NULL before removing
107  // it from the table.
108  // Only during destruction is it legal for self->instancename to be NULL
109  // So, if it's NULL, we're in the process of destroying it...
110 
111  // Not completely certain what we're doing is sufficient...
112  // In particular, what happens if we try and remove an element which
113  // is trying to be removed? Does the glib code tolerate that?
114  // My strong suspicion is that it does tolerate this because we
115  // free the instancename (key) last.
116  // Either glib removed the item before freeing the object, or vice versa
117  // If the first case, then the second pass through it simply won't be
118  // in the table the second time around.
119  //
120  // The same condition holds if they do them in the opposite order.
121  // But if they tried to free the key before removing it that would
122  // not likely work for many cases, so it's unlikely that they do it
123  // in that order.
124  UNREF(self);
125  }
126 }
127 
130 FSTATIC gboolean
131 _discovery_rediscover(gpointer vself)
132 {
133  Discovery* self = CASTTOCLASS(Discovery, vself);
134 
135  return self->discover(self);
136 }
137 
142 Discovery*
143 discovery_new(const char * instname,
144  NetGSource* iosource,
145  ConfigContext* context,
146  gsize objsize)
147 {
148  gsize size = objsize < sizeof(Discovery) ? sizeof(Discovery) : objsize;
150  g_return_val_if_fail(ret != NULL, NULL);
152  ret->_instancename = g_strdup(instname);
157  ret->discover = NULL;
158  ret->_timerid = 0;
159  ret->_iosource = iosource;
160  ret->_config = context;
161  ret->starttime = g_get_real_time();
162  REF(ret->_config);
163  return ret;
164 }
165 
166 
173 void
175 {
176  gint timeout;
177  if (NULL == _discovery_timers) {
178  _discovery_timers = g_hash_table_new_full(g_str_hash, g_str_equal
180  assert(_discovery_timers != NULL);
181  }
182  self->discover(self);
183  timeout = self->discoverintervalsecs(self);
184  if (timeout > 0) {
185  self->_timerid = g_timeout_add_seconds(timeout, _discovery_rediscover, self);
186  }
187  REF(self);
188  // _discovery_ghash_destructor will unref it if there's one already there...
189  g_hash_table_replace(_discovery_timers, self->instancename(self), self);
190 }
191 FSTATIC void
192 discovery_unregister(const char* instance)
193 {
194  if (_discovery_timers) {
195  // _discovery_ghash_destructor will unref it if there's one already there...
196  g_hash_table_remove(_discovery_timers, instance);
197  }
198 }
199 
201 void
203 {
204  if (_discovery_timers != NULL) {
205  GHashTable* timers = _discovery_timers;
206  _discovery_timers = NULL;
207  g_hash_table_remove_all(timers);
208  g_hash_table_destroy(timers); timers = NULL;
209  }else{
210  DEBUGMSG1("Discovery timers were NULL");
211  }
212 }
214 FSTATIC void
216  char * jsonout,
217  gsize jsonlen)
218 {
219  FrameSet* fs;
220  CstringFrame* jsf;
221  IntFrame* intf;
222  Frame* fsf;
223  ConfigContext* cfg = self->_config;
224  NetGSource* io = self->_iosource;
225  NetAddr* cma;
226  const char * basename = self->instancename(self);
227 
228  g_return_if_fail(cfg != NULL && io != NULL);
229 
230  DEBUGMSG2("%s.%d: discovering %s: _sentyet == %d"
231  , __FUNCTION__, __LINE__, basename, self->_sentyet);
232  // Primitive caching - don't send what we've already sent.
233  if (self->_sentyet) {
234  const char * oldvalue = cfg->getstring(cfg, basename);
235  if (oldvalue != NULL && strcmp(jsonout, oldvalue) == 0) {
236  DEBUGMSG2("%s.%d: %s sent this value - don't send again."
237  , __FUNCTION__, __LINE__, basename);
238  g_free(jsonout);
239  return;
240  }
241  DEBUGMSG2("%s.%d: %s this value is different from previous value"
242  , __FUNCTION__, __LINE__, basename);
243  }
244  DEBUGMSG2("%s.%d: Sending %"G_GSIZE_FORMAT" bytes of JSON text"
245  , __FUNCTION__, __LINE__, jsonlen);
246  cfg->setstring(cfg, basename, jsonout);
247  cma = cfg->getaddr(cfg, CONFIGNAME_CMADISCOVER);
248  if (cma == NULL) {
249  DEBUGMSG2("%s.%d: %s address is unknown - skipping send"
250  , __FUNCTION__, __LINE__, CONFIGNAME_CMADISCOVER);
251  g_free(jsonout);
252  return;
253  }
254  self->_sentyet = TRUE;
255 
258  intf->setint(intf, self->starttime);
259  frameset_append_frame(fs, &intf->baseclass);
260  UNREF2(intf);
262  fsf = &jsf->baseclass; // base class object of jsf
263  fsf->setvalue(fsf, jsonout, jsonlen+1, frame_default_valuefinalize); // jsonlen is strlen(jsonout)
264  frameset_append_frame(fs, fsf);
265  DEBUGMSG2("%s.%d: Sending a %"G_GSIZE_FORMAT" bytes JSON frameset"
266  , __FUNCTION__, __LINE__, jsonlen);
267  io->_netio->sendareliablefs(io->_netio, cma, DEFAULT_FSP_QID, fs);
268  ++ self->reportcount;
269  UNREF(fsf);
270  UNREF(fs);
271 }
272 
#define CONFIGNAME_CMADISCOVER
Address of where to send discovery reports.
#define FRAMESETTYPE_JSDISCOVERY
Packet contains JSON-formatted discovery data.
Definition: framesettypes.h:45
const char *(* getstring)(const ConfigContext *, const char *name)
Get String value.
Definition: configcontext.h:86
FSTATIC void _discovery_flushcache(Discovery *self)
default (do-nothing) 'flush cache' function
Definition: discovery.c:56
#define DEBUGMSG1(...)
Definition: proj_classes.h:89
void discovery_register(Discovery *self)
Function for registering a discovery object with the discovery infrastructure.
Definition: discovery.c:174
void discovery_unregister_all(void)
Unregister all discovery methods in preparation for shutting down - to make valgrind happy :-D...
Definition: discovery.c:202
This is an IntFrame class TLV (type, length, value) frame - representing an integer of some specified...
Definition: intframe.h:39
NetIO * _netio
netio this object is based on
Definition: netgsource.h:50
#define FRAMETYPE_JSDISCOVER
FRAMETYPE_JSDISCOVER Frame (frametype 19) Frame subclass - CstringFrame class.
Definition: frametypes.h:308
This is the base Frame class object (in-memory TLV (type, length, value)) for every general component...
Definition: frame.h:43
IntFrame * intframe_new(guint16 frametype, int intbytes)
Construct new IntFrame object.
Definition: intframe.c:181
FSTATIC char * _discovery_instancename(const Discovery *self)
internal function return the type of Discovery object
Definition: discovery.c:49
Describes interfaces to C-String Frame (Cstringframe) C-Class It holds conventional zero-terminated b...
FrameSet * frameset_new(guint16 frameset_type)
Construct a new frameset of the given type.
Definition: frameset.c:110
WINEXPORT gint64 g_get_real_time(void)
HAVE_G_GET_MONOTONIC_TIME.
char * _instancename
Timer id for repeating discovery.
Definition: discovery.h:59
#define FSTATIC
Definition: projectcommon.h:31
Discovery * discovery_new(const char *instname, NetGSource *iosource, ConfigContext *context, gsize objsize)
Discovery constructor.
Definition: discovery.c:143
#define FREECLASSOBJ(obj)
Free a C-class object.
Definition: proj_classes.h:76
Semi-Abstract class (yes, really) defining discovery objects.
#define BINDDEBUG(Cclass)
BINDDEBUG is for telling the class system where the debug variable for this class is - put it in the ...
Definition: proj_classes.h:82
NetAddr *(* getaddr)(const ConfigContext *, const char *name)
Get NetAddr value.
Definition: configcontext.h:92
guint _timerid
Timer id for repeating discovery.
Definition: discovery.h:60
Implements the IntFrame class - integers in a frame.
void frameset_append_frame(FrameSet *fs, Frame *f)
Append frame to the front of the end of the frame list.
Definition: frameset.c:143
#define __FUNCTION__
FSTATIC guint _discovery_discoverintervalsecs(const Discovery *self)
default function - return zero for discovery interval
Definition: discovery.c:63
NetGSource * _iosource
How to send packets.
Definition: discovery.h:61
void(* sendjson)(Discovery *, char *, gsize)
Send JSON string.
Definition: discovery.h:54
#define REF(obj)
Definition: assimobj.h:39
#define FRAMETYPE_WALLCLOCK
FRAMETYPE_WALLCLOCK Frame (frametype 7) Frame subclass - IntFrame class.
Definition: frametypes.h:167
This is our CstringFrame class object - used for holding C-style NULL terminated strings.
Definition: cstringframe.h:36
Project common header file.
Header file defining the data layouts for our Frames.
struct _Discovery Discovery
Definition: discovery.h:45
void(* setstring)(ConfigContext *, const char *name, const char *value)
Definition: configcontext.h:87
FSTATIC void discovery_unregister(const char *instance)
Definition: discovery.c:192
Discovery class abstract C-class - it supports discovering "things" through subclasses for different ...
Definition: discovery.h:47
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
guint64 starttime
When this operation was started.
Definition: discovery.h:65
gboolean sendareliablefs(NetIO *self, NetAddr *dest, guint16 queueid, FrameSet *frameset)
[out] source address of return result
FSTATIC void _discovery_ghash_destructor(gpointer gdiscovery)
Discovery Destructor function for the GHashTable.
Definition: discovery.c:101
FSTATIC void frame_default_valuefinalize(gpointer value)
Finalize a Frame.
Definition: frame.c:56
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
FSTATIC void _discovery_sendjson(Discovery *self, char *jsonout, gsize jsonlen)
Send JSON that we discovered to the CMA - with some caching going on.
Definition: discovery.c:215
The NetAddr class class represents a general network address - whether IP, MAC, or any other type of ...
Definition: netaddr.h:43
char *(* instancename)(const Discovery *self)
Which object is this?
Definition: discovery.h:49
Frame baseclass
base Frame class object
Definition: intframe.h:40
void(* setint)(IntFrame *self, guint64 value)
set the integer to the given value
Definition: intframe.h:43
#define DEFAULT_FSP_QID
Default Queue ID.
Definition: fsprotocol.h:127
gboolean(* discover)(Discovery *self)
Perform the discovery.
Definition: discovery.h:51
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:46
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
FSTATIC gboolean _discovery_rediscover(gpointer vself)
GSourceFunc function to invoke discover member function at the timed interval.
Definition: discovery.c:131
#define DEBUGMSG2(...)
Definition: proj_classes.h:90
guint(* discoverintervalsecs)(const Discovery *self)
How often to re-discover? (in seconds)
Definition: discovery.h:52
void(* setvalue)(Frame *self, gpointer value, guint32 length, GDestroyNotify valfinal)
member function for setting value
Definition: frame.h:52
ConfigContext * _config
Configuration Parameters - has address of CMA.
Definition: discovery.h:62
#define UNREF2(obj)
Definition: assimobj.h:36
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
Implements the FsProtocol object.
AssimObj baseclass
Base object class.
Definition: discovery.h:48
The NetGSource class objects integrate NetIO class objects into the g_main_loop paradigm.
Definition: netgsource.h:43
#define NEWSUBCLASS(Cclass, obj)
Definition: proj_classes.h:67
WINEXPORT CstringFrame * cstringframe_new(guint16 frame_type, gsize framesize)
Construct a new CstringFrame - allowing for "derived" frame types...
Definition: cstringframe.c:101
FSTATIC void _discovery_finalize(AssimObj *gself)
Finalizing function for Discovery objects.
Definition: discovery.c:72