1818#include <stdlib.h>
1919#include <string.h>
2020#include <stddef.h>
21+ #include <unistd.h>
2122
2223#include "comdb2.h"
2324#include "reqlog_int.h"
@@ -37,57 +38,75 @@ typedef struct systable_api_history {
3738 cdb2_client_datetime_t last_seen ;
3839} systable_api_history_t ;
3940
40- static void append_entries (systable_api_history_t * * data , int * nrecords , api_history_t * api_history , const char * host , const char * task )
41+ typedef struct api_history_collect_ctx {
42+ systable_api_history_t * cursor ;
43+ const char * host ;
44+ const char * task ;
45+ int nrecords ;
46+ } api_history_collect_ctx_t ;
47+
48+ static int collect_api_history_rows (void * obj , void * arg )
4149{
42- acquire_api_history_lock (api_history , 0 );
43- int num_entries = get_num_api_history_entries (api_history );
44- assert (num_entries > -1 );
45- if (!num_entries ) {
46- release_api_history_lock (api_history );
47- return ;
48- }
50+ api_driver_t * entry = (api_driver_t * )obj ;
51+ api_history_collect_ctx_t * ctx = (api_history_collect_ctx_t * )arg ;
52+ systable_api_history_t * row = ctx -> cursor ;
53+ row -> host = strdup (ctx -> host ? ctx -> host : "unknown" );
54+ row -> task = strdup (ctx -> task ? ctx -> task : "unknown" );
55+ row -> api_driver_name = strdup (entry -> name ? entry -> name : "unknown" );
56+ row -> api_driver_version = strdup (entry -> version ? entry -> version : "unknown" );
57+ dttz_t dt = (dttz_t ){.dttz_sec = entry -> last_seen ? entry -> last_seen : time (NULL )};
58+ dttz_to_client_datetime (& dt , "UTC" , & row -> last_seen );
59+ ctx -> cursor ++ ;
60+ ctx -> nrecords ++ ;
61+ return 0 ;
62+ }
4963
50- int prev = * nrecords ;
51- * nrecords += num_entries ;
52- systable_api_history_t * buffer = realloc (* data , * nrecords * sizeof (systable_api_history_t ));
53-
54- void * curr = NULL ;
55- unsigned int iter = 0 ;
56- for (unsigned int i = prev ; i < * nrecords ; i ++ ) {
57- api_driver_t * entry = get_next_api_history_entry (api_history , & curr , & iter );
58- assert (entry );
59-
60- buffer [i ].host = strdup (host );
61- buffer [i ].task = strdup (task );
62- buffer [i ].api_driver_name = strdup (entry -> name );
63- buffer [i ].api_driver_version = strdup (entry -> version );
64-
65- dttz_t dt = (dttz_t ){.dttz_sec = entry -> last_seen };
66- dttz_to_client_datetime (& dt , "UTC" , & buffer [i ].last_seen );
67- }
64+ static int count_api_entries (void * obj , void * arg )
65+ {
66+ nodestats_t * entry = (nodestats_t * )obj ;
67+ int * total = (int * )arg ;
68+ if (entry -> rawtotals .api_history )
69+ * total += get_num_api_history_entries (entry -> rawtotals .api_history );
70+ return 0 ;
71+ }
6872
69- * data = buffer ;
70- release_api_history_lock (api_history );
73+ static int collect_node_api_history (void * obj , void * arg )
74+ {
75+ nodestats_t * entry = (nodestats_t * )obj ;
76+ api_history_collect_ctx_t * ctx = (api_history_collect_ctx_t * )arg ;
77+ ctx -> host = entry -> host ;
78+ ctx -> task = entry -> task ;
79+ if (entry -> rawtotals .api_history )
80+ hash_for_api_history (entry -> rawtotals .api_history , collect_api_history_rows , ctx );
81+ return 0 ;
7182}
7283
7384int init_api_history_data (void * * data , int * nrecords )
7485{
7586 * nrecords = 0 ;
76- systable_api_history_t * systable = calloc ( * nrecords , sizeof ( systable_api_history_t ));
87+
7788 acquire_clientstats_lock (0 );
78-
79- void * curr = NULL ;
80- unsigned int iter = 0 ;
81- nodestats_t * entry = get_next_clientstats_entry (& curr , & iter );
82-
83- while (entry ) {
84- assert (entry -> rawtotals .api_history );
85- Pthread_mutex_lock (& entry -> rawtotals .lk );
86- append_entries (& systable , nrecords , entry -> rawtotals .api_history , entry -> host , entry -> task );
87- Pthread_mutex_unlock (& entry -> rawtotals .lk );
88- entry = get_next_clientstats_entry (& curr , & iter );
89+
90+ int total_entries = 0 ;
91+ hash_for_clientstats (count_api_entries , & total_entries );
92+
93+ if (total_entries == 0 ) { //no clientstats so no api history entries
94+ * data = NULL ;
95+ release_clientstats_lock ();
96+ return 0 ;
97+ }
98+
99+ systable_api_history_t * systable = calloc (total_entries , sizeof (systable_api_history_t ));
100+ if (!systable ) {
101+ logmsg (LOGMSG_ERROR , "%s: out of memory for %d entries\n" , __func__ , total_entries );
102+ release_clientstats_lock ();
103+ return SQLITE_NOMEM ;
89104 }
90105
106+ api_history_collect_ctx_t ctx = { .cursor = systable , .host = NULL , .task = NULL , .nrecords = 0 };
107+ hash_for_clientstats (collect_node_api_history , & ctx );
108+
109+ * nrecords = ctx .nrecords ;
91110 * data = systable ;
92111 release_clientstats_lock ();
93112 return 0 ;
0 commit comments