]> granicus.if.org Git - icinga2/blob - lib/livestatus/servicestable.cpp
add some object locking to the Dump method (which could theoreticylly suffer from...
[icinga2] / lib / livestatus / servicestable.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "livestatus/servicestable.hpp"
4 #include "livestatus/hoststable.hpp"
5 #include "livestatus/servicegroupstable.hpp"
6 #include "livestatus/hostgroupstable.hpp"
7 #include "livestatus/endpointstable.hpp"
8 #include "icinga/service.hpp"
9 #include "icinga/servicegroup.hpp"
10 #include "icinga/hostgroup.hpp"
11 #include "icinga/checkcommand.hpp"
12 #include "icinga/eventcommand.hpp"
13 #include "icinga/timeperiod.hpp"
14 #include "icinga/macroprocessor.hpp"
15 #include "icinga/icingaapplication.hpp"
16 #include "icinga/compatutility.hpp"
17 #include "icinga/pluginutility.hpp"
18 #include "base/configtype.hpp"
19 #include "base/objectlock.hpp"
20 #include "base/json.hpp"
21 #include "base/convert.hpp"
22 #include "base/utility.hpp"
23 #include <boost/tuple/tuple.hpp>
24 #include <boost/algorithm/string/replace.hpp>
25
26 using namespace icinga;
27
28 ServicesTable::ServicesTable(LivestatusGroupByType type)
29         : Table(type)
30 {
31         AddColumns(this);
32 }
33
34
35 void ServicesTable::AddColumns(Table *table, const String& prefix,
36         const Column::ObjectAccessor& objectAccessor)
37 {
38         table->AddColumn(prefix + "description", Column(&ServicesTable::ShortNameAccessor, objectAccessor));
39         table->AddColumn(prefix + "service_description", Column(&ServicesTable::ShortNameAccessor, objectAccessor)); //ugly compatibility hack
40         table->AddColumn(prefix + "display_name", Column(&ServicesTable::DisplayNameAccessor, objectAccessor));
41         table->AddColumn(prefix + "check_command", Column(&ServicesTable::CheckCommandAccessor, objectAccessor));
42         table->AddColumn(prefix + "check_command_expanded", Column(&ServicesTable::CheckCommandExpandedAccessor, objectAccessor));
43         table->AddColumn(prefix + "event_handler", Column(&ServicesTable::EventHandlerAccessor, objectAccessor));
44         table->AddColumn(prefix + "plugin_output", Column(&ServicesTable::PluginOutputAccessor, objectAccessor));
45         table->AddColumn(prefix + "long_plugin_output", Column(&ServicesTable::LongPluginOutputAccessor, objectAccessor));
46         table->AddColumn(prefix + "perf_data", Column(&ServicesTable::PerfDataAccessor, objectAccessor));
47         table->AddColumn(prefix + "notification_period", Column(&Table::EmptyStringAccessor, objectAccessor));
48         table->AddColumn(prefix + "check_period", Column(&ServicesTable::CheckPeriodAccessor, objectAccessor));
49         table->AddColumn(prefix + "notes", Column(&ServicesTable::NotesAccessor, objectAccessor));
50         table->AddColumn(prefix + "notes_expanded", Column(&ServicesTable::NotesExpandedAccessor, objectAccessor));
51         table->AddColumn(prefix + "notes_url", Column(&ServicesTable::NotesUrlAccessor, objectAccessor));
52         table->AddColumn(prefix + "notes_url_expanded", Column(&ServicesTable::NotesUrlExpandedAccessor, objectAccessor));
53         table->AddColumn(prefix + "action_url", Column(&ServicesTable::ActionUrlAccessor, objectAccessor));
54         table->AddColumn(prefix + "action_url_expanded", Column(&ServicesTable::ActionUrlExpandedAccessor, objectAccessor));
55         table->AddColumn(prefix + "icon_image", Column(&ServicesTable::IconImageAccessor, objectAccessor));
56         table->AddColumn(prefix + "icon_image_expanded", Column(&ServicesTable::IconImageExpandedAccessor, objectAccessor));
57         table->AddColumn(prefix + "icon_image_alt", Column(&ServicesTable::IconImageAltAccessor, objectAccessor));
58         table->AddColumn(prefix + "initial_state", Column(&Table::EmptyStringAccessor, objectAccessor));
59         table->AddColumn(prefix + "max_check_attempts", Column(&ServicesTable::MaxCheckAttemptsAccessor, objectAccessor));
60         table->AddColumn(prefix + "current_attempt", Column(&ServicesTable::CurrentAttemptAccessor, objectAccessor));
61         table->AddColumn(prefix + "state", Column(&ServicesTable::StateAccessor, objectAccessor));
62         table->AddColumn(prefix + "has_been_checked", Column(&ServicesTable::HasBeenCheckedAccessor, objectAccessor));
63         table->AddColumn(prefix + "last_state", Column(&ServicesTable::LastStateAccessor, objectAccessor));
64         table->AddColumn(prefix + "last_hard_state", Column(&ServicesTable::LastHardStateAccessor, objectAccessor));
65         table->AddColumn(prefix + "state_type", Column(&ServicesTable::StateTypeAccessor, objectAccessor));
66         table->AddColumn(prefix + "check_type", Column(&ServicesTable::CheckTypeAccessor, objectAccessor));
67         table->AddColumn(prefix + "acknowledged", Column(&ServicesTable::AcknowledgedAccessor, objectAccessor));
68         table->AddColumn(prefix + "acknowledgement_type", Column(&ServicesTable::AcknowledgementTypeAccessor, objectAccessor));
69         table->AddColumn(prefix + "no_more_notifications", Column(&ServicesTable::NoMoreNotificationsAccessor, objectAccessor));
70         table->AddColumn(prefix + "last_time_ok", Column(&ServicesTable::LastTimeOkAccessor, objectAccessor));
71         table->AddColumn(prefix + "last_time_warning", Column(&ServicesTable::LastTimeWarningAccessor, objectAccessor));
72         table->AddColumn(prefix + "last_time_critical", Column(&ServicesTable::LastTimeCriticalAccessor, objectAccessor));
73         table->AddColumn(prefix + "last_time_unknown", Column(&ServicesTable::LastTimeUnknownAccessor, objectAccessor));
74         table->AddColumn(prefix + "last_check", Column(&ServicesTable::LastCheckAccessor, objectAccessor));
75         table->AddColumn(prefix + "next_check", Column(&ServicesTable::NextCheckAccessor, objectAccessor));
76         table->AddColumn(prefix + "last_notification", Column(&ServicesTable::LastNotificationAccessor, objectAccessor));
77         table->AddColumn(prefix + "next_notification", Column(&ServicesTable::NextNotificationAccessor, objectAccessor));
78         table->AddColumn(prefix + "current_notification_number", Column(&ServicesTable::CurrentNotificationNumberAccessor, objectAccessor));
79         table->AddColumn(prefix + "last_state_change", Column(&ServicesTable::LastStateChangeAccessor, objectAccessor));
80         table->AddColumn(prefix + "last_hard_state_change", Column(&ServicesTable::LastHardStateChangeAccessor, objectAccessor));
81         table->AddColumn(prefix + "scheduled_downtime_depth", Column(&ServicesTable::ScheduledDowntimeDepthAccessor, objectAccessor));
82         table->AddColumn(prefix + "is_flapping", Column(&ServicesTable::IsFlappingAccessor, objectAccessor));
83         table->AddColumn(prefix + "checks_enabled", Column(&ServicesTable::ChecksEnabledAccessor, objectAccessor));
84         table->AddColumn(prefix + "accept_passive_checks", Column(&ServicesTable::AcceptPassiveChecksAccessor, objectAccessor));
85         table->AddColumn(prefix + "event_handler_enabled", Column(&ServicesTable::EventHandlerEnabledAccessor, objectAccessor));
86         table->AddColumn(prefix + "notifications_enabled", Column(&ServicesTable::NotificationsEnabledAccessor, objectAccessor));
87         table->AddColumn(prefix + "process_performance_data", Column(&ServicesTable::ProcessPerformanceDataAccessor, objectAccessor));
88         table->AddColumn(prefix + "is_executing", Column(&Table::ZeroAccessor, objectAccessor));
89         table->AddColumn(prefix + "active_checks_enabled", Column(&ServicesTable::ActiveChecksEnabledAccessor, objectAccessor));
90         table->AddColumn(prefix + "check_options", Column(&Table::EmptyStringAccessor, objectAccessor));
91         table->AddColumn(prefix + "flap_detection_enabled", Column(&ServicesTable::FlapDetectionEnabledAccessor, objectAccessor));
92         table->AddColumn(prefix + "check_freshness", Column(&Table::OneAccessor, objectAccessor));
93         table->AddColumn(prefix + "obsess_over_service", Column(&Table::ZeroAccessor, objectAccessor));
94         table->AddColumn(prefix + "modified_attributes", Column(&Table::ZeroAccessor, objectAccessor));
95         table->AddColumn(prefix + "modified_attributes_list", Column(&Table::ZeroAccessor, objectAccessor));
96         table->AddColumn(prefix + "pnpgraph_present", Column(&Table::ZeroAccessor, objectAccessor));
97         table->AddColumn(prefix + "staleness", Column(&ServicesTable::StalenessAccessor, objectAccessor));
98         table->AddColumn(prefix + "check_interval", Column(&ServicesTable::CheckIntervalAccessor, objectAccessor));
99         table->AddColumn(prefix + "retry_interval", Column(&ServicesTable::RetryIntervalAccessor, objectAccessor));
100         table->AddColumn(prefix + "notification_interval", Column(&ServicesTable::NotificationIntervalAccessor, objectAccessor));
101         table->AddColumn(prefix + "first_notification_delay", Column(&Table::EmptyStringAccessor, objectAccessor));
102         table->AddColumn(prefix + "low_flap_threshold", Column(&ServicesTable::LowFlapThresholdAccessor, objectAccessor));
103         table->AddColumn(prefix + "high_flap_threshold", Column(&ServicesTable::HighFlapThresholdAccessor, objectAccessor));
104         table->AddColumn(prefix + "latency", Column(&ServicesTable::LatencyAccessor, objectAccessor));
105         table->AddColumn(prefix + "execution_time", Column(&ServicesTable::ExecutionTimeAccessor, objectAccessor));
106         table->AddColumn(prefix + "percent_state_change", Column(&ServicesTable::PercentStateChangeAccessor, objectAccessor));
107         table->AddColumn(prefix + "in_check_period", Column(&ServicesTable::InCheckPeriodAccessor, objectAccessor));
108         table->AddColumn(prefix + "in_notification_period", Column(&ServicesTable::InNotificationPeriodAccessor, objectAccessor));
109         table->AddColumn(prefix + "contacts", Column(&ServicesTable::ContactsAccessor, objectAccessor));
110         table->AddColumn(prefix + "downtimes", Column(&ServicesTable::DowntimesAccessor, objectAccessor));
111         table->AddColumn(prefix + "downtimes_with_info", Column(&ServicesTable::DowntimesWithInfoAccessor, objectAccessor));
112         table->AddColumn(prefix + "comments", Column(&ServicesTable::CommentsAccessor, objectAccessor));
113         table->AddColumn(prefix + "comments_with_info", Column(&ServicesTable::CommentsWithInfoAccessor, objectAccessor));
114         table->AddColumn(prefix + "comments_with_extra_info", Column(&ServicesTable::CommentsWithExtraInfoAccessor, objectAccessor));
115         table->AddColumn(prefix + "custom_variable_names", Column(&ServicesTable::CustomVariableNamesAccessor, objectAccessor));
116         table->AddColumn(prefix + "custom_variable_values", Column(&ServicesTable::CustomVariableValuesAccessor, objectAccessor));
117         table->AddColumn(prefix + "custom_variables", Column(&ServicesTable::CustomVariablesAccessor, objectAccessor));
118         table->AddColumn(prefix + "groups", Column(&ServicesTable::GroupsAccessor, objectAccessor));
119         table->AddColumn(prefix + "contact_groups", Column(&ServicesTable::ContactGroupsAccessor, objectAccessor));
120         table->AddColumn(prefix + "check_source", Column(&ServicesTable::CheckSourceAccessor, objectAccessor));
121         table->AddColumn(prefix + "is_reachable", Column(&ServicesTable::IsReachableAccessor, objectAccessor));
122         table->AddColumn(prefix + "cv_is_json", Column(&ServicesTable::CVIsJsonAccessor, objectAccessor));
123         table->AddColumn(prefix + "original_attributes", Column(&ServicesTable::OriginalAttributesAccessor, objectAccessor));
124
125         HostsTable::AddColumns(table, "host_", std::bind(&ServicesTable::HostAccessor, _1, objectAccessor));
126
127         /* add additional group by values received through the object accessor */
128         if (table->GetGroupByType() == LivestatusGroupByServiceGroup) {
129                 /* _1 = row, _2 = groupByType, _3 = groupByObject */
130                 Log(LogDebug, "Livestatus")
131                         << "Processing services group by servicegroup table.";
132                 ServiceGroupsTable::AddColumns(table, "servicegroup_", std::bind(&ServicesTable::ServiceGroupAccessor, _1, _2, _3));
133         } else if (table->GetGroupByType() == LivestatusGroupByHostGroup) {
134                 /* _1 = row, _2 = groupByType, _3 = groupByObject */
135                 Log(LogDebug, "Livestatus")
136                         << "Processing services group by hostgroup table.";
137                 HostGroupsTable::AddColumns(table, "hostgroup_", std::bind(&ServicesTable::HostGroupAccessor, _1, _2, _3));
138         }
139 }
140
141 String ServicesTable::GetName() const
142 {
143         return "services";
144 }
145
146 String ServicesTable::GetPrefix() const
147 {
148         return "service";
149 }
150
151 void ServicesTable::FetchRows(const AddRowFunction& addRowFn)
152 {
153         if (GetGroupByType() == LivestatusGroupByServiceGroup) {
154                 for (const ServiceGroup::Ptr& sg : ConfigType::GetObjectsByType<ServiceGroup>()) {
155                         for (const Service::Ptr& service : sg->GetMembers()) {
156                                 /* the caller must know which groupby type and value are set for this row */
157                                 if (!addRowFn(service, LivestatusGroupByServiceGroup, sg))
158                                         return;
159                         }
160                 }
161         } else if (GetGroupByType() == LivestatusGroupByHostGroup) {
162                 for (const HostGroup::Ptr& hg : ConfigType::GetObjectsByType<HostGroup>()) {
163                         ObjectLock ylock(hg);
164                         for (const Host::Ptr& host : hg->GetMembers()) {
165                                 ObjectLock ylock(host);
166                                 for (const Service::Ptr& service : host->GetServices()) {
167                                         /* the caller must know which groupby type and value are set for this row */
168                                         if (!addRowFn(service, LivestatusGroupByHostGroup, hg))
169                                                 return;
170                                 }
171                         }
172                 }
173         } else {
174                 for (const Service::Ptr& service : ConfigType::GetObjectsByType<Service>()) {
175                         if (!addRowFn(service, LivestatusGroupByNone, Empty))
176                                 return;
177                 }
178         }
179 }
180
181 Object::Ptr ServicesTable::HostAccessor(const Value& row, const Column::ObjectAccessor& parentObjectAccessor)
182 {
183         Value service;
184
185         if (parentObjectAccessor)
186                 service = parentObjectAccessor(row, LivestatusGroupByNone, Empty);
187         else
188                 service = row;
189
190         Service::Ptr svc = static_cast<Service::Ptr>(service);
191
192         if (!svc)
193                 return nullptr;
194
195         return svc->GetHost();
196 }
197
198 Object::Ptr ServicesTable::ServiceGroupAccessor(const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject)
199 {
200         /* return the current group by value set from within FetchRows()
201          * this is the servicegroup object used for the table join inside
202          * in AddColumns()
203          */
204         if (groupByType == LivestatusGroupByServiceGroup)
205                 return groupByObject;
206
207         return nullptr;
208 }
209
210 Object::Ptr ServicesTable::HostGroupAccessor(const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject)
211 {
212         /* return the current group by value set from within FetchRows()
213          * this is the servicegroup object used for the table join inside
214          * in AddColumns()
215          */
216         if (groupByType == LivestatusGroupByHostGroup)
217                 return groupByObject;
218
219         return nullptr;
220 }
221
222 Value ServicesTable::ShortNameAccessor(const Value& row)
223 {
224         Service::Ptr service = static_cast<Service::Ptr>(row);
225
226         if (!service)
227                 return Empty;
228
229         return service->GetShortName();
230 }
231
232 Value ServicesTable::DisplayNameAccessor(const Value& row)
233 {
234         Service::Ptr service = static_cast<Service::Ptr>(row);
235
236         if (!service)
237                 return Empty;
238
239         return service->GetDisplayName();
240 }
241
242 Value ServicesTable::CheckCommandAccessor(const Value& row)
243 {
244         Service::Ptr service = static_cast<Service::Ptr>(row);
245
246         if (!service)
247                 return Empty;
248
249         CheckCommand::Ptr checkcommand = service->GetCheckCommand();
250
251         if (checkcommand)
252                 return CompatUtility::GetCommandName(checkcommand) + "!" + CompatUtility::GetCheckableCommandArgs(service);
253
254         return Empty;
255 }
256
257 Value ServicesTable::CheckCommandExpandedAccessor(const Value& row)
258 {
259         Service::Ptr service = static_cast<Service::Ptr>(row);
260
261         if (!service)
262                 return Empty;
263
264         CheckCommand::Ptr checkcommand = service->GetCheckCommand();
265
266         if (checkcommand)
267                 return CompatUtility::GetCommandName(checkcommand) + "!" + CompatUtility::GetCheckableCommandArgs(service);
268
269         return Empty;
270 }
271
272 Value ServicesTable::EventHandlerAccessor(const Value& row)
273 {
274         Service::Ptr service = static_cast<Service::Ptr>(row);
275
276         if (!service)
277                 return Empty;
278
279         EventCommand::Ptr eventcommand = service->GetEventCommand();
280
281         if (eventcommand)
282                 return CompatUtility::GetCommandName(eventcommand);
283
284         return Empty;
285 }
286
287 Value ServicesTable::PluginOutputAccessor(const Value& row)
288 {
289         Service::Ptr service = static_cast<Service::Ptr>(row);
290
291         if (!service)
292                 return Empty;
293
294         String output;
295         CheckResult::Ptr cr = service->GetLastCheckResult();
296
297         if (cr)
298                 output = CompatUtility::GetCheckResultOutput(cr);
299
300         return output;
301 }
302
303 Value ServicesTable::LongPluginOutputAccessor(const Value& row)
304 {
305         Service::Ptr service = static_cast<Service::Ptr>(row);
306
307         if (!service)
308                 return Empty;
309
310         String long_output;
311         CheckResult::Ptr cr = service->GetLastCheckResult();
312
313         if (cr)
314                 long_output = CompatUtility::GetCheckResultLongOutput(cr);
315
316         return long_output;
317 }
318
319 Value ServicesTable::PerfDataAccessor(const Value& row)
320 {
321         Service::Ptr service = static_cast<Service::Ptr>(row);
322
323         if (!service)
324                 return Empty;
325
326         String perfdata;
327         CheckResult::Ptr cr = service->GetLastCheckResult();
328
329         if (!cr)
330                 return Empty;
331
332         return PluginUtility::FormatPerfdata(cr->GetPerformanceData());
333 }
334
335 Value ServicesTable::CheckPeriodAccessor(const Value& row)
336 {
337         Service::Ptr service = static_cast<Service::Ptr>(row);
338
339         if (!service)
340                 return Empty;
341
342         TimePeriod::Ptr checkPeriod = service->GetCheckPeriod();
343
344         if (!checkPeriod)
345                 return Empty;
346
347         return checkPeriod->GetName();
348 }
349
350 Value ServicesTable::NotesAccessor(const Value& row)
351 {
352         Service::Ptr service = static_cast<Service::Ptr>(row);
353
354         if (!service)
355                 return Empty;
356
357         return service->GetNotes();
358 }
359
360 Value ServicesTable::NotesExpandedAccessor(const Value& row)
361 {
362         Service::Ptr service = static_cast<Service::Ptr>(row);
363
364         if (!service)
365                 return Empty;
366
367         MacroProcessor::ResolverList resolvers {
368                 { "service", service },
369                 { "host", service->GetHost() },
370                 { "icinga", IcingaApplication::GetInstance() }
371         };
372
373         return MacroProcessor::ResolveMacros(service->GetNotes(), resolvers);
374 }
375
376 Value ServicesTable::NotesUrlAccessor(const Value& row)
377 {
378         Service::Ptr service = static_cast<Service::Ptr>(row);
379
380         if (!service)
381                 return Empty;
382
383         return service->GetNotesUrl();
384 }
385
386 Value ServicesTable::NotesUrlExpandedAccessor(const Value& row)
387 {
388         Service::Ptr service = static_cast<Service::Ptr>(row);
389
390         if (!service)
391                 return Empty;
392
393         MacroProcessor::ResolverList resolvers {
394                 { "service", service },
395                 { "host", service->GetHost() },
396                 { "icinga", IcingaApplication::GetInstance() }
397         };
398
399         return MacroProcessor::ResolveMacros(service->GetNotesUrl(), resolvers);
400 }
401
402 Value ServicesTable::ActionUrlAccessor(const Value& row)
403 {
404         Service::Ptr service = static_cast<Service::Ptr>(row);
405
406         if (!service)
407                 return Empty;
408
409         return service->GetActionUrl();
410 }
411
412 Value ServicesTable::ActionUrlExpandedAccessor(const Value& row)
413 {
414         Service::Ptr service = static_cast<Service::Ptr>(row);
415
416         if (!service)
417                 return Empty;
418
419         MacroProcessor::ResolverList resolvers {
420                 { "service", service },
421                 { "host", service->GetHost() },
422                 { "icinga", IcingaApplication::GetInstance() }
423         };
424
425         return MacroProcessor::ResolveMacros(service->GetActionUrl(), resolvers);
426 }
427
428 Value ServicesTable::IconImageAccessor(const Value& row)
429 {
430         Service::Ptr service = static_cast<Service::Ptr>(row);
431
432         if (!service)
433                 return Empty;
434
435         return service->GetIconImage();
436 }
437
438 Value ServicesTable::IconImageExpandedAccessor(const Value& row)
439 {
440         Service::Ptr service = static_cast<Service::Ptr>(row);
441
442         if (!service)
443                 return Empty;
444
445         MacroProcessor::ResolverList resolvers {
446                 { "service", service },
447                 { "host", service->GetHost() },
448                 { "icinga", IcingaApplication::GetInstance() }
449         };
450
451         return MacroProcessor::ResolveMacros(service->GetIconImage(), resolvers);
452 }
453
454 Value ServicesTable::IconImageAltAccessor(const Value& row)
455 {
456         Service::Ptr service = static_cast<Service::Ptr>(row);
457
458         if (!service)
459                 return Empty;
460
461         return service->GetIconImageAlt();
462 }
463
464 Value ServicesTable::MaxCheckAttemptsAccessor(const Value& row)
465 {
466         Service::Ptr service = static_cast<Service::Ptr>(row);
467
468         if (!service)
469                 return Empty;
470
471         return service->GetMaxCheckAttempts();
472 }
473
474 Value ServicesTable::CurrentAttemptAccessor(const Value& row)
475 {
476         Service::Ptr service = static_cast<Service::Ptr>(row);
477
478         if (!service)
479                 return Empty;
480
481         return service->GetCheckAttempt();
482 }
483
484 Value ServicesTable::StateAccessor(const Value& row)
485 {
486         Service::Ptr service = static_cast<Service::Ptr>(row);
487
488         if (!service)
489                 return Empty;
490
491         return service->GetState();
492 }
493
494 Value ServicesTable::HasBeenCheckedAccessor(const Value& row)
495 {
496         Service::Ptr service = static_cast<Service::Ptr>(row);
497
498         if (!service)
499                 return Empty;
500
501         return Convert::ToLong(service->HasBeenChecked());
502 }
503
504 Value ServicesTable::LastStateAccessor(const Value& row)
505 {
506         Service::Ptr service = static_cast<Service::Ptr>(row);
507
508         if (!service)
509                 return Empty;
510
511         return service->GetLastState();
512 }
513
514 Value ServicesTable::LastHardStateAccessor(const Value& row)
515 {
516         Service::Ptr service = static_cast<Service::Ptr>(row);
517
518         if (!service)
519                 return Empty;
520
521         return service->GetLastHardState();
522 }
523
524 Value ServicesTable::StateTypeAccessor(const Value& row)
525 {
526         Service::Ptr service = static_cast<Service::Ptr>(row);
527
528         if (!service)
529                 return Empty;
530
531         return service->GetStateType();
532 }
533
534 Value ServicesTable::CheckTypeAccessor(const Value& row)
535 {
536         Service::Ptr service = static_cast<Service::Ptr>(row);
537
538         if (!service)
539                 return Empty;
540
541         return (service->GetEnableActiveChecks() ? 0 : 1); /* 0 .. active, 1 .. passive */
542 }
543
544 Value ServicesTable::AcknowledgedAccessor(const Value& row)
545 {
546         Service::Ptr service = static_cast<Service::Ptr>(row);
547
548         if (!service)
549                 return Empty;
550
551         ObjectLock olock(service);
552         return service->IsAcknowledged();
553 }
554
555 Value ServicesTable::AcknowledgementTypeAccessor(const Value& row)
556 {
557         Service::Ptr service = static_cast<Service::Ptr>(row);
558
559         if (!service)
560                 return Empty;
561
562         ObjectLock olock(service);
563         return service->GetAcknowledgement();
564 }
565
566 Value ServicesTable::NoMoreNotificationsAccessor(const Value& row)
567 {
568         Service::Ptr service = static_cast<Service::Ptr>(row);
569
570         if (!service)
571                 return Empty;
572
573         return (CompatUtility::GetCheckableNotificationNotificationInterval(service) == 0 && !service->GetVolatile()) ? 1 : 0;
574 }
575
576 Value ServicesTable::LastTimeOkAccessor(const Value& row)
577 {
578         Service::Ptr service = static_cast<Service::Ptr>(row);
579
580         if (!service)
581                 return Empty;
582
583         return static_cast<int>(service->GetLastStateOK());
584 }
585
586 Value ServicesTable::LastTimeWarningAccessor(const Value& row)
587 {
588         Service::Ptr service = static_cast<Service::Ptr>(row);
589
590         if (!service)
591                 return Empty;
592
593         return static_cast<int>(service->GetLastStateWarning());
594 }
595
596 Value ServicesTable::LastTimeCriticalAccessor(const Value& row)
597 {
598         Service::Ptr service = static_cast<Service::Ptr>(row);
599
600         if (!service)
601                 return Empty;
602
603         return static_cast<int>(service->GetLastStateCritical());
604 }
605
606 Value ServicesTable::LastTimeUnknownAccessor(const Value& row)
607 {
608         Service::Ptr service = static_cast<Service::Ptr>(row);
609
610         if (!service)
611                 return Empty;
612
613         return static_cast<int>(service->GetLastStateUnknown());
614 }
615
616 Value ServicesTable::LastCheckAccessor(const Value& row)
617 {
618         Service::Ptr service = static_cast<Service::Ptr>(row);
619
620         if (!service)
621                 return Empty;
622
623         return static_cast<int>(service->GetLastCheck());
624 }
625
626 Value ServicesTable::NextCheckAccessor(const Value& row)
627 {
628         Service::Ptr service = static_cast<Service::Ptr>(row);
629
630         if (!service)
631                 return Empty;
632
633         return static_cast<int>(service->GetNextCheck());
634 }
635
636 Value ServicesTable::LastNotificationAccessor(const Value& row)
637 {
638         Service::Ptr service = static_cast<Service::Ptr>(row);
639
640         if (!service)
641                 return Empty;
642
643         return CompatUtility::GetCheckableNotificationLastNotification(service);
644 }
645
646 Value ServicesTable::NextNotificationAccessor(const Value& row)
647 {
648         Service::Ptr service = static_cast<Service::Ptr>(row);
649
650         if (!service)
651                 return Empty;
652
653         return CompatUtility::GetCheckableNotificationNextNotification(service);
654 }
655
656 Value ServicesTable::CurrentNotificationNumberAccessor(const Value& row)
657 {
658         Service::Ptr service = static_cast<Service::Ptr>(row);
659
660         if (!service)
661                 return Empty;
662
663         return CompatUtility::GetCheckableNotificationNotificationNumber(service);
664 }
665
666 Value ServicesTable::LastStateChangeAccessor(const Value& row)
667 {
668         Service::Ptr service = static_cast<Service::Ptr>(row);
669
670         if (!service)
671                 return Empty;
672
673         return static_cast<int>(service->GetLastStateChange());
674 }
675
676 Value ServicesTable::LastHardStateChangeAccessor(const Value& row)
677 {
678         Service::Ptr service = static_cast<Service::Ptr>(row);
679
680         if (!service)
681                 return Empty;
682
683         return static_cast<int>(service->GetLastHardStateChange());
684 }
685
686 Value ServicesTable::ScheduledDowntimeDepthAccessor(const Value& row)
687 {
688         Service::Ptr service = static_cast<Service::Ptr>(row);
689
690         if (!service)
691                 return Empty;
692
693         return service->GetDowntimeDepth();
694 }
695
696 Value ServicesTable::IsFlappingAccessor(const Value& row)
697 {
698         Service::Ptr service = static_cast<Service::Ptr>(row);
699
700         if (!service)
701                 return Empty;
702
703         return service->IsFlapping();
704 }
705
706 Value ServicesTable::ChecksEnabledAccessor(const Value& row)
707 {
708         Service::Ptr service = static_cast<Service::Ptr>(row);
709
710         if (!service)
711                 return Empty;
712
713         return Convert::ToLong(service->GetEnableActiveChecks());
714 }
715
716 Value ServicesTable::AcceptPassiveChecksAccessor(const Value& row)
717 {
718         Service::Ptr service = static_cast<Service::Ptr>(row);
719
720         if (!service)
721                 return Empty;
722
723         return Convert::ToLong(service->GetEnablePassiveChecks());
724 }
725
726 Value ServicesTable::EventHandlerEnabledAccessor(const Value& row)
727 {
728         Service::Ptr service = static_cast<Service::Ptr>(row);
729
730         if (!service)
731                 return Empty;
732
733         return Convert::ToLong(service->GetEnableEventHandler());
734 }
735
736 Value ServicesTable::NotificationsEnabledAccessor(const Value& row)
737 {
738         Service::Ptr service = static_cast<Service::Ptr>(row);
739
740         if (!service)
741                 return Empty;
742
743         return Convert::ToLong(service->GetEnableNotifications());
744 }
745
746 Value ServicesTable::ProcessPerformanceDataAccessor(const Value& row)
747 {
748         Service::Ptr service = static_cast<Service::Ptr>(row);
749
750         if (!service)
751                 return Empty;
752
753         return Convert::ToLong(service->GetEnablePerfdata());
754 }
755
756 Value ServicesTable::ActiveChecksEnabledAccessor(const Value& row)
757 {
758         Service::Ptr service = static_cast<Service::Ptr>(row);
759
760         if (!service)
761                 return Empty;
762
763         return Convert::ToLong(service->GetEnableActiveChecks());
764 }
765
766 Value ServicesTable::FlapDetectionEnabledAccessor(const Value& row)
767 {
768         Service::Ptr service = static_cast<Service::Ptr>(row);
769
770         if (!service)
771                 return Empty;
772
773         return Convert::ToLong(service->GetEnableFlapping());
774 }
775
776 Value ServicesTable::StalenessAccessor(const Value& row)
777 {
778         Service::Ptr service = static_cast<Service::Ptr>(row);
779
780         if (!service)
781                 return Empty;
782
783         if (service->HasBeenChecked() && service->GetLastCheck() > 0)
784                 return (Utility::GetTime() - service->GetLastCheck()) / (service->GetCheckInterval() * 3600);
785
786         return 0.0;
787 }
788
789 Value ServicesTable::CheckIntervalAccessor(const Value& row)
790 {
791         Service::Ptr service = static_cast<Service::Ptr>(row);
792
793         if (!service)
794                 return Empty;
795
796         return service->GetCheckInterval() / 60.0;
797 }
798
799 Value ServicesTable::RetryIntervalAccessor(const Value& row)
800 {
801         Service::Ptr service = static_cast<Service::Ptr>(row);
802
803         if (!service)
804                 return Empty;
805
806         return service->GetRetryInterval() / 60.0;
807 }
808
809 Value ServicesTable::NotificationIntervalAccessor(const Value& row)
810 {
811         Service::Ptr service = static_cast<Service::Ptr>(row);
812
813         if (!service)
814                 return Empty;
815
816         return CompatUtility::GetCheckableNotificationNotificationInterval(service);
817 }
818
819 Value ServicesTable::LowFlapThresholdAccessor(const Value& row)
820 {
821         Service::Ptr service = static_cast<Service::Ptr>(row);
822
823         if (!service)
824                 return Empty;
825
826         return service->GetFlappingThresholdLow();
827 }
828
829 Value ServicesTable::HighFlapThresholdAccessor(const Value& row)
830 {
831         Service::Ptr service = static_cast<Service::Ptr>(row);
832
833         if (!service)
834                 return Empty;
835
836         return service->GetFlappingThresholdHigh();
837 }
838
839 Value ServicesTable::LatencyAccessor(const Value& row)
840 {
841         Service::Ptr service = static_cast<Service::Ptr>(row);
842
843         if (!service)
844                 return Empty;
845
846         CheckResult::Ptr cr = service->GetLastCheckResult();
847
848         if (!cr)
849                 return Empty;
850
851         return cr->CalculateLatency();
852 }
853
854 Value ServicesTable::ExecutionTimeAccessor(const Value& row)
855 {
856         Service::Ptr service = static_cast<Service::Ptr>(row);
857
858         if (!service)
859                 return Empty;
860
861         CheckResult::Ptr cr = service->GetLastCheckResult();
862
863         if (!cr)
864                 return Empty;
865
866         return cr->CalculateExecutionTime();
867 }
868
869 Value ServicesTable::PercentStateChangeAccessor(const Value& row)
870 {
871         Service::Ptr service = static_cast<Service::Ptr>(row);
872
873         if (!service)
874                 return Empty;
875
876         return service->GetFlappingCurrent();
877 }
878
879 Value ServicesTable::InCheckPeriodAccessor(const Value& row)
880 {
881         Service::Ptr service = static_cast<Service::Ptr>(row);
882
883         if (!service)
884                 return Empty;
885
886         TimePeriod::Ptr timeperiod = service->GetCheckPeriod();
887
888         /* none set means always checked */
889         if (!timeperiod)
890                 return 1;
891
892         return Convert::ToLong(timeperiod->IsInside(Utility::GetTime()));
893 }
894
895 Value ServicesTable::InNotificationPeriodAccessor(const Value& row)
896 {
897         Service::Ptr service = static_cast<Service::Ptr>(row);
898
899         if (!service)
900                 return Empty;
901
902         for (const Notification::Ptr& notification : service->GetNotifications()) {
903                 TimePeriod::Ptr timeperiod = notification->GetPeriod();
904
905                 if (!timeperiod || timeperiod->IsInside(Utility::GetTime()))
906                         return 1;
907         }
908
909         return 0;
910 }
911
912 Value ServicesTable::ContactsAccessor(const Value& row)
913 {
914         Service::Ptr service = static_cast<Service::Ptr>(row);
915
916         if (!service)
917                 return Empty;
918
919         ArrayData result;
920
921         for (const User::Ptr& user : CompatUtility::GetCheckableNotificationUsers(service)) {
922                 result.push_back(user->GetName());
923         }
924
925         return new Array(std::move(result));
926 }
927
928 Value ServicesTable::DowntimesAccessor(const Value& row)
929 {
930         Service::Ptr service = static_cast<Service::Ptr>(row);
931
932         if (!service)
933                 return Empty;
934
935         ArrayData result;
936
937         for (const Downtime::Ptr& downtime : service->GetDowntimes()) {
938                 if (downtime->IsExpired())
939                         continue;
940
941                 result.push_back(downtime->GetLegacyId());
942         }
943
944         return new Array(std::move(result));
945 }
946
947 Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
948 {
949         Service::Ptr service = static_cast<Service::Ptr>(row);
950
951         if (!service)
952                 return Empty;
953
954         ArrayData result;
955
956         for (const Downtime::Ptr& downtime : service->GetDowntimes()) {
957                 if (downtime->IsExpired())
958                         continue;
959
960                 result.push_back(new Array({
961                         downtime->GetLegacyId(),
962                         downtime->GetAuthor(),
963                         downtime->GetComment()
964                 }));
965         }
966
967         return new Array(std::move(result));
968 }
969
970 Value ServicesTable::CommentsAccessor(const Value& row)
971 {
972         Service::Ptr service = static_cast<Service::Ptr>(row);
973
974         if (!service)
975                 return Empty;
976
977         ArrayData result;
978
979         for (const Comment::Ptr& comment : service->GetComments()) {
980                 if (comment->IsExpired())
981                         continue;
982
983                 result.push_back(comment->GetLegacyId());
984         }
985
986         return new Array(std::move(result));
987 }
988
989 Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
990 {
991         Service::Ptr service = static_cast<Service::Ptr>(row);
992
993         if (!service)
994                 return Empty;
995
996         ArrayData result;
997
998         for (const Comment::Ptr& comment : service->GetComments()) {
999                 if (comment->IsExpired())
1000                         continue;
1001
1002                 result.push_back(new Array({
1003                         comment->GetLegacyId(),
1004                         comment->GetAuthor(),
1005                         comment->GetText()
1006                 }));
1007         }
1008
1009         return new Array(std::move(result));
1010 }
1011
1012 Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
1013 {
1014         Service::Ptr service = static_cast<Service::Ptr>(row);
1015
1016         if (!service)
1017                 return Empty;
1018
1019         ArrayData result;
1020
1021         for (const Comment::Ptr& comment : service->GetComments()) {
1022                 if (comment->IsExpired())
1023                         continue;
1024
1025                 result.push_back(new Array({
1026                         comment->GetLegacyId(),
1027                         comment->GetAuthor(),
1028                         comment->GetText(),
1029                         comment->GetEntryType(),
1030                         static_cast<int>(comment->GetEntryTime())
1031                 }));
1032         }
1033
1034         return new Array(std::move(result));
1035 }
1036
1037 Value ServicesTable::CustomVariableNamesAccessor(const Value& row)
1038 {
1039         Service::Ptr service = static_cast<Service::Ptr>(row);
1040
1041         if (!service)
1042                 return Empty;
1043
1044         Dictionary::Ptr vars = service->GetVars();
1045
1046         ArrayData result;
1047
1048         if (vars) {
1049                 ObjectLock olock(vars);
1050                 for (const Dictionary::Pair& kv : vars) {
1051                         result.push_back(kv.first);
1052                 }
1053         }
1054
1055         return new Array(std::move(result));
1056 }
1057
1058 Value ServicesTable::CustomVariableValuesAccessor(const Value& row)
1059 {
1060         Service::Ptr service = static_cast<Service::Ptr>(row);
1061
1062         if (!service)
1063                 return Empty;
1064
1065         Dictionary::Ptr vars = service->GetVars();
1066
1067         ArrayData result;
1068
1069         if (vars) {
1070                 ObjectLock olock(vars);
1071                 for (const Dictionary::Pair& kv : vars) {
1072                         if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
1073                                 result.push_back(JsonEncode(kv.second));
1074                         else
1075                                 result.push_back(kv.second);
1076                 }
1077         }
1078
1079         return new Array(std::move(result));
1080 }
1081
1082 Value ServicesTable::CustomVariablesAccessor(const Value& row)
1083 {
1084         Service::Ptr service = static_cast<Service::Ptr>(row);
1085
1086         if (!service)
1087                 return Empty;
1088
1089         Dictionary::Ptr vars = service->GetVars();
1090
1091         ArrayData result;
1092
1093         if (vars) {
1094                 ObjectLock olock(vars);
1095                 for (const Dictionary::Pair& kv : vars) {
1096                         Value val;
1097
1098                         if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
1099                                 val = JsonEncode(kv.second);
1100                         else
1101                                 val = kv.second;
1102
1103                         result.push_back(new Array({
1104                                 kv.first,
1105                                 val
1106                         }));
1107                 }
1108         }
1109
1110         return new Array(std::move(result));
1111 }
1112
1113 Value ServicesTable::CVIsJsonAccessor(const Value& row)
1114 {
1115         Service::Ptr service = static_cast<Service::Ptr>(row);
1116
1117         if (!service)
1118                 return Empty;
1119
1120         Dictionary::Ptr vars = service->GetVars();
1121
1122         if (!vars)
1123                 return Empty;
1124
1125         bool cv_is_json = false;
1126
1127         ObjectLock olock(vars);
1128         for (const Dictionary::Pair& kv : vars) {
1129                 if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
1130                         cv_is_json = true;
1131         }
1132
1133         return cv_is_json;
1134 }
1135
1136 Value ServicesTable::GroupsAccessor(const Value& row)
1137 {
1138         Service::Ptr service = static_cast<Service::Ptr>(row);
1139
1140         if (!service)
1141                 return Empty;
1142
1143         Array::Ptr groups = service->GetGroups();
1144
1145         if (!groups)
1146                 return Empty;
1147
1148         return groups;
1149 }
1150
1151 Value ServicesTable::ContactGroupsAccessor(const Value& row)
1152 {
1153         Service::Ptr service = static_cast<Service::Ptr>(row);
1154
1155         if (!service)
1156                 return Empty;
1157
1158         ArrayData result;
1159
1160         for (const UserGroup::Ptr& usergroup : CompatUtility::GetCheckableNotificationUserGroups(service)) {
1161                 result.push_back(usergroup->GetName());
1162         }
1163
1164         return new Array(std::move(result));
1165 }
1166
1167 Value ServicesTable::CheckSourceAccessor(const Value& row)
1168 {
1169         Service::Ptr service = static_cast<Service::Ptr>(row);
1170
1171         if (!service)
1172                 return Empty;
1173
1174         CheckResult::Ptr cr = service->GetLastCheckResult();
1175
1176         if (cr)
1177                 return cr->GetCheckSource();
1178
1179         return Empty;
1180 }
1181
1182 Value ServicesTable::IsReachableAccessor(const Value& row)
1183 {
1184         Service::Ptr service = static_cast<Service::Ptr>(row);
1185
1186         if (!service)
1187                 return Empty;
1188
1189         return service->IsReachable();
1190 }
1191
1192 Value ServicesTable::OriginalAttributesAccessor(const Value& row)
1193 {
1194         Service::Ptr service = static_cast<Service::Ptr>(row);
1195
1196         if (!service)
1197                 return Empty;
1198
1199         return JsonEncode(service->GetOriginalAttributes());
1200 }