The Assimilation Monitoring Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
jsondiscovery.c
Go to the documentation of this file.
1 
24 #include <projectcommon.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28 #include <memory.h>
29 #define DISCOVERY_SUBCLASS
30 #include <frameset.h>
31 #include <configcontext.h>
32 #include <cstringframe.h>
33 #include <frametypes.h>
34 #include <framesettypes.h>
35 #include <jsondiscovery.h>
36 #include <assert.h>
37 #include <fsprotocol.h>
43 
47 FSTATIC void _jsondiscovery_childwatch(ChildProcess*, enum HowDied, int rc, int signal, gboolean core_dumped);
48 FSTATIC void _jsondiscovery_send(JsonDiscovery* self, char * jsonout, gsize jsonlen);
51 
53 FSTATIC guint
55 {
56  const JsonDiscovery* self = CASTTOCONSTCLASS(JsonDiscovery, dself);
57  return self->_intervalsecs;
58 }
59 
61 FSTATIC void
63 {
64  JsonDiscovery* self = CASTTOCLASS(JsonDiscovery, dself);
65  if (self->jsonparams) {
66  UNREF(self->jsonparams);
67  }
68  if (self->logprefix) {
69  g_free(self->logprefix);
70  self->logprefix = NULL;
71  }
72  if (self->_fullpath) {
73  g_free(self->_fullpath);
74  self->_fullpath = NULL;
75  }
76  _discovery_finalize(dself);
77 }
78 
80 FSTATIC gboolean
82 {
83  JsonDiscovery* self = CASTTOCLASS(JsonDiscovery, dself);
84  gchar* argv[2];
85  ConfigContext* cfg = self->baseclass._config;
86  if (NULL != self->child) {
87  g_warning("%s.%d: JSON discovery process still running - skipping this iteration."
88  , __FUNCTION__, __LINE__);
89  return TRUE;
90  }
91  ++ self->baseclass.discovercount;
92  if (cfg->getaddr(cfg, CONFIGNAME_CMADISCOVER) == NULL) {
93  DEBUGMSG2("%s.%d: don't have [%s] address yet - continuing."
95  }
96  argv[0] = self->_fullpath;
97  argv[1] = NULL;
98 
99  DEBUGMSG1("Running Discovery [%s]", argv[0]);
100 
101  self->child = childprocess_new(0 // object size (0 == default size)
102 , argv // char** argv
103 , NULL // char** envp
104 , self->jsonparams // ConfigContext*envmod
105 , NULL // const char* curdir
107  //gboolean (*notify)(ChildProcess*, enum HowDied, int rc, int signal, gboolean core_dumped)
108 , TRUE // gboolean save_stdout
109 , G_LOG_DOMAIN // const char * logdomain
110 , self->logprefix // const char * logprefix
111 , G_LOG_LEVEL_MESSAGE // GLogLevelFlags loglevel
112 , 0 //guint32 timeout_seconds;
113 , self // gpointer user_data
115 , NULL
116  );
117 
118  // Don't want us going away while we have a child out there...
119  REF2(self);
120  return TRUE;
121 }
123 FSTATIC void
125 , enum HowDied status
126 , int rc
127 , int signal
128 , gboolean core_dumped)
129 {
131  gchar* jsonout = NULL;
132  gsize jsonlen = 0;
133 
134  (void)core_dumped;
135  (void)rc;
136  (void)signal;
137  if (status != EXITED_ZERO) {
138  // We don't need to log anything... It's being done for us...
139  goto quitchild;
140  }
141  jsonout = g_strdup(child->stdout_src->textread->str);
142  jsonlen = strlen(jsonout);
143  if (jsonlen == 0) {
144  g_warning("JSON discovery [%s] produced no output.", self->_fullpath);
145  goto quitchild;
146  }
147  //g_debug("Got %d bytes of JSON TEXT: [%s]", jsonlen, jsonout);
148  _jsondiscovery_send(self, jsonout, jsonlen);
149 
150 quitchild:
151  UNREF(self->child);
152  child = NULL;
153  // We did a 'ref' in _jsondiscovery_discover above to keep us from disappearing while child was running.
154  UNREF2(self);
155 }
156 
158 FSTATIC void
159 _jsondiscovery_send(JsonDiscovery* self, char * jsonout, gsize jsonlen)
160 {
161  FrameSet* fs;
162  CstringFrame* jsf;
163  Frame* fsf;
164  ConfigContext* cfg = self->baseclass._config;
165  NetGSource* io = self->baseclass._iosource;
166  NetAddr* cma;
167  const char * basename = self->baseclass.instancename(&self->baseclass);
168 
169  g_return_if_fail(cfg != NULL && io != NULL);
170 
171  DEBUGMSG2("%s.%d: discovering %s: _sentyet == %d"
172  , __FUNCTION__, __LINE__, basename, self->baseclass._sentyet);
173  // Primitive caching - don't send what we've already sent.
174  if (self->baseclass._sentyet) {
175  const char * oldvalue = cfg->getstring(cfg, basename);
176  if (oldvalue != NULL && strcmp(jsonout, oldvalue) == 0) {
177  DEBUGMSG2("%s.%d: %s sent this value - don't send again."
178  , __FUNCTION__, __LINE__, basename);
179  g_free(jsonout);
180  return;
181  }
182  DEBUGMSG2("%s.%d: %s this value is different from previous value"
183  , __FUNCTION__, __LINE__, basename);
184  }
185  DEBUGMSG2("%s.%d: Sending %"G_GSIZE_FORMAT" bytes of JSON text"
186  , __FUNCTION__, __LINE__, jsonlen);
187  cfg->setstring(cfg, basename, jsonout);
188  cma = cfg->getaddr(cfg, CONFIGNAME_CMADISCOVER);
189  if (cma == NULL) {
190  DEBUGMSG2("%s.%d: %s address is unknown - skipping send"
191  , __FUNCTION__, __LINE__, CONFIGNAME_CMADISCOVER);
192  g_free(jsonout);
193  return;
194  }
195  self->baseclass._sentyet = TRUE;
196 
199  fsf = &jsf->baseclass; // base class object of jsf
200  fsf->setvalue(fsf, jsonout, jsonlen+1, frame_default_valuefinalize); // jsonlen is strlen(jsonout)
201  frameset_append_frame(fs, fsf);
202  DEBUGMSG2("%s.%d: Sending a %"G_GSIZE_FORMAT" bytes JSON frameset"
203  , __FUNCTION__, __LINE__, jsonlen);
204  io->_netio->sendareliablefs(io->_netio, cma, DEFAULT_FSP_QID, fs);
205  ++ self->baseclass.reportcount;
206  UNREF(fsf);
207  UNREF(fs);
208 }
209 
212 jsondiscovery_new(const char * discoverytype,
213  const char * instancename,
214  gint intervalsecs,
215  ConfigContext*jsoninst,
216  NetGSource* iosource,
217  ConfigContext*context,
218  gsize objsize)
219 {
220  const char * basedir = NULL;
221  ConfigContext* jsonparams;
222  JsonDiscovery* ret;
223 
225  g_return_val_if_fail(jsoninst != NULL, NULL);
226  g_return_val_if_fail(*discoverytype != '/', NULL);
227  jsonparams = jsoninst->getconfig(jsoninst, "parameters");
228  g_return_val_if_fail(jsonparams != NULL, NULL);
230  , discovery_new(instancename, iosource, context
231  , objsize < sizeof(JsonDiscovery) ? sizeof(JsonDiscovery) : objsize));
232  g_return_val_if_fail(ret != NULL, NULL);
236  ret->jsonparams = jsonparams;
237  REF(ret->jsonparams);
238  ret->_intervalsecs = intervalsecs;
239  basedir = context->getstring(context, "JSONAGENTROOT");
240  if (NULL == basedir) {
241  basedir = JSONAGENTROOT;
242  }
243  ret->_fullpath = g_strdup_printf("%s%s%s", basedir, "/", discoverytype);
244  ret->logprefix = g_strdup_printf("Discovery %s: ", instancename);
245  DEBUGMSG2("%s.%d: FULLPATH=[%s] discoverytype[%s]"
246  , __FUNCTION__, __LINE__, ret->_fullpath, discoverytype);
248  return ret;
249 }