⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blk_file.cc

📁 X-tree的C++源码
💻 CC
字号:
/* seq_file.cc :: Implementation einer sequentiellen Filestruktur durch                  gecachede Bloecke.  Tobias Mayr(mayrt) 4/95 	          soll einmal Alternative zu SequentialList sein */#include "blk_file.h"void error(char *t, bool ex);//================================================================//===========================BlockFile============================// Interne Funktionen:void BlockFile::fwrite_number(int value)    // schreibt an SEEK_CUR eine Zahl, siehe fread_number{   put_bytes((char *) &value,sizeof(int));}int BlockFile::fread_number()   // liest von SEEK_CUR eine Zahl, siehe fwrite_number{   char ca[sizeof(int)];   get_bytes(ca,sizeof(int));   return *((int *)ca);}// Zugriffsfunktionen:-------------------------------------------------BlockFile::BlockFile(char* name,int b_length){   char *buffer;   int l;   filename = new char[strlen(name) + 1];   strcpy(filename,name);   blocklength = b_length;	// nur fuer neue Files relevant   number = 0;   if((fp=fopen(name,"rb+"))!=0)	// zum update oeffnen   // bekanntes File   {	      new_flag = FALSE;      blocklength = fread_number();      number = fread_number();	// Gesamtzahl der Bloecke lesen   }   else    // unbekanntes File   {	      if (blocklength < BFHEAD_LENGTH)    	error("BlockFile::BlockFile: Blocks zu kurz",TRUE);      fp=fopen(filename,"wb+");      if (fp == 0) 	  error("BlockFile::new_file: Schreibfehler",TRUE);      new_flag = TRUE;      fwrite_number(blocklength);      // Gesamtzahl Bloecke ist 0      fwrite_number(0);		  buffer = new char[(l=blocklength-(int)ftell(fp))];      memset(buffer, 0, sizeof(buffer));      put_bytes(buffer,l);      delete [] buffer;   }   fseek(fp,0,SEEK_SET);	// auf Anfang (Header) gehen   act_block=0;			// aktueller Block ist der Header}      BlockFile::~BlockFile(){   delete[] filename;   fclose(fp);}void BlockFile::read_header(char* buffer){   fseek(fp,BFHEAD_LENGTH,SEEK_SET);   get_bytes(buffer,blocklength-BFHEAD_LENGTH);   if(number<1)    {        fseek(fp,0,SEEK_SET);       act_block=0;    }   else        act_block=1;}void BlockFile::set_header(char* header){   fseek(fp,BFHEAD_LENGTH,SEEK_SET);   put_bytes(header,blocklength-BFHEAD_LENGTH);   if(number<1)    {        fseek(fp,0,SEEK_SET);       act_block=0;    }   else        act_block=1;}bool BlockFile::read_block(Block b,int pos)// pos bezieht sich auf externe Nummerierung beginnend bei 0 NACH dem Header{   // Externe Num. --> interne Num.   pos++;	   if (pos<=number && pos>0)        seek_block(pos);   else        return FALSE;   get_bytes(b,blocklength);   if (pos+1>number)    {        fseek(fp,0,SEEK_SET);       act_block=0;    }   else        act_block=pos+1;   return TRUE;}bool BlockFile::write_block(const Block block,int pos)// pos bezieht sich auf externe Nummerierung beginnend bei 0 NACH dem Header   {   // Externe Num. --> interne Num.   pos++;      if (pos<=number && pos>0)        seek_block(pos);   else        return FALSE;   put_bytes(block,blocklength);   if (pos+1>number)    {        fseek(fp,0,SEEK_SET);       act_block=0;    }   else        act_block=pos+1;   return TRUE;}int BlockFile::append_block(const Block block)// Das Resulat bezieht sich auf externe Nummerierung{   fseek(fp,0,SEEK_END);   put_bytes(block,blocklength);    number++;   fseek(fp,sizeof(int),SEEK_SET);   fwrite_number(number);   fseek(fp,-blocklength,SEEK_END);   // -1 zur Umrechnung in externe Num.   return (act_block=number)-1;	}bool BlockFile::delete_last_blocks(int num){   if (num>number)       return FALSE;#ifdef UNIX   if (truncate(filename,(number-num+1)*blocklength) != 0)	  error("BlockFile::delete_last_blocks : truncate-Fehler",TRUE);#endif   number -= num;   fseek(fp,sizeof(int),SEEK_SET);   fwrite_number(number);   fseek(fp,0,SEEK_SET);   act_block=0;   return TRUE;}//================================================================//========================CachedBlockFile=========================// Interne Funktionen:--------------------------------------------int CachedBlockFile::next()// liefert freien Platz im Cache oder -1// ptr rotiert ueber den vollen Cache, um diesen gleichmaessig// 'auszulasten'{   int ret_val, tmp;   if (cachesize==0)        return -1;   else       if (fuf_cont[ptr]==free)        {	   ret_val = ptr++;	   if(ptr==cachesize)		   ptr=0;	   return ret_val;	   }	   else	   {		 tmp = ptr+1;	 if (tmp==cachesize)		 tmp=0;		 // suche freie Pos.		 while (tmp!=ptr && fuf_cont[tmp]!=free)		 if(++tmp==cachesize)		 //tmp rotiert ueber der Liste		 tmp=0;		 if (ptr==tmp)	// kein Platz frei ?		 {		// naechste unfixed Pos. wird freigemacht		 if(fuf_cont[ptr]==fixed)		 {		 tmp=ptr+1;		 if (tmp==cachesize)			 tmp=0;		 // suche unfixed Pos.		 while(tmp!=ptr && fuf_cont[tmp]!=used)			 if(++tmp==cachesize)			 //tmp rotiert ueber der Liste			 tmp=0;		 if (ptr==tmp)		 // alles fix			 return -1;		 else				 // tmp zeigt auf used			 ptr=tmp;		 }		 BlockFile::write_block(cache[ptr],cache_cont[ptr]-1);		 fuf_cont[ptr]=free;		 ret_val=ptr++;		 if (ptr==cachesize)		 ptr=0;		 return ret_val;	 }	 else		 return tmp;	  }}int CachedBlockFile::in_cache(int index)// liefert Pos. eines Blocks im Cache, sonst -1{   int i;   for (i = 0; i<cachesize; i++)	   if (cache_cont[i] == index && fuf_cont[i] != free)		   return i;   return -1;}// Zugriffsfunktionen:-------------------------------------------------CachedBlockFile::CachedBlockFile(char* name,int blength, int csize)   : BlockFile(name,blength){	int i;	ptr=0;	if (csize>=0)	cachesize=csize;	else	error("CachedBlockFile::CachedBlockFile: neg. Cachesize",TRUE);	cache_cont = new int[cachesize];	fuf_cont = new uses[cachesize];	for (i=0; i<cachesize; i++)	{	cache_cont[i]=0;  // 0 bedeutet Cache unbenutzt (leer)	fuf_cont[i]=free;	}	cache = new char*[cachesize];	for (i=0; i<cachesize; i++)	cache[i] = new char[get_blocklength()];}CachedBlockFile::~CachedBlockFile(){	flush();	delete[] cache_cont;	delete[] fuf_cont;	for (int i=0;i<cachesize;i++)	delete[] cache[i];	delete[] cache;}bool CachedBlockFile::read_block(Block block,int index){	int c_ind;	index++;	// Externe Num. --> interne Num.	if(index<=get_num_of_blocks() && index>0)	{	if((c_ind=in_cache(index))>=0)		// gecached?	{		memcpy(block,cache[c_ind],get_blocklength());	}	else		// nicht im Cache	{		c_ind = next();		if (c_ind >= 0)			// Ist im Cache noch was frei?		{		BlockFile::read_block(cache[c_ind],index-1); // ext. Num.		cache_cont[c_ind]=index;		fuf_cont[c_ind]=used;		memcpy(block,cache[c_ind],get_blocklength());		}		else			// kein Cache mehr verfuegbar		BlockFile::read_block(block,index-1); // read-through (ext.Num.)	}	return TRUE;	}	else	return FALSE;}bool CachedBlockFile::write_block(const Block block,int index){	int c_ind;	index++;	// Externe Num. --> interne Num.	if(index <= get_num_of_blocks() && index > 0)	{	c_ind = in_cache(index);	if(c_ind >= 0)	// gecached?		memcpy(cache[c_ind], block, get_blocklength());	else		// nicht im C.	{		c_ind = next();		if (c_ind >= 0)			// im Cache was frei? (cachesize==0?)		{		memcpy(cache[c_ind],block,get_blocklength());		cache_cont[c_ind]=index;		fuf_cont[c_ind]=used;		}		else			// kein Cache verfuegbar			// write-through (ext.Num.)		BlockFile::write_block(block,index-1);	}	return TRUE;	}	else	return FALSE;}bool CachedBlockFile::fix_block(int index)// gefixte Bloecke bleiben immer im Cache{	int c_ind;	index++;	// Externe Num. --> interne Num.	if (index<=get_num_of_blocks() && index>0)	{	if((c_ind=in_cache(index))>=0) 	// gecached?		fuf_cont[c_ind]=fixed;	else		// nicht im C.		if((c_ind=next())>=0)	// im Cache was frei?		{		BlockFile::read_block(cache[c_ind],index-1); // ext.Num.		cache_cont[c_ind]=index;		fuf_cont[c_ind]=fixed;		}		else	// kein Cache verfuegbar		return FALSE;	return TRUE;	}	else	return FALSE;}bool CachedBlockFile::unfix_block(int index)// Fixierung eines Blocks durch fix_block wieder aufheben{	int i;	i =0;	index++;	// Externe Num. --> interne Num.	if(index<=get_num_of_blocks() && index>0)	{	while(i<cachesize && (cache_cont[i]!=index || fuf_cont[i]==free))		i++;	if (i!=cachesize)		fuf_cont[i]=used;	return TRUE;	}	else	return FALSE;}void CachedBlockFile::unfix_all()   // Hebt alle Fixierungen auf{	int i;	for (i=0; i<cachesize; i++)	if (fuf_cont[i]==fixed)		fuf_cont[i]=used;}void CachedBlockFile::set_cachesize(int size)// sichert und loescht alten Cache, und baut neuen auf (size>=0){	int i;	if (size>=0)	{	ptr=0;	flush();	for(i=0; i<cachesize; i++)		delete[] cache[i];	delete[] cache;	delete[] cache_cont;	delete[] fuf_cont;	cachesize = size;	cache_cont = new int[cachesize];	fuf_cont = new uses[cachesize];	for (i=0; i<cachesize; i++)	{		cache_cont[i]=0;  // 0 bedeutet Cache unbenutzt (leer)		fuf_cont[i]=free;	}	cache = new char*[cachesize];	for (i=0; i<cachesize; i++)		cache[i] = new char[get_blocklength()];	}	else	error("CachedBlockFile::set_cachesize : neg. cachesize",TRUE);}void CachedBlockFile::flush()// schreibt den  Cache auf Platte, gibt ihn nicht frei{	int i;	for (i=0; i<cachesize; i++)	if (fuf_cont[i]!=free)	// Cache besetzt?		BlockFile::write_block(cache[i], cache_cont[i]-1); // ext.Num.}      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -