Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dir_stat() #6

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Prev Previous commit
Next Next commit
use readdir()
wlandau committed Dec 19, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 45319a192306464a7d9b8a12adcbf18c95740b9c
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Generated by roxygen2: do not edit by hand

export(dir_stat)
export(log_active)
export(log_phase_get)
export(log_phase_reset)
38 changes: 38 additions & 0 deletions man/dir_stat.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions man/log_active.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions man/log_phase_get.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions man/log_phase_reset.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions man/log_phase_set.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions man/log_plot.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions man/log_print.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions man/log_read.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions man/log_start.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions man/log_stop.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions man/log_support.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions src/error.h → src/constant.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef ERROR_H
#define ERROR_H
#ifndef CONSTANT_H
#define CONSTANT_H

#define BUFFER_SIZE 2048
#define ERROR_ARITHMETIC 10000
#define ERROR_BUFFER 10001
#define ERROR_FILE 10002
4 changes: 2 additions & 2 deletions src/log.c
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ SEXP log_active(void) {
}

SEXP log_phase_get(void) {
char phase[PHASE_N];
char phase[BUFFER_SIZE];
pthread_phase_get(phase);
SEXP out = PROTECT(mkString(phase));
UNPROTECT(1);
@@ -41,7 +41,7 @@ SEXP log_print(
const int* pids_ = INTEGER(pids);
const int n_pids_ = INTEGER(n_pids)[0];
const char** names_ = (const char**) malloc(n_pids_ * sizeof(char*));
char phase[PHASE_N];
char phase[BUFFER_SIZE];
if (names_ == NULL) {
return R_NilValue;
}
2 changes: 1 addition & 1 deletion src/metrics.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef METRICS_H
#define METRICS_H

#include "error.h"
#include "constant.h"
#include "timers.h"
#include <stdio.h>
#include <stdlib.h>
120 changes: 51 additions & 69 deletions src/stat.c
Original file line number Diff line number Diff line change
@@ -1,90 +1,72 @@
#include "stat.h"

#if SUPPORT_NFTW

int nftw_entry(
const char *fpath,
const struct stat *sb,
int typeflag,
struct FTW *ftwbuf
) {
R_CheckUserInterrupt();
if (typeflag == FTW_F) {
if (state.count == state.capacity) {
state.capacity *= 2;
REPROTECT(
state.path = Rf_xlengthgets(state.path, state.capacity),
state.index_path
);
REPROTECT(
state.size = Rf_xlengthgets(state.size, state.capacity),
state.index_size
);
REPROTECT(
state.mtime = Rf_xlengthgets(state.mtime, state.capacity),
state.index_mtime
);
}
SET_STRING_ELT(state.path, state.count, mkChar(fpath));
REAL(state.size)[state.count] = (double) sb->st_size;
REAL(state.mtime)[state.count] = (double) sb->st_mtime;
state.count++;
}
return 0;
}
#if SUPPORT_READDIR

SEXP dir_stat(SEXP path) {
state.count = 0;
state.capacity = 2048;
PROTECT_WITH_INDEX(
state.path = allocVector(STRSXP, state.capacity),
&state.index_path
);
PROTECT_WITH_INDEX(
state.size = allocVector(REALSXP, state.capacity),
&state.index_size
);
PROTECT_WITH_INDEX(
state.mtime = allocVector(REALSXP, state.capacity),
&state.index_mtime
);
if (nftw(CHAR(STRING_ELT(path, 0)), nftw_entry, 20, FTW_PHYS) == -1) {
Rf_error("nftw() failed: %s", strerror(errno));
const char* parent = CHAR(STRING_ELT(path, 0));
DIR* handle = opendir(parent);
if (handle == NULL) {
Rf_error("opendir() failed on %s: %s", parent, strerror(errno));
}
REPROTECT(
state.path = Rf_xlengthgets(state.path, state.count),
state.index_path
);
REPROTECT(
state.size = Rf_xlengthgets(state.size, state.count),
state.index_size
);
REPROTECT(
state.mtime = Rf_xlengthgets(state.mtime, state.count),
state.index_mtime
);
int capacity = BUFFER_SIZE;
int count = 0;
int stat_result;
SEXP file;
SEXP size;
SEXP mtime;
PROTECT_INDEX index_path;
PROTECT_INDEX index_size;
PROTECT_INDEX index_mtime;
PROTECT_WITH_INDEX(file = allocVector(STRSXP, capacity), &index_path);
PROTECT_WITH_INDEX(size = allocVector(REALSXP, capacity), &index_size);
PROTECT_WITH_INDEX(mtime = allocVector(REALSXP, capacity), &index_mtime);
struct dirent *entry;
struct stat stat_info;
char buffer[BUFFER_SIZE];
while ((entry = readdir(handle)) != NULL) {
R_CheckUserInterrupt();
snprintf(buffer, BUFFER_SIZE, "%s/%s", parent, entry->d_name);
if (entry->d_type == DT_REG) {
stat_result = stat(buffer, &stat_info);
} else if (entry->d_type == DT_LNK) {
stat_result = lstat(buffer, &stat_info);
} else {
continue;
}
if (stat_result == -1) {
continue;
}
SET_STRING_ELT(file, count, mkChar(buffer));
REAL(size)[count] = (double) stat_info.st_size;
REAL(mtime)[count] = (double) stat_info.st_mtime;
++count;
if (count == capacity) {
capacity *= 2;
REPROTECT(file = Rf_xlengthgets(file, capacity), index_path);
REPROTECT(size = Rf_xlengthgets(size, capacity), index_size);
REPROTECT(mtime = Rf_xlengthgets(mtime, capacity), index_mtime);
}
}
closedir(handle);
REPROTECT(file = Rf_xlengthgets(file, count), index_path);
REPROTECT(size = Rf_xlengthgets(size, count), index_size);
REPROTECT(mtime = Rf_xlengthgets(mtime, count), index_mtime);
SEXP result = PROTECT(allocVector(VECSXP, 3));
SEXP names = PROTECT(allocVector(STRSXP, 3));
SET_STRING_ELT(names, 0, mkChar("path"));
SET_STRING_ELT(names, 1, mkChar("size"));
SET_STRING_ELT(names, 2, mkChar("mtime"));
SET_VECTOR_ELT(result, 0, state.path);
SET_VECTOR_ELT(result, 1, state.size);
SET_VECTOR_ELT(result, 2, state.mtime);
SET_VECTOR_ELT(result, 0, file);
SET_VECTOR_ELT(result, 1, size);
SET_VECTOR_ELT(result, 2, mtime);
setAttrib(result, R_NamesSymbol, names);
state.path = R_NilValue;
state.size = R_NilValue;
state.mtime = R_NilValue;
UNPROTECT(5);
return result;
}

#else

#include <stdio.h>

SEXP dir_stat(SEXP path) {
Rprintf("unsupported: %ld\n", _POSIX_VERSION);
return R_NilValue;
}

18 changes: 4 additions & 14 deletions src/stat.h
Original file line number Diff line number Diff line change
@@ -4,25 +4,15 @@
#include <R.h>
#include <Rinternals.h>
#include "support.h"
#include <unistd.h>

#if SUPPORT_NFTW
#if SUPPORT_READDIR
#include "constant.h"
#include <dirent.h>
#include <errno.h>
#include <ftw.h>
#include <sys/stat.h>
#include <string.h>
#endif

typedef struct {
PROTECT_INDEX index_path;
PROTECT_INDEX index_size;
PROTECT_INDEX index_mtime;
SEXP path;
SEXP size;
SEXP mtime;
int count;
int capacity;
} nftw_state_t;

SEXP dir_stat(SEXP path);

#endif
Loading