コード例 #1
0
ファイル: fblk.c プロジェクト: CoryXie/nix-os
/* for dfblk only */
static Memblk*
getmelted(uint isdir, uint type, daddrt *addrp, int *chg)
{
	Memblk *b, *nb;

	*chg = 0;
	if(*addrp == 0){
		b = dballoc(type);
		*addrp = b->addr;
		*chg = 1;
		return b;
	}

	b = dbget(type, *addrp);
	nb = nil;
	if(!b->frozen)
		return b;
	if(catcherror()){
		mbput(b);
		mbput(nb);
		error(nil);
	}
	nb = dbdup(b);
	assert(type == b->type);
	if(isdir && type == DBdata)
		dupdentries(nb->d.data, Dblkdatasz/Daddrsz);
	USED(&nb);		/* for error() */
	*addrp = nb->addr;
	*chg = 1;
	dbput(b, b->type, b->addr);
	noerror();
	mbput(b);
	return nb;
}
コード例 #2
0
ファイル: fblk.c プロジェクト: CoryXie/nix-os
/*
 * Drop one disk reference for f and reclaim its storage if it's gone.
 * The given memory reference is not released.
 * For directories, all files contained have their disk references adjusted,
 * and they are also reclaimed if no further references exist.
 *
 * NB: Time ago, directories were not in compact form (they had holes
 * due to removals) and this had a bug while reclaiming that could lead
 * to double frees of disk blocks.
 * The bug was fixed, but since then, directories have changed again to
 * have holes. If the a double free happens again, this is the place where
 * to look, besides dbdup and dfchdentry.
 */
int
dfput(Memblk *f)
{
	int i;
	Memblk *b;
	long tot;

	isfile(f);
	dKprint("dfput %H\n", f);
	/*
	 * Remove children if it's the last disk ref before we drop data blocks.
	 * No new disk refs may be added, so there's no race here.
	 */
	tot = 0;
	if(dbgetref(f->addr) == 1 && (f->d.mode&DMDIR) != 0){
		rwlock(f, Wr);
		if(catcherror()){
			rwunlock(f, Wr);
			error(nil);
		}
		for(i = 0; i < f->d.ndents; i++){
			b = dfchild(f, i);
			if(!catcherror()){
				tot += dfput(b);
				noerror();
			}
			mbput(b);
		}
		noerror();
		rwunlock(f, Wr);
	}

	if(dbput(f, f->type, f->addr) == 0)
		tot++;
	return tot;
}
コード例 #3
0
ファイル: fblk.c プロジェクト: CoryXie/nix-os
/*
 * Caller walked down p, and now requires the nth element to be
 * melted, and wlocked for writing. (nth count starts at 1);
 * 
 * Return the path with the version of f that we must use,
 * locked for writing and melted.
 * References kept in the path are traded for the ones returned.
 */
Path*
dfmelt(Path **pp, int nth)
{
	int i;
	Memblk *f, **fp, *nf;
	Path *p;

	ownpath(pp);
	p = *pp;
	assert(nth >= 1 && p->nf >= nth && p->nf >= 2);
	assert(p->f[0] == fs->root);
	fp = &p->f[nth-1];

	/*
	 * 1. Optimistic: Try to get a loaded melted version for f.
	 */
	followmelted(fp, Wr);
	f = *fp;
	if(!f->frozen)
		return p;
	ainc(&fs->nmelts);
	rwunlock(f, Wr);

	/*
	 * 2. Realistic:
	 * walk down the path, melting every frozen thing until we
	 * reach f. Keep wlocks so melted files are not frozen while we walk.
	 * /active is special, because it's only frozen temporarily while
	 * creating a frozen version of the tree. Instead of melting it,
	 * we should just wait for it.
	 * p[0] is /
	 * p[1] is /active
	 */
	for(;;){
		followmelted(&p->f[1], Wr);
		if(p->f[1]->frozen == 0)
			break;
		rwunlock(p->f[1], Wr);
		yield();
	}
	/*
	 * At loop header, parent is p->f[i-1], melted and wlocked.
	 * At the end of the loop, p->f[i] is melted and wlocked.
	 */
	for(i = 2; i < nth; i++){
		followmelted(&p->f[i], Wr);
		if(!p->f[i]->frozen){
			rwunlock(p->f[i-1], Wr);
			continue;
		}
		if(catcherror()){
			rwunlock(p->f[i-1], Wr);
			rwunlock(p->f[i], Wr);
			error(nil);
		}

		nf = dbdup(p->f[i]);
		rwlock(nf, Wr);

		if(catcherror()){
			rwunlock(nf, Wr);
			mbput(nf);
			error(nil);
		}
		dfchdentry(p->f[i-1], p->f[i]->addr, nf->addr, Mkit);
		noerror();
		noerror();
		/* committed */
		rwunlock(p->f[i-1], Wr);		/* parent */
		rwunlock(p->f[i], Wr);		/* old frozen version */
		f = p->f[i];
		p->f[i] = nf;
		assert(f->ref > 1);
		mbput(f);			/* ref from path */
		if(!catcherror()){
			dbput(f, f->type, f->addr); /* p->f[i] ref from disk */
			noerror();
		}
	}
	return p;
}
コード例 #4
0
ファイル: dbt2orb.c プロジェクト: battistuz/antelope_contrib
int main(int argc, char **argv)
 { Pf 		*pf;
   char		*orbname,
		*dbname,
		*expr,
		*table,
		*rowtemp,
                verbose;
   int  	orb,
		totalrecords,
		records,
 		record;
   Dbptr  	db,
		dbinput,
		dbscratch;

  elog_init(argc,argv);		

  /* initialize variables */

  verbose = 0;
  expr = NULL;
  loop = 0;
  record = 0;
  totalrecords = 0;

  rowtemp = malloc(ROW_MAX_LENGTH);
  
  if (rowtemp == NULL) die(1,"malloc() error.\n");

  /* read in command line options */

  { int c;
    unsigned char errflg = 0;

    while (( c = getopt( argc, argv, "vl:s:")) != -1)
        switch (c) {
          case 'l': loop = atoi(optarg);
                    sigset(SIGINT,done);
                    break;
          case 's': expr = optarg;
                    break;
          case 'v': verbose = 1;
                    break;
          case '?': errflg++;
        }

    if ( (argc - optind) != 3 ) errflg++;

    if (errflg) 
       { elog_die(0,"usage: %s [-v] [-s subset] [-l delay] db table orb\n",argv[0]); 
       }
    
    dbname = argv[optind++];
    table  = argv[optind++];
    orbname= argv[optind++];
  }
    
  /* start our work */

  if ( dbopen ( dbname,  "r+",  &dbinput ) == dbINVALID )
     { elog_die(1,"Couldn't open input database, \"%s\".\n",dbname); }

  dbinput   = dblookup( dbinput, 0, table, 0, 0);
  dbscratch = dblookup( dbinput, 0, 0, 0, "dbSCRATCH");

  if ( dbinput.table == dbINVALID )
   { elog_die(1,"Couldn't lookup the table \"%s\" in the database \"%s\".\n",
		table,dbname); }
  if ( dbscratch.record == dbINVALID )
   { elog_die(1,"Couldn't lookup the scratch record in the database \"%s\".\n",
		dbname); }
  
  if ( dbquery( dbinput, dbRECORD_COUNT, &records) < 0 )
   { elog_die(1,"dbquery dbRECORD_COUNT failed.\n"); }

  orb      = orbopen( orbname, "w&" );

  if ( orb == -1 )
   { elog_die(1,"Couldn't open the orb, \"%s\".\n",orbname); }

  if (loop == 0) loop = -1;

  while (loop)
   { db = dbinput;
     
     if ( expr != NULL) db = dbsubset( db, expr, 0 );
     
     db.record = record;

     if ( dbquery( db, dbRECORD_COUNT, &records) < 0 )
   	 elog_die(1,"dbquery dbRECORD_COUNT failed.\n");  
     
     for (;db.record<records;db.record++)
       { if (verbose) printf("writing record %d to orb...\n",db.record); 

         /* copy the row from what could be a view into the scratch record of the
            input database, so as to avoid putting a view on the ORB */
         if ( dbget( db,        rowtemp) == dbINVALID ) die(1,"dbget error.\n");
         if ( dbput( dbscratch, rowtemp) == dbINVALID ) die(1,"dbput error.\n");

         if ( db2orbpkt( dbscratch, orb ) < 0 )
            { complain ( 0, "Couldn't write record #%d to %s.\n",
              	   db.record, orbname); } 
         totalrecords++;
       }

     record = db.record; 

     /* if a subset expression was supplied, then we're working with
        a view, which should be freed. */

     if ( expr != NULL) dbfree(db);
     if ( loop == -1 ) loop = 0;
     sleep(loop);
   } 

  printf("posted %d records from database %s to orb %s.\n",totalrecords,dbname,orbname);
  dbclose(dbinput);
  orbclose(orb); 
  free(rowtemp);
 }