Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "stdinc.h"
#include <bio.h>
#include "dat.h"
#include "fns.h"
#include "error.h"

int num = 100;
int length = 20*1024;
int block= 1024;
int bush = 4;
int iter = 100;
Biobuf *bout;
int maxdepth;

Source *mkroot(Cache*);
void new(Source*, int trace, int);
int delete(Source*);
int count(Source *s, int);
void stats(Source *s);
void dump(Source *s, int ident, ulong entry);
static void bench(Source *r);

void
main(int argc, char *argv[])
{
        int i;
        Fs *fs;
        int csize = 1000;
        ulong t;
        Source *r;

        ARGBEGIN{
        case 'i':
                iter = atoi(ARGF());
                break;
        case 'n':
                num = atoi(ARGF());
                break;
        case 'l':
                length = atoi(ARGF());
                break;
        case 'b':       
                block = atoi(ARGF());
                break;
        case 'u':
                bush = atoi(ARGF());
                break;
        case 'c':
                csize = atoi(ARGF());
                break;
        }ARGEND;

        vtAttach();

        bout = vtMemAllocZ(sizeof(Biobuf));
        Binit(bout, 1, OWRITE);

        fmtinstall('V', vtScoreFmt);
        fmtinstall('R', vtErrFmt);

        fs = fsOpen(argv[0], nil, csize, OReadWrite);
        if(fs == nil)
                sysfatal("could not open fs: %r");

        t = time(0);

        srand(0);

        r = fs->source;
        dump(r, 0, 0);

        fprint(2, "count = %d\n", count(r, 1));
        for(i=0; i<num; i++)
                new(r, 0, 0);

        for(i=0; i<iter; i++){
                if(i % 10000 == 0)
                        stats(r);
                new(r, 0, 0);
                delete(r);
        }

//      dump(r, 0, 0);

        fprint(2, "count = %d\n", count(r, 1));
//      cacheCheck(c);

        fprint(2, "deleting\n");
        for(i=0; i<num; i++)
                delete(r);
//      dump(r, 0, 0);

        fprint(2, "count = %d\n", count(r, 1));
        fprint(2, "total time = %ld\n", time(0)-t);
        
        fsClose(fs);
        vtDetach();
        exits(0);
}

static void
bench(Source *r)
{
        vlong t;
        Entry e;
        int i;

        t = nsec();

        for(i=0; i<1000000; i++)
                sourceGetEntry(r, &e);

        fprint(2, "%f\n", 1e-9*(nsec() - t));
}

void
new(Source *s, int trace, int depth)
{
        int i, n;
        Source *ss;
        Entry e;
        
        if(depth > maxdepth)
                maxdepth = depth;

        Bflush(bout);

        n = sourceGetDirSize(s);
        for(i=0; i<n; i++){
                ss = sourceOpen(s, nrand(n), OReadWrite);
                if(ss == nil || !sourceGetEntry(ss, &e))
                        continue;
                if((e.flags & VtEntryDir) && frand() < 1./bush){
                        if(trace){
                                int j;
                                for(j=0; j<trace; j++)
                                        Bprint(bout, " ");
                                Bprint(bout, "decend %d\n", i);
                        }
                        new(ss, trace?trace+1:0, depth+1);
                        sourceClose(ss);
                        return;
                }
                sourceClose(ss);
        }
        ss = sourceCreate(s, s->dsize, 1+frand()>.5, 0);
        if(ss == nil){
                Bprint(bout, "could not create directory: %R\n");
                return;
        }
        if(trace){
                int j;
                for(j=1; j<trace; j++)
                        Bprint(bout, " ");
                Bprint(bout, "create %d\n", ss->offset);
        }
        sourceClose(ss);
}

int
delete(Source *s)
{
        int i, n;
        Source *ss;

        n = sourceGetDirSize(s);
        /* check if empty */
        for(i=0; i<n; i++){
                ss = sourceOpen(s, i, OReadWrite);
                if(ss != nil){
                        sourceClose(ss);
                        break;
                }
        }
        if(i == n)
                return 0;
                
        for(;;){
                ss = sourceOpen(s, nrand(n), OReadWrite);
                if(ss == nil)
                        continue;
                if(s->dir && delete(ss)){
                        sourceClose(ss);
                        return 1;
                }
                if(1)
                        break;
                sourceClose(ss);
        }


        sourceRemove(ss);
        return 1;
}

void
dump(Source *s, int ident, ulong entry)
{
        ulong i, n;
        Source *ss;
        Entry e;

        for(i=0; i<ident; i++)
                Bprint(bout, " ");

        if(!sourceGetEntry(s, &e)){
                fprint(2, "sourceGetEntry failed: %r\n");
                return;
        }

        Bprint(bout, "%4lud: gen %4ud depth %d tag=%x score=%V",
                entry, e.gen, e.depth, e.tag, e.score);
        if(!s->dir){
                Bprint(bout, " data size: %llud\n", e.size);
                return;
        }
        n = sourceGetDirSize(s);
        Bprint(bout, " dir size: %lud\n", n);
        for(i=0; i<n; i++){
                ss = sourceOpen(s, i, 1);
                if(ss == nil)
                        continue;
                dump(ss, ident+1, i);
                sourceClose(ss);
        }
        return;
}

int
count(Source *s, int rec)
{
        ulong i, n;
        int c;
        Source *ss;

        n = sourceGetDirSize(s);
        c = 0;
        for(i=0; i<n; i++){
                ss = sourceOpen(s, i, OReadOnly);
                if(ss == nil)
                        continue;
                if(rec)
                        c += count(ss, rec);
                c++;
                sourceClose(ss);
        }
        return c;
}

void
stats(Source *s)
{
        int n, i, c, cc, max;
        Source *ss;

        cc = 0;
        max = 0;
        n = sourceGetDirSize(s);
        for(i=0; i<n; i++){
                ss = sourceOpen(s, i, 1);
                if(ss == nil)
                        continue;
                cc++;
                c = count(ss, 1);
                if(c > max)
                        max = c;
                sourceClose(ss);
        }
fprint(2, "count = %d top = %d depth=%d maxcount %d\n", cc, n, maxdepth, max);
}