// ----------------------------------------------------------------------------
// helper functions
+procfile *ff = NULL;
+
long get_processors(void) {
int processors = 0;
- procfile *ff = procfile_open("/proc/stat", "");
+ ff = procfile_reopen(ff, "/proc/stat", "");
if(!ff) return 1;
ff = procfile_readall(ff);
if(!ff) {
- procfile_close(ff);
+ // procfile_close(ff);
return 1;
}
processors--;
if(processors < 1) processors = 1;
- procfile_close(ff);
+ // procfile_close(ff);
return processors;
}
long get_pid_max(void) {
long mpid = 32768;
- procfile *ff = procfile_open("/proc/sys/kernel/pid_max", "");
+ ff = procfile_reopen(ff, "/proc/sys/kernel/pid_max", "");
if(!ff) return mpid;
ff = procfile_readall(ff);
if(!ff) {
- procfile_close(ff);
+ // procfile_close(ff);
return mpid;
}
mpid = atol(procfile_lineword(ff, 0, 0));
if(mpid) mpid = 32768;
- procfile_close(ff);
+ // procfile_close(ff);
return mpid;
}
snprintf(filename, FILENAME_MAX, "/proc/%d/stat", p->pid);
- procfile *ff = procfile_open(filename, "");
+ ff = procfile_reopen(ff, filename, "");
if(!ff) return 1;
ff = procfile_readall(ff);
if(!ff) {
- procfile_close(ff);
+ // procfile_close(ff);
return 1;
}
if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: VALUES: %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", p->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
- procfile_close(ff);
+ // procfile_close(ff);
return 0;
}
snprintf(filename, FILENAME_MAX, "/proc/%d/statm", p->pid);
- procfile *ff = procfile_open(filename, "");
+ ff = procfile_reopen(ff, filename, "");
if(!ff) return 1;
ff = procfile_readall(ff);
if(!ff) {
- procfile_close(ff);
+ // procfile_close(ff);
return 1;
}
p->statm_data = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
p->statm_dirty = strtoull(procfile_lineword(ff, 0, 6), NULL, 10);
- procfile_close(ff);
+ // procfile_close(ff);
return 0;
}
snprintf(filename, FILENAME_MAX, "/proc/%d/io", p->pid);
- procfile *ff = procfile_open(filename, ":");
+ ff = procfile_reopen(ff, filename, ":");
if(!ff) return 1;
ff = procfile_readall(ff);
if(!ff) {
- procfile_close(ff);
+ // procfile_close(ff);
return 1;
}
p->io_storage_bytes_written = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
p->io_cancelled_write_bytes = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
- procfile_close(ff);
+ // procfile_close(ff);
return 0;
}
info("apps.plugin: starting...");
+ procfile_adaptive_initial_allocation = 1;
+
unsigned long started_t = time(NULL), current_t;
Hertz = get_hertz();
pid_max = get_pid_max();
#define PF_PREFIX "PROCFILE"
+#define PFWORDS_INCREASE_STEP 200
+#define PFLINES_INCREASE_STEP 10
+#define PROCFILE_INCREMENT_BUFFER 512
+
+int procfile_adaptive_initial_allocation = 0;
+
+// if adaptive allocation is set, these store the
+// max values we have seen so far
+uint32_t procfile_max_lines = PFLINES_INCREASE_STEP;
+uint32_t procfile_max_words = PFWORDS_INCREASE_STEP;
+size_t procfile_max_allocation = PROCFILE_INCREMENT_BUFFER;
+
// ----------------------------------------------------------------------------
// An array of words
-#define PFWORDS_INCREASE_STEP 200
pfwords *pfwords_add(pfwords *fw, char *str) {
// debug(D_PROCFILE, PF_PREFIX ": adding word No %d: '%s'", fw->len, str);
pfwords *pfwords_new(void) {
// debug(D_PROCFILE, PF_PREFIX ": initializing words");
- pfwords *new = malloc(sizeof(pfwords) + PFWORDS_INCREASE_STEP * sizeof(char *));
+ uint32_t size = (procfile_adaptive_initial_allocation) ? procfile_max_words : PFWORDS_INCREASE_STEP;
+
+ pfwords *new = malloc(sizeof(pfwords) + size * sizeof(char *));
if(!new) return NULL;
new->len = 0;
- new->size = PFWORDS_INCREASE_STEP;
+ new->size = size;
return new;
}
// ----------------------------------------------------------------------------
// An array of lines
-#define PFLINES_INCREASE_STEP 10
-
pflines *pflines_add(pflines *fl, uint32_t first_word) {
// debug(D_PROCFILE, PF_PREFIX ": adding line %d at word %d", fl->len, first_word);
pflines *pflines_new(void) {
// debug(D_PROCFILE, PF_PREFIX ": initializing lines");
- pflines *new = malloc(sizeof(pflines) + PFLINES_INCREASE_STEP * sizeof(ffline));
+ uint32_t size = (procfile_adaptive_initial_allocation) ? procfile_max_words : PFLINES_INCREASE_STEP;
+
+ pflines *new = malloc(sizeof(pflines) + size * sizeof(ffline));
if(!new) return NULL;
new->len = 0;
- new->size = PFLINES_INCREASE_STEP;
+ new->size = size;
return new;
}
// ----------------------------------------------------------------------------
// The procfile
-#define PROCFILE_INITIAL_BUFFER 256
-#define PROCFILE_INCREMENT_BUFFER 512
-
#define PF_CHAR_IS_SEPARATOR 0
#define PF_CHAR_IS_NEWLINE 1
#define PF_CHAR_IS_WORD 2
ff = procfile_parser(ff);
+ if(procfile_adaptive_initial_allocation) {
+ if(ff->len > procfile_max_allocation) procfile_max_allocation = ff->len;
+ if(ff->lines->len > procfile_max_lines) procfile_max_lines = ff->lines->len;
+ if(ff->words->len > procfile_max_words) procfile_max_words = ff->words->len;
+ }
+
debug(D_PROCFILE, "File '%s' updated.", ff->filename);
return ff;
}
return NULL;
}
- procfile *ff = malloc(sizeof(procfile) + PROCFILE_INITIAL_BUFFER);
+ size_t size = (procfile_adaptive_initial_allocation) ? procfile_max_allocation : PROCFILE_INCREMENT_BUFFER;
+ procfile *ff = malloc(sizeof(procfile) + size);
if(!ff) {
error(PF_PREFIX ": Cannot allocate memory for file '%s'. Reason: %s", filename, strerror(errno));
close(fd);
ff->filename[FILENAME_MAX] = '\0';
ff->fd = fd;
- ff->size = PROCFILE_INITIAL_BUFFER;
+ ff->size = size;
ff->len = 0;
ff->lines = pflines_new();
return ff;
}
+procfile *procfile_reopen(procfile *ff, const char *filename, const char *separators) {
+ if(!ff) return procfile_open(filename, separators);
+
+ if(ff->fd != -1) close(ff->fd);
+
+ ff->fd = open(filename, O_RDONLY, 0666);
+ if(ff->fd == -1) {
+ procfile_close(ff);
+ return NULL;
+ }
+
+ strncpy(ff->filename, filename, FILENAME_MAX);
+ ff->filename[FILENAME_MAX] = '\0';
+
+ return ff;
+}
// ----------------------------------------------------------------------------
// example parsing of procfile data
typedef struct {
char filename[FILENAME_MAX + 1];
int fd; // the file desriptor
- ssize_t len; // the bytes we have placed into data
- ssize_t size; // the bytes we have allocated for data
+ size_t len; // the bytes we have placed into data
+ size_t size; // the bytes we have allocated for data
pflines *lines;
pfwords *words;
char separators[256];
// open a /proc or /sys file
extern procfile *procfile_open(const char *filename, const char *separators);
+// re-open a file
+// the separators argument is only used if ff == NULL
+extern procfile *procfile_reopen(procfile *ff, const char *filename, const char *separators);
+
// example walk-through a procfile parsed file
extern void procfile_print(procfile *ff);
// ----------------------------------------------------------------------------
+// set this to 1, to have procfile adapt its initial buffer allocation to the max allocation used so far
+extern int procfile_adaptive_initial_allocation;
+
// return the number of lines present
#define procfile_lines(ff) (ff->lines->len)