/proc/net parsing optimizations

This commit is contained in:
Doug MacEachern 2006-07-03 20:17:35 +00:00
parent f26a733bfa
commit b313b3ec27
1 changed files with 50 additions and 89 deletions

View File

@ -1545,13 +1545,13 @@ int sigar_cpu_info_list_get(sigar_t *sigar,
return SIGAR_OK; return SIGAR_OK;
} }
static unsigned int hex2int(const char *x) static SIGAR_INLINE unsigned int hex2int(const char *x, int len)
{ {
int i, ch; int i;
unsigned int j; unsigned int j;
for (i=0, j=0; i<8; i++) { for (i=0, j=0; i<len; i++) {
ch = x[i]; register int ch = x[i];
j <<= 4; j <<= 4;
if (isdigit(ch)) { if (isdigit(ch)) {
j |= ch - '0'; j |= ch - '0';
@ -1567,6 +1567,8 @@ static unsigned int hex2int(const char *x)
return j; return j;
} }
#define HEX_ENT_LEN 8
#ifdef __LP64__ #ifdef __LP64__
#define ROUTE_FMT "%16s %128s %128s %X %ld %ld %ld %128s %ld %ld %ld\n" #define ROUTE_FMT "%16s %128s %128s %X %ld %ld %ld %128s %ld %ld %ld\n"
#else #else
@ -1611,9 +1613,9 @@ int sigar_net_route_list_get(sigar_t *sigar,
} }
route->flags = flags; route->flags = flags;
route->destination = hex2int(net_addr); route->destination = hex2int(net_addr, HEX_ENT_LEN);
route->gateway = hex2int(gate_addr); route->gateway = hex2int(gate_addr, HEX_ENT_LEN);
route->mask = hex2int(mask_addr); route->mask = hex2int(mask_addr, HEX_ENT_LEN);
} }
fclose(fp); fclose(fp);
@ -1683,25 +1685,13 @@ int sigar_net_interface_stat_get(sigar_t *sigar, const char *name,
return found ? SIGAR_OK : ENXIO; return found ? SIGAR_OK : ENXIO;
} }
#define IS_NULL_PTR(ptr) ((ptr == NULL) || (*(ptr) == '\0')) static SIGAR_INLINE int ip_format(char *buffer, int buflen, char *ptr, int len)
#define HEX_ENT_LEN 8
static SIGAR_INLINE int ip_format(char *buffer, int buflen, char *ptr)
{ {
int alen; if (len > HEX_ENT_LEN) {
if (IS_NULL_PTR(ptr)) {
alen = 0;
}
else {
alen = strlen(ptr);
}
if (alen > HEX_ENT_LEN) {
struct in6_addr addr; struct in6_addr addr;
int i; int i;
for (i=0; i<=3; i++, ptr+=8) { for (i=0; i<=3; i++, ptr+=HEX_ENT_LEN) {
addr.s6_addr32[i] = hex2int(ptr); addr.s6_addr32[i] = hex2int(ptr, HEX_ENT_LEN);
} }
if (!inet_ntop(AF_INET6, &addr, buffer, buflen)) { if (!inet_ntop(AF_INET6, &addr, buffer, buflen)) {
return errno; return errno;
@ -1709,7 +1699,7 @@ static SIGAR_INLINE int ip_format(char *buffer, int buflen, char *ptr)
} }
else { else {
struct in_addr addr; struct in_addr addr;
addr.s_addr = (alen == HEX_ENT_LEN) ? hex2int(ptr) : 0; addr.s_addr = (len == HEX_ENT_LEN) ? hex2int(ptr, HEX_ENT_LEN) : 0;
if (!inet_ntop(AF_INET, &addr, buffer, buflen)) { if (!inet_ntop(AF_INET, &addr, buffer, buflen)) {
return errno; return errno;
} }
@ -1747,12 +1737,18 @@ static int proc_net_walker(sigar_net_connection_walker_t *walker,
return SIGAR_OK; /* continue loop */ return SIGAR_OK; /* continue loop */
} }
#define SKIP_WHILE(p, c) while (*p == c) p++
#define SKIP_PAST(p, c) \
while(*p && (*p != c)) p++; \
SKIP_WHILE(p, c)
static int proc_net_read(sigar_net_connection_walker_t *walker, static int proc_net_read(sigar_net_connection_walker_t *walker,
const char *fname, const char *fname,
int type) int type)
{ {
FILE *fp; FILE *fp;
char buffer[8192], *ptr; char buffer[8192];
char *ptr;
int flags = walker->flags; int flags = walker->flags;
if (!(fp = fopen(fname, "r"))) { if (!(fp = fopen(fname, "r"))) {
@ -1763,56 +1759,37 @@ static int proc_net_read(sigar_net_connection_walker_t *walker,
while ((ptr = fgets(buffer, sizeof(buffer), fp))) { while ((ptr = fgets(buffer, sizeof(buffer), fp))) {
sigar_net_connection_t conn; sigar_net_connection_t conn;
char *port = NULL;
char *laddr, *raddr; char *laddr, *raddr;
int laddr_len=0, raddr_len=0;
int status, more; int status, more;
SIGAR_SKIP_SPACE(ptr); /* skip leading space */
if (IS_NULL_PTR(ptr)) { SKIP_WHILE(ptr, ' ');
continue;
}
ptr = sigar_skip_token(ptr); /* skip number */ /* skip "%d: " */
while (isspace(*ptr)) { SKIP_PAST(ptr, ' ');
ptr++;
}
if (IS_NULL_PTR(ptr)) {
continue;
}
if (!(port = strchr(ptr, ':'))) {
continue;
}
*port = '\0';
++port;
conn.local_port = (strtoul(port, &port, 16) & 0xffff);
laddr = ptr; laddr = ptr;
while (*ptr && (*ptr != ':')) {
ptr = port; laddr_len++;
while (isspace(*ptr)) {
ptr++; ptr++;
} }
if (IS_NULL_PTR(ptr)) { SKIP_WHILE(ptr, ':');
continue;
}
if (!(port = strchr(ptr, ':'))) { conn.local_port = (strtoul(ptr, &ptr, 16) & 0xffff);
continue;
} SKIP_WHILE(ptr, ' ');
*port = '\0';
++port;
conn.remote_port = (strtoul(port, &port, 16) & 0xffff);
raddr = ptr; raddr = ptr;
while (*ptr && (*ptr != ':')) {
ptr = port; raddr_len++;
while (isspace(*ptr)) {
ptr++; ptr++;
} }
if (IS_NULL_PTR(ptr)) { SKIP_WHILE(ptr, ':');
continue;
} conn.remote_port = (strtoul(ptr, &ptr, 16) & 0xffff);
SKIP_WHILE(ptr, ' ');
if (!((conn.remote_port && (flags & SIGAR_NETCONN_CLIENT)) || if (!((conn.remote_port && (flags & SIGAR_NETCONN_CLIENT)) ||
(!conn.remote_port && (flags & SIGAR_NETCONN_SERVER)))) (!conn.remote_port && (flags & SIGAR_NETCONN_SERVER))))
@ -1824,7 +1801,7 @@ static int proc_net_read(sigar_net_connection_walker_t *walker,
status = ip_format(conn.local_address, status = ip_format(conn.local_address,
sizeof(conn.local_address), sizeof(conn.local_address),
laddr); laddr, laddr_len);
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
@ -1832,46 +1809,30 @@ static int proc_net_read(sigar_net_connection_walker_t *walker,
status = ip_format(conn.remote_address, status = ip_format(conn.remote_address,
sizeof(conn.remote_address), sizeof(conn.remote_address),
raddr); raddr, raddr_len);
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
} }
/* SIGAR_TCP_* currently matches TCP_* in linux/tcp.h */ /* SIGAR_TCP_* currently matches TCP_* in linux/tcp.h */
sscanf(ptr, "%2x", &conn.state); conn.state = hex2int(ptr, 2);
ptr = sigar_skip_token(ptr); ptr += 2;
SIGAR_SKIP_SPACE(ptr); SKIP_WHILE(ptr, ' ');
if (IS_NULL_PTR(ptr)) {
continue;
}
if (strlen(ptr) < ((HEX_ENT_LEN*2) + 1)) { conn.send_queue = hex2int(ptr, HEX_ENT_LEN);
continue;
}
conn.send_queue = hex2int(ptr);
ptr += HEX_ENT_LEN+1; /* tx + ':' */; ptr += HEX_ENT_LEN+1; /* tx + ':' */;
conn.receive_queue = hex2int(ptr); conn.receive_queue = hex2int(ptr, HEX_ENT_LEN);
ptr += HEX_ENT_LEN; ptr += HEX_ENT_LEN;
SKIP_WHILE(ptr, ' ');
SIGAR_SKIP_SPACE(ptr); SKIP_PAST(ptr, ' '); /* tr:tm->whem */
if (IS_NULL_PTR(ptr)) { SKIP_PAST(ptr, ' '); /* retrnsmt */
continue;
}
ptr = sigar_skip_multiple_token(ptr, 2); /* tr:tm->when retrnsmt */
if (IS_NULL_PTR(ptr)) {
continue;
}
conn.uid = sigar_strtoul(ptr); conn.uid = sigar_strtoul(ptr);
ptr = sigar_skip_token(ptr); SKIP_PAST(ptr, ' '); /* timeout */
if (IS_NULL_PTR(ptr)) {
continue;
}
conn.inode = sigar_strtoul(ptr); conn.inode = sigar_strtoul(ptr);