clang-format
This commit is contained in:
@@ -44,40 +44,37 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NTRIES 100 /* loop count */
|
||||
#define NPROCS 5 /* actually totals 4x this +1 processes */
|
||||
#define NTRIES 100 /* loop count */
|
||||
#define NPROCS 5 /* actually totals 4x this +1 processes */
|
||||
|
||||
#define TESTDIR "dirconc"
|
||||
#define NNAMES 4
|
||||
#define NAMESIZE 32
|
||||
#define TESTDIR "dirconc"
|
||||
#define NNAMES 4
|
||||
#define NAMESIZE 32
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
static const char *const names[NNAMES] = {
|
||||
"aaaa",
|
||||
"bbbb",
|
||||
"cccc",
|
||||
"dddd",
|
||||
"aaaa",
|
||||
"bbbb",
|
||||
"cccc",
|
||||
"dddd",
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
choose_name(char *buf, size_t len)
|
||||
{
|
||||
const char *a, *b, *c;
|
||||
static void choose_name(char *buf, size_t len) {
|
||||
const char *a, *b, *c;
|
||||
|
||||
a = names[random()%NNAMES];
|
||||
if (random()%2==0) {
|
||||
snprintf(buf, len, "%s", a);
|
||||
return;
|
||||
}
|
||||
b = names[random()%NNAMES];
|
||||
if (random()%2==0) {
|
||||
snprintf(buf, len, "%s/%s", a, b);
|
||||
return;
|
||||
}
|
||||
c = names[random()%NNAMES];
|
||||
snprintf(buf, len, "%s/%s/%s", a, b, c);
|
||||
a = names[random() % NNAMES];
|
||||
if (random() % 2 == 0) {
|
||||
snprintf(buf, len, "%s", a);
|
||||
return;
|
||||
}
|
||||
b = names[random() % NNAMES];
|
||||
if (random() % 2 == 0) {
|
||||
snprintf(buf, len, "%s/%s", a, b);
|
||||
return;
|
||||
}
|
||||
c = names[random() % NNAMES];
|
||||
snprintf(buf, len, "%s/%s/%s", a, b, c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@@ -86,277 +83,224 @@ choose_name(char *buf, size_t len)
|
||||
* The purpose of this is to be atomic. In our world, straight
|
||||
* printf tends not to be.
|
||||
*/
|
||||
static
|
||||
void
|
||||
static void
|
||||
#ifdef __GNUC__
|
||||
__attribute__((__format__(__printf__, 1, 2)))
|
||||
__attribute__((__format__(__printf__, 1, 2)))
|
||||
#endif
|
||||
say(const char *fmt, ...)
|
||||
{
|
||||
char buf[512];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
write(STDOUT_FILENO, buf, strlen(buf));
|
||||
say(const char *fmt, ...) {
|
||||
char buf[512];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
write(STDOUT_FILENO, buf, strlen(buf));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
static
|
||||
void
|
||||
dorename(const char *name1, const char *name2)
|
||||
{
|
||||
if (rename(name1, name2) < 0) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
case ENOTEMPTY:
|
||||
case EINVAL:
|
||||
break;
|
||||
default:
|
||||
say("pid %d: rename %s -> %s: %s\n",
|
||||
getpid(), name1, name2, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void dorename(const char *name1, const char *name2) {
|
||||
if (rename(name1, name2) < 0) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
case ENOTEMPTY:
|
||||
case EINVAL:
|
||||
break;
|
||||
default:
|
||||
say("pid %d: rename %s -> %s: %s\n", getpid(), name1, name2,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
domkdir(const char *name)
|
||||
{
|
||||
if (mkdir(name, 0775)<0) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
case EEXIST:
|
||||
break;
|
||||
default:
|
||||
say("pid %d: mkdir %s: %s\n",
|
||||
getpid(), name, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void domkdir(const char *name) {
|
||||
if (mkdir(name, 0775) < 0) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
case EEXIST:
|
||||
break;
|
||||
default:
|
||||
say("pid %d: mkdir %s: %s\n", getpid(), name, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
dormdir(const char *name)
|
||||
{
|
||||
if (rmdir(name)<0) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
case ENOTEMPTY:
|
||||
break;
|
||||
default:
|
||||
say("pid %d: rmdir %s: %s\n",
|
||||
getpid(), name, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void dormdir(const char *name) {
|
||||
if (rmdir(name) < 0) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
case ENOTEMPTY:
|
||||
break;
|
||||
default:
|
||||
say("pid %d: rmdir %s: %s\n", getpid(), name, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
cleanup_rmdir(const char *name)
|
||||
{
|
||||
if (rmdir(name)<0) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
break;
|
||||
default:
|
||||
say("cleanup (pid %d): rmdir %s: %s\n",
|
||||
getpid(), name, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void cleanup_rmdir(const char *name) {
|
||||
if (rmdir(name) < 0) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
break;
|
||||
default:
|
||||
say("cleanup (pid %d): rmdir %s: %s\n", getpid(), name, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
static
|
||||
void
|
||||
rename_proc(void)
|
||||
{
|
||||
char name1[NAMESIZE], name2[NAMESIZE];
|
||||
int ct;
|
||||
static void rename_proc(void) {
|
||||
char name1[NAMESIZE], name2[NAMESIZE];
|
||||
int ct;
|
||||
|
||||
for (ct=0; ct<NTRIES; ct++) {
|
||||
choose_name(name1, sizeof(name1));
|
||||
choose_name(name2, sizeof(name2));
|
||||
say("pid %2d: rename %s -> %s\n", (int)getpid(), name1, name2);
|
||||
dorename(name1, name2);
|
||||
}
|
||||
for (ct = 0; ct < NTRIES; ct++) {
|
||||
choose_name(name1, sizeof(name1));
|
||||
choose_name(name2, sizeof(name2));
|
||||
say("pid %2d: rename %s -> %s\n", (int)getpid(), name1, name2);
|
||||
dorename(name1, name2);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
mkdir_proc(void)
|
||||
{
|
||||
char name[NAMESIZE];
|
||||
int ct;
|
||||
static void mkdir_proc(void) {
|
||||
char name[NAMESIZE];
|
||||
int ct;
|
||||
|
||||
for (ct=0; ct<NTRIES; ct++) {
|
||||
choose_name(name, sizeof(name));
|
||||
say("pid %2d: mkdir %s\n", (int)getpid(), name);
|
||||
domkdir(name);
|
||||
}
|
||||
for (ct = 0; ct < NTRIES; ct++) {
|
||||
choose_name(name, sizeof(name));
|
||||
say("pid %2d: mkdir %s\n", (int)getpid(), name);
|
||||
domkdir(name);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
rmdir_proc(void)
|
||||
{
|
||||
char name[NAMESIZE];
|
||||
int ct;
|
||||
static void rmdir_proc(void) {
|
||||
char name[NAMESIZE];
|
||||
int ct;
|
||||
|
||||
for (ct=0; ct<NTRIES; ct++) {
|
||||
choose_name(name, sizeof(name));
|
||||
say("pid %2d: rmdir %s\n", (int)getpid(), name);
|
||||
dormdir(name);
|
||||
}
|
||||
for (ct = 0; ct < NTRIES; ct++) {
|
||||
choose_name(name, sizeof(name));
|
||||
say("pid %2d: rmdir %s\n", (int)getpid(), name);
|
||||
dormdir(name);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
static
|
||||
pid_t
|
||||
dofork(void (*func)(void))
|
||||
{
|
||||
pid_t pid;
|
||||
static pid_t dofork(void (*func)(void)) {
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
say("fork: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
func();
|
||||
exit(0);
|
||||
}
|
||||
return pid;
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
say("fork: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
func();
|
||||
exit(0);
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
run(void)
|
||||
{
|
||||
pid_t pids[NPROCS*4], wp;
|
||||
int i, status;
|
||||
static void run(void) {
|
||||
pid_t pids[NPROCS * 4], wp;
|
||||
int i, status;
|
||||
|
||||
for (i=0; i<NPROCS; i++) {
|
||||
pids[i*4] = dofork(mkdir_proc);
|
||||
pids[i*4+1] = dofork(mkdir_proc);
|
||||
pids[i*4+2] = dofork(rename_proc);
|
||||
pids[i*4+3] = dofork(rmdir_proc);
|
||||
}
|
||||
for (i = 0; i < NPROCS; i++) {
|
||||
pids[i * 4] = dofork(mkdir_proc);
|
||||
pids[i * 4 + 1] = dofork(mkdir_proc);
|
||||
pids[i * 4 + 2] = dofork(rename_proc);
|
||||
pids[i * 4 + 3] = dofork(rmdir_proc);
|
||||
}
|
||||
|
||||
for (i=0; i<NPROCS*4; i++) {
|
||||
if (pids[i]>=0) {
|
||||
wp = waitpid(pids[i], &status, 0);
|
||||
if (wp<0) {
|
||||
say("waitpid %d: %s\n", (int) pids[i],
|
||||
strerror(errno));
|
||||
}
|
||||
else if (WIFSIGNALED(status)) {
|
||||
say("pid %d: signal %d\n", (int) pids[i],
|
||||
WTERMSIG(status));
|
||||
}
|
||||
else if (WIFEXITED(status) && WEXITSTATUS(status)!=0) {
|
||||
say("pid %d: exit %d\n", (int) pids[i],
|
||||
WEXITSTATUS(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < NPROCS * 4; i++) {
|
||||
if (pids[i] >= 0) {
|
||||
wp = waitpid(pids[i], &status, 0);
|
||||
if (wp < 0) {
|
||||
say("waitpid %d: %s\n", (int)pids[i], strerror(errno));
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
say("pid %d: signal %d\n", (int)pids[i], WTERMSIG(status));
|
||||
} else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
|
||||
say("pid %d: exit %d\n", (int)pids[i], WEXITSTATUS(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
static
|
||||
void
|
||||
setup(const char *fs)
|
||||
{
|
||||
if (chdir(fs)<0) {
|
||||
say("chdir: %s: %s\n", fs, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (mkdir(TESTDIR, 0775)<0) {
|
||||
say("mkdir: %s: %s\n", TESTDIR, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (chdir(TESTDIR)<0) {
|
||||
say("chdir: %s: %s\n", TESTDIR, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
static void setup(const char *fs) {
|
||||
if (chdir(fs) < 0) {
|
||||
say("chdir: %s: %s\n", fs, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (mkdir(TESTDIR, 0775) < 0) {
|
||||
say("mkdir: %s: %s\n", TESTDIR, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (chdir(TESTDIR) < 0) {
|
||||
say("chdir: %s: %s\n", TESTDIR, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
recursive_cleanup(const char *sofar, int depth)
|
||||
{
|
||||
char buf[NAMESIZE*32];
|
||||
int i;
|
||||
static void recursive_cleanup(const char *sofar, int depth) {
|
||||
char buf[NAMESIZE * 32];
|
||||
int i;
|
||||
|
||||
for (i=0; i<NNAMES; i++) {
|
||||
snprintf(buf, sizeof(buf), "%s/%s", sofar, names[i]);
|
||||
if (rmdir(buf)<0) {
|
||||
if (errno==ENOTEMPTY) {
|
||||
recursive_cleanup(buf, depth+1);
|
||||
cleanup_rmdir(buf);
|
||||
}
|
||||
else if (errno!=ENOENT) {
|
||||
say("cleanup (pid %d): rmdir %s: %s\n",
|
||||
getpid(), buf, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < NNAMES; i++) {
|
||||
snprintf(buf, sizeof(buf), "%s/%s", sofar, names[i]);
|
||||
if (rmdir(buf) < 0) {
|
||||
if (errno == ENOTEMPTY) {
|
||||
recursive_cleanup(buf, depth + 1);
|
||||
cleanup_rmdir(buf);
|
||||
} else if (errno != ENOENT) {
|
||||
say("cleanup (pid %d): rmdir %s: %s\n", getpid(), buf, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
cleanup(void)
|
||||
{
|
||||
recursive_cleanup(".", 0);
|
||||
static void cleanup(void) {
|
||||
recursive_cleanup(".", 0);
|
||||
|
||||
chdir("..");
|
||||
cleanup_rmdir(TESTDIR);
|
||||
chdir("..");
|
||||
cleanup_rmdir(TESTDIR);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *fs;
|
||||
long seed = 0;
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *fs;
|
||||
long seed = 0;
|
||||
|
||||
say("Concurrent directory ops test\n");
|
||||
say("Concurrent directory ops test\n");
|
||||
|
||||
if (argc==0 || argv==NULL) {
|
||||
say("Warning: argc is 0 - assuming you mean to run on lhd1: "
|
||||
"with seed 0\n");
|
||||
fs = "lhd1:";
|
||||
}
|
||||
else if (argc==2) {
|
||||
fs = argv[1];
|
||||
}
|
||||
else if (argc==3) {
|
||||
fs = argv[1];
|
||||
seed = atoi(argv[2]);
|
||||
}
|
||||
else {
|
||||
say("Usage: dirconc filesystem [random-seed]\n");
|
||||
exit(1);
|
||||
}
|
||||
if (argc == 0 || argv == NULL) {
|
||||
say("Warning: argc is 0 - assuming you mean to run on lhd1: "
|
||||
"with seed 0\n");
|
||||
fs = "lhd1:";
|
||||
} else if (argc == 2) {
|
||||
fs = argv[1];
|
||||
} else if (argc == 3) {
|
||||
fs = argv[1];
|
||||
seed = atoi(argv[2]);
|
||||
} else {
|
||||
say("Usage: dirconc filesystem [random-seed]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
srandom(seed);
|
||||
setup(fs);
|
||||
say("Starting in %s/%s\n", fs, TESTDIR);
|
||||
srandom(seed);
|
||||
setup(fs);
|
||||
say("Starting in %s/%s\n", fs, TESTDIR);
|
||||
|
||||
run();
|
||||
run();
|
||||
|
||||
say("Cleaning up\n");
|
||||
cleanup();
|
||||
say("Cleaning up\n");
|
||||
cleanup();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user