Re: [PATCH 5/6] syslets: add generic syslets infrastructure

From: Rusty Russell
Date: Wed Jan 09 2008 - 20:18:38 EST


On Thursday 10 January 2008 09:58:10 Linus Torvalds wrote:
> On Thu, 10 Jan 2008, Rusty Russell wrote:
> > I'd have to read his original statement, but eventfd doesn't build up
> > state, so I think it qualifies.
>
> How about you guys battle it out by giving an example program usign the
> interface?

Nice idea.

> And *simplicity* of the end result really does matter. If it's not simple
> to use, people won't use it.

Completely agreed, but async is always more complex than sync.

eg. your malloc()-and-overwrite trick here assumes it's serial, similarly
stack vars. Even before anything's happened we've massively increased the
number of mallocs :( Maybe someone else can see a neater way?

Below is an async-ready version (I've assumed you still want each dir grouped
together). It's already slower (best 0m3.842s vs best 0m3.659s):

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

static void find(const char *base, int baselen);

struct result
{
struct result *next;
struct stat st;
unsigned int namelen;
char name[];
};

static struct result *new_result(const char *base, int baselen,
const char *sub, int sublen)
{
struct result *r;

r = malloc(sizeof(*r) + baselen + sublen + 2);
memcpy(r->name, base, baselen);
r->name[baselen] = '/';
memcpy(r->name + baselen + 1, sub, sublen+1);
r->namelen = baselen + sublen + 1;

return r;
}

static void process(struct result *r, struct result **dirs)
{
printf("%8lu %s\n", r->st.st_size, r->name);
if (S_ISDIR(r->st.st_mode)) {
r->next = *dirs;
*dirs = r;
} else
free(r);
}

/* -1 = fail, 0 = success, 1 = in progress. */
static int handle_async(struct result *r)
{
/* Ours is sync. */
return lstat(r->name, &r->st);
}

static void process_pending(struct result *pending, struct result **dirs)
{
/* Since we're sync, pending will be NULL. Otherwise call
pending as they complete. */
}

static void find(const char *base, int baselen)
{
DIR *dir;
struct result *r, *pending = NULL, *dirs = NULL;

dir = opendir(base);
if (dir) {
struct dirent *de;
while ((de = readdir(dir)) != NULL) {
const char *p = de->d_name;
int len = strlen(p);
if (p[0] == '.') {
if (len == 1)
continue;
if (len == 2 && p[1] == '.')
continue;
}
r = new_result(base, baselen, p, len);
switch (handle_async(r)) {
case 0:
process(r, &dirs);
break;
case -1:
free(r);
break;
case 1:
r->next = pending;
pending = r;
}
}
closedir(dir);
process_pending(pending, &dirs);
while (dirs) {
find(dirs->name, dirs->namelen);
r = dirs;
dirs = dirs->next;
free(r);
}
}
}

int main(int argc, char **argv)
{
find(".",1);
return 0;
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/