Browse code

sercmd: added command line completion for counters

Command line completion for counters groups and names, for all the
counters RPCs defined in the counters module.

Andrei Pelinescu-Onciul authored on 08/08/2010 17:33:32
Showing 1 changed files
... ...
@@ -32,6 +32,7 @@
32 32
  *  2006-02-14  created by andrei
33 33
  *  2009-06-29  command line completion for cfg groups and vars (andrei)
34 34
  *  2009-06-30  command line completion for mi cmds (andrei)
35
+ *  2010-08-08  command line completion for counters/statistic (andrei)
35 36
  */
36 37
 
37 38
 
... ...
@@ -54,6 +55,7 @@
54 54
 
55 55
 #define USE_CFG_VARS /* cfg group and vars completion */
56 56
 #define USE_MI  /* mi completion */
57
+#define USE_COUNTERS /* counters/statistics completion */
57 58
 #endif
58 59
 
59 60
 #include "parse_listen_id.h"
... ...
@@ -151,6 +153,23 @@ str* mi_cmds;
151 151
 int mi_cmds_no;
152 152
 #endif /* USE_MI */
153 153
 
154
+#ifdef USE_COUNTERS
155
+struct binrpc_val* cnt_grps_array; /* response array */
156
+int cnt_grps_no; /* number of response records */
157
+
158
+struct cnt_var_grp {
159
+	struct cnt_var_grp * next;
160
+	str grp_name;
161
+	str* var_names; /**< str array (null terminated strings)*/
162
+	int var_no;
163
+	struct binrpc_val* cnt_vars_array; /* var_name will point here */
164
+	int cnt_vars_no; /* cnt_vars_array size (no. of response records) */
165
+};
166
+
167
+struct cnt_var_grp* cnt_grp_lst; /* counters groups list, allong with vars */
168
+struct cnt_var_grp* crt_cnt_grp;
169
+#endif /* USE_COUNTERS */
170
+
154 171
 
155 172
 
156 173
 #define IOV_SET(vect, str) \
... ...
@@ -279,6 +298,10 @@ enum complete_states {
279 279
 #ifdef USE_MI
280 280
 	COMPLETE_MI,
281 281
 #endif /* USE_Mi */
282
+#ifdef USE_COUNTERS
283
+	COMPLETE_CNT_GRP,
284
+	COMPLETE_CNT_VAR,
285
+#endif /* USE_COUNTERS */
282 286
 	COMPLETE_NOTHING
283 287
 };
284 288
 
... ...
@@ -321,6 +344,26 @@ char* complete_params_mi[]={
321 321
 };
322 322
 #endif /* USE_MI */
323 323
 
324
+#ifdef USE_COUNTERS
325
+/* commands for which we complete the first param with a counter group */
326
+char* complete_param1_counter_grp[] = {
327
+	"cnt.get",
328
+	"cnt.get_raw",
329
+	"cnt.grp_get_all",
330
+	"cnt.reset",
331
+	"cnt.var_list",
332
+	0
333
+};
334
+
335
+/* commands for which we completed the 2nd param with a counter name */
336
+char* complete_param2_counter_name[] = {
337
+	"cnt.get",
338
+	"cnt.get_raw",
339
+	"cnt.reset",
340
+	0
341
+};
342
+#endif /* USE_COUNTERS */
343
+
324 344
 #endif /* USE_READLINE */
325 345
 
326 346
 
... ...
@@ -1196,7 +1239,7 @@ error:
1196 1196
 
1197 1197
 
1198 1198
 
1199
-#if defined(USE_CFG_VARS) || defined (USE_MI)
1199
+#if defined(USE_CFG_VARS) || defined (USE_MI) || defined (USE_COUNTERS)
1200 1200
 /** check if cmd is a rpc command.
1201 1201
  * Quick check (using the internal rpc_array) if cmd is a valid rpc command.
1202 1202
  * @param cmd - null terminated ascii string
... ...
@@ -1491,6 +1534,158 @@ void free_mi_cmds()
1491 1491
 
1492 1492
 
1493 1493
 
1494
+#ifdef USE_COUNTERS
1495
+/* retrieve the counters names and group list */
1496
+static int get_counters_list(int s)
1497
+{
1498
+	struct binrpc_cmd cmd;
1499
+	int cookie;
1500
+	unsigned char reply_buf[MAX_REPLY_SIZE];
1501
+	unsigned char* msg_body;
1502
+	struct binrpc_parse_ctx in_pkt;
1503
+	struct cnt_var_grp* grp;
1504
+	struct cnt_var_grp* last_grp;
1505
+	str grp_name;
1506
+	str var_name;
1507
+	int r;
1508
+	int ret;
1509
+	
1510
+	cmd.method="cnt.grps_list";
1511
+	cmd.argc=0;
1512
+	if (!is_rpc_cmd(cmd.method)) goto error;
1513
+	
1514
+	cookie=gen_cookie();
1515
+	if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
1516
+		if (ret==-1) goto error_send;
1517
+		else goto binrpc_err;
1518
+	}
1519
+	/* read reply */
1520
+	memset(&in_pkt, 0, sizeof(in_pkt));
1521
+	if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
1522
+					&msg_body))<0){
1523
+		goto error;
1524
+	}
1525
+	switch(in_pkt.type){
1526
+		case BINRPC_FAULT:
1527
+			if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
1528
+				goto error;
1529
+			}
1530
+			break;
1531
+		case BINRPC_REPL:
1532
+			cnt_grps_no=20; /* default counter list */
1533
+			if ((cnt_grps_array=parse_reply_body(&cnt_grps_no, &in_pkt,
1534
+												msg_body, in_pkt.tlen))==0)
1535
+				goto error;
1536
+			break;
1537
+		default:
1538
+			fprintf(stderr, "ERROR: not a reply\n");
1539
+			goto error;
1540
+	}
1541
+	/* get the config groups */
1542
+	last_grp=0;
1543
+	for (r=0; r<cnt_grps_no; r++){
1544
+		grp_name.s=0; grp_name.len=0;
1545
+		if (cnt_grps_array[r].type!=BINRPC_T_STR)
1546
+			continue;
1547
+		grp_name=cnt_grps_array[r].u.strval;
1548
+		/* check for duplicates */
1549
+		for (grp=cnt_grp_lst; grp; grp=grp->next){
1550
+			if (grp->grp_name.len==grp_name.len &&
1551
+					memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){
1552
+				break; /* found */
1553
+			}
1554
+		}
1555
+		if (grp==0){
1556
+			/* not found => create a new one  */
1557
+			grp=malloc(sizeof(*grp));
1558
+			if (grp==0) goto error_mem;
1559
+			memset(grp, 0, sizeof(*grp));
1560
+			grp->grp_name=grp_name;
1561
+			if (last_grp){
1562
+				last_grp->next=grp;
1563
+				last_grp=grp;
1564
+			}else{
1565
+				cnt_grp_lst=grp;
1566
+				last_grp=cnt_grp_lst;
1567
+			}
1568
+		}
1569
+	}
1570
+	/* gets vars per group */
1571
+	for (grp=cnt_grp_lst; grp; grp=grp->next){
1572
+		cmd.method="cnt.var_list";
1573
+		cmd.argv[0].type=BINRPC_T_STR;
1574
+		cmd.argv[0].u.strval=grp->grp_name;
1575
+		cmd.argc=1;
1576
+		if (!is_rpc_cmd(cmd.method)) goto error;
1577
+		cookie=gen_cookie();
1578
+		if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
1579
+			if (ret==-1) goto error_send;
1580
+			else goto binrpc_err;
1581
+		}
1582
+		/* read reply */
1583
+		memset(&in_pkt, 0, sizeof(in_pkt));
1584
+		if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
1585
+						&msg_body))<0){
1586
+			goto error;
1587
+		}
1588
+		switch(in_pkt.type){
1589
+			case BINRPC_FAULT:
1590
+				if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
1591
+					goto error;
1592
+				}
1593
+				break;
1594
+			case BINRPC_REPL:
1595
+				grp->cnt_vars_no=100; /* default counter list */
1596
+				if ((grp->cnt_vars_array=parse_reply_body(&grp->cnt_vars_no,
1597
+												&in_pkt, msg_body,
1598
+												in_pkt.tlen))==0)
1599
+				goto error;
1600
+				break;
1601
+			default:
1602
+				fprintf(stderr, "ERROR: not a reply\n");
1603
+				goto error;
1604
+		}
1605
+		grp->var_no = 0;
1606
+		grp->var_names=malloc(sizeof(str)*grp->cnt_vars_no);
1607
+		if (grp->var_names==0) goto error_mem;
1608
+		memset(grp->var_names, 0, sizeof(str)*grp->var_no);
1609
+		for (r=0; r<grp->cnt_vars_no; r++) {
1610
+			if (grp->cnt_vars_array[r].type!=BINRPC_T_STR)
1611
+				continue;
1612
+			var_name=grp->cnt_vars_array[r].u.strval;
1613
+			grp->var_names[grp->var_no] = var_name;
1614
+			grp->var_no++;
1615
+		}
1616
+	}
1617
+	return 0;
1618
+binrpc_err:
1619
+error_send:
1620
+error:
1621
+error_mem:
1622
+	return -1;
1623
+}
1624
+
1625
+
1626
+
1627
+void free_cnt_grp_lst()
1628
+{
1629
+	struct cnt_var_grp* grp;
1630
+	struct cnt_var_grp* last;
1631
+	
1632
+	grp=cnt_grp_lst;
1633
+	while(grp){
1634
+		last=grp;
1635
+		grp=grp->next;
1636
+		if (last->cnt_vars_array)
1637
+			free_rpc_array(last->cnt_vars_array, last->cnt_vars_no);
1638
+		free(last);
1639
+	}
1640
+	cnt_grp_lst=0;
1641
+}
1642
+#endif /* USE_COUNTERS */
1643
+
1644
+
1645
+
1494 1646
 
1495 1647
 static void print_formatting(char* prefix, char* format, char* suffix)
1496 1648
 {
... ...
@@ -1611,6 +1806,9 @@ static char* sercmd_generator(const char* text, int state)
1611 1611
 #ifdef USE_CFG_VARS
1612 1612
 	static struct cfg_var_grp* grp;
1613 1613
 #endif
1614
+#ifdef USE_COUNTERS
1615
+	static struct cnt_var_grp* cnt_grp;
1616
+#endif
1614 1617
 	switch(attempted_completion_state){
1615 1618
 		case COMPLETE_INIT:
1616 1619
 		case COMPLETE_NOTHING:
... ...
@@ -1722,6 +1920,52 @@ static char* sercmd_generator(const char* text, int state)
1722 1722
 			}
1723 1723
 			break;
1724 1724
 #endif /* USE_MI */
1725
+#ifdef USE_COUNTERS
1726
+		case COMPLETE_CNT_GRP:
1727
+			if (state==0){
1728
+				/* init */
1729
+				len=strlen(text);
1730
+				cnt_grp=cnt_grp_lst;
1731
+			}else{
1732
+				cnt_grp=cnt_grp->next;
1733
+			}
1734
+			for(;cnt_grp; cnt_grp=cnt_grp->next){
1735
+				if (len<=cnt_grp->grp_name.len &&
1736
+						memcmp(text, cnt_grp->grp_name.s, len)==0) {
1737
+					/* zero-term copy of the cnt_grp name */
1738
+					name=malloc(cnt_grp->grp_name.len+1);
1739
+					if (name){
1740
+						memcpy(name, cnt_grp->grp_name.s,
1741
+									cnt_grp->grp_name.len);
1742
+						name[cnt_grp->grp_name.len]=0;
1743
+					}
1744
+					return name;
1745
+				}
1746
+			}
1747
+			break;
1748
+		case COMPLETE_CNT_VAR:
1749
+			if (state==0){
1750
+				/* init */
1751
+				len=strlen(text);
1752
+				idx=0;
1753
+			}
1754
+			while(idx < crt_cnt_grp->var_no){
1755
+				if (len<=crt_cnt_grp->var_names[idx].len &&
1756
+						memcmp(text, crt_cnt_grp->var_names[idx].s, len)==0) {
1757
+					/* zero-term copy of the var name */
1758
+					name=malloc(crt_cnt_grp->var_names[idx].len+1);
1759
+					if (name){
1760
+						memcpy(name, crt_cnt_grp->var_names[idx].s,
1761
+									 crt_cnt_grp->var_names[idx].len);
1762
+						name[crt_cnt_grp->var_names[idx].len]=0;
1763
+					}
1764
+					idx++;
1765
+					return name;
1766
+				}
1767
+				idx++;
1768
+			}
1769
+			break;
1770
+#endif /* USE_COUNTERS */
1725 1771
 	}
1726 1772
 	/* no matches */
1727 1773
 	return 0;
... ...
@@ -1739,6 +1983,11 @@ char** sercmd_completion(const char* text, int start, int end)
1739 1739
 	static int grp_start;
1740 1740
 	int grp_len;
1741 1741
 #endif /* USE_CFG_VARS */
1742
+#ifdef USE_COUNTERS
1743
+	struct cnt_var_grp* cnt_grp;
1744
+	static int cnt_grp_start;
1745
+	int cnt_grp_len;
1746
+#endif /* USE_COUNTERS */
1742 1747
 	
1743 1748
 	crt_param_no=0;
1744 1749
 	/* skip over whitespace at the beginning */
... ...
@@ -1751,6 +2000,9 @@ char** sercmd_completion(const char* text, int start, int end)
1751 1751
 #ifdef USE_CFG_VARS
1752 1752
 		grp_start=0;
1753 1753
 #endif /* USE_CFG_VARS */
1754
+#ifdef USE_COUNTERS
1755
+		cnt_grp_start=0;
1756
+#endif /* USE_COUNTERS */
1754 1757
 	}else{ /* or if this is a command for which we complete the parameters */
1755 1758
 		/* find first whitespace after command name*/
1756 1759
 		for(; (j<start) && (rl_line_buffer[j]!=' ') &&
... ...
@@ -1802,6 +2054,19 @@ char** sercmd_completion(const char* text, int start, int end)
1802 1802
 				}
1803 1803
 			}
1804 1804
 #endif /* USE_MI */
1805
+#ifdef USE_COUNTERS
1806
+			/* try  complete_param*_cfg_grp */
1807
+			for(i=0; complete_param1_counter_grp[i]; i++){
1808
+				if ((cmd_len==strlen(complete_param1_counter_grp[i])) &&
1809
+						(strncmp(&rl_line_buffer[cmd_start],
1810
+								 complete_param1_counter_grp[i],
1811
+								 cmd_len)==0)){
1812
+						attempted_completion_state=COMPLETE_CNT_GRP;
1813
+						cnt_grp_start=start;
1814
+						goto end;
1815
+				}
1816
+			}
1817
+#endif /* USE_COUNTERS */
1805 1818
 		}else if (crt_param_no==2){
1806 1819
 #ifdef USE_CFG_VARS
1807 1820
 			/* see if we complete cfg. var names for this command */
... ...
@@ -1831,6 +2096,35 @@ char** sercmd_completion(const char* text, int start, int end)
1831 1831
 				}
1832 1832
 			}
1833 1833
 #endif /* USE_CFG_VARS */
1834
+#ifdef USE_COUNTERS
1835
+			/* see if we complete counter names for this command */
1836
+			for(i=0; complete_param2_counter_name[i]; i++){
1837
+				if ((cmd_len==strlen(complete_param2_counter_name[i])) &&
1838
+						(strncmp(&rl_line_buffer[cmd_start],
1839
+								complete_param2_counter_name[i],
1840
+								cmd_len)==0)){
1841
+					/* get the group name: */
1842
+					/* find grp_start */
1843
+					for(j=cmd_end; (j<start) && ((rl_line_buffer[j]==' ') ||
1844
+									(rl_line_buffer[j]=='\t')); j++);
1845
+					cnt_grp_start=j;
1846
+					/* find group end / cnt_grp_len*/
1847
+					for(j=cnt_grp_start; (j<start) &&
1848
+							(rl_line_buffer[j]!=' ') &&
1849
+							(rl_line_buffer[j]!='\t'); j++);
1850
+					cnt_grp_len=j-cnt_grp_start;
1851
+					for(cnt_grp=cnt_grp_lst; cnt_grp; cnt_grp=cnt_grp->next){
1852
+						if (cnt_grp_len==cnt_grp->grp_name.len &&
1853
+								memcmp(&rl_line_buffer[cnt_grp_start],
1854
+										cnt_grp->grp_name.s, cnt_grp_len)==0) {
1855
+							attempted_completion_state=COMPLETE_CNT_VAR;
1856
+							crt_cnt_grp=cnt_grp;
1857
+							goto end;
1858
+						}
1859
+					}
1860
+				}
1861
+			}
1862
+#endif /* COUNTERS */
1834 1863
 		}
1835 1864
 		attempted_completion_state=COMPLETE_NOTHING;
1836 1865
 	}
... ...
@@ -2000,6 +2294,9 @@ int main(int argc, char** argv)
2000 2000
 	#ifdef USE_MI
2001 2001
 		get_mi_list(s);
2002 2002
 	#endif /* USE_MI */
2003
+	#ifdef USE_COUNTERS
2004
+		get_counters_list(s);
2005
+	#endif /* USE_COUNTERS */
2003 2006
 	}
2004 2007
 	/* banners */
2005 2008
 	printf("%s %s\n", NAME, VERSION);
... ...
@@ -2068,6 +2365,15 @@ end:
2068 2068
 		mi_which_no=0;
2069 2069
 	}
2070 2070
 #endif /* USE_MI */
2071
+#ifdef USE_COUNTERS
2072
+	if (cnt_grp_lst)
2073
+		free_cnt_grp_lst();
2074
+	if (cnt_grps_array){
2075
+		free_rpc_array(cnt_grps_array, cnt_grps_no);
2076
+		cnt_grps_array=0;
2077
+		cnt_grps_no=0;
2078
+	}
2079
+#endif /* USE_COUNTERS */
2071 2080
 	cleanup();
2072 2081
 	exit(0);
2073 2082
 error:
... ...
@@ -2095,6 +2401,15 @@ error:
2095 2095
 		mi_which_no=0;
2096 2096
 	}
2097 2097
 #endif /* USE_MI */
2098
+#ifdef USE_COUNTERS
2099
+	if (cnt_grp_lst)
2100
+		free_cnt_grp_lst();
2101
+	if (cnt_grps_array){
2102
+		free_rpc_array(cnt_grps_array, cnt_grps_no);
2103
+		cnt_grps_array=0;
2104
+		cnt_grps_no=0;
2105
+	}
2106
+#endif /* USE_COUNTERS */
2098 2107
 	cleanup();
2099 2108
 	exit(-1);
2100 2109
 }