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

📄 fsdirectory.cpp

📁 clucene是c++版的全文检索引擎,完全移植于lucene,采用 stl 编写.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------------
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
* 
* Distributable under the terms of either the Apache License (Version 2.0) or 
* the GNU Lesser General Public License, as specified in the COPYING file.
------------------------------------------------------------------------------*/
#include "CLucene/StdHeader.h"
#include "FSDirectory.h"
#include "CLucene/util/Misc.h"
#include "CLucene/util/MD5Digester.h"
#include "CLucene/debug/condition.h"

#include "CLucene/util/dirent.h" //if we have dirent, then the native one will be used

CL_NS_DEF(store)
CL_NS_USE(util)

   /** This cache of directories ensures that there is a unique Directory
   * instance per path, so that synchronization on the Directory can be used to
   * synchronize access between readers and writers.
   */
	static CL_NS(util)::CLHashMap<const char*,FSDirectory*,CL_NS(util)::Compare::Char,CL_NS(util)::Equals::Char> DIRECTORIES(false,false);

	FSDirectory::FSIndexInput::FSIndexInput(const char* path, int32_t __bufferSize):
		BufferedIndexInput(__bufferSize)	
    {
	//Func - Constructor.
	//       Opens the file named path
	//Pre  - path != NULL
	//Post - if the file could not be opened  an exception is thrown.

	  CND_PRECONDITION(path != NULL, "path is NULL");

	  handle = _CLNEW SharedHandle();
	  strcpy(handle->path,path);

	  //Open the file
	  handle->fhandle  = _open(path, O_BINARY | O_RDONLY | O_RANDOM, _S_IREAD );
	  
	  //Check if a valid handle was retrieved
	  if (handle->fhandle < 0){
		int err = errno;
        if ( err == ENOENT )
		    _CLTHROWA(CL_ERR_IO, "File does not exist");
        else if ( err == EACCES )
            _CLTHROWA(CL_ERR_IO, "File Access denied");
        else if ( err == EMFILE )
            _CLTHROWA(CL_ERR_IO, "Too many open files");
	  }

	  //Store the file length
	  handle->_length = fileSize(handle->fhandle);
	  handle->_fpos = 0;
	  this->_pos = 0;
  }

  FSDirectory::FSIndexInput::FSIndexInput(const FSIndexInput& other): BufferedIndexInput(other){
  //Func - Constructor
  //       Uses clone for its initialization
  //Pre  - clone is a valide instance of FSIndexInput
  //Post - The instance has been created and initialized by clone
	if ( other.handle == NULL )
		_CLTHROWA(CL_ERR_NullPointer, "other handle is null");

	SCOPED_LOCK_MUTEX(other.handle->THIS_LOCK)
	handle = _CL_POINTER(other.handle);
	_pos = other.handle->_fpos; //note where we are currently...
  }

  FSDirectory::FSIndexInput::SharedHandle::SharedHandle(){
  	fhandle = 0;
    _length = 0;
    _fpos = 0;
    path[0]=0;
  }
  FSDirectory::FSIndexInput::SharedHandle::~SharedHandle() throw(CLuceneError&){
    if ( fhandle >= 0 ){
      if ( _close(fhandle) != 0 )
        _CLTHROWA(CL_ERR_IO, "File IO Close error");
      else
        fhandle = -1;
    }
  }

  FSDirectory::FSIndexInput::~FSIndexInput(){
  //Func - Destructor
  //Pre  - True
  //Post - The file for which this instance is responsible has been closed.
  //       The instance has been destroyed

	  FSIndexInput::close();
  }

  IndexInput* FSDirectory::FSIndexInput::clone() const
  {
    return _CLNEW FSDirectory::FSIndexInput(*this);
  }
  void FSDirectory::FSIndexInput::close()  {
	BufferedIndexInput::close();
	_CLDECDELETE(handle);
  }

  void FSDirectory::FSIndexInput::seekInternal(const int64_t position)  {
	CND_PRECONDITION(position>=0 &&position<handle->_length,"Seeking out of range")
	_pos = position;
  }

/** IndexInput methods */
void FSDirectory::FSIndexInput::readInternal(uint8_t* b, const int32_t len) {
	SCOPED_LOCK_MUTEX(handle->THIS_LOCK)
	CND_PRECONDITION(handle!=NULL,"shared file handle has closed");
	CND_PRECONDITION(handle->fhandle>=0,"file is not open");

	if ( handle->_fpos != _pos ){
		if ( fileSeek(handle->fhandle,_pos,SEEK_SET) != _pos ){
			_CLTHROWA( CL_ERR_IO, "File IO Seek error");
		}
		handle->_fpos = _pos;
	}

	bufferLength = _read(handle->fhandle,b,len); // 2004.10.31:SF 1037836
	if (bufferLength == 0){
		_CLTHROWA(CL_ERR_IO, "read past EOF");
	}
	if (bufferLength == -1){
		_CLTHROWA(CL_ERR_IO, "read error");
	}
	_pos+=bufferLength;
	handle->_fpos=_pos;
}

  FSDirectory::FSIndexOutput::FSIndexOutput(const char* path){
	//O_BINARY - Opens file in binary (untranslated) mode
	//O_CREAT - Creates and opens new file for writing. Has no effect if file specified by filename exists
	//O_RANDOM - Specifies that caching is optimized for, but not restricted to, random access from disk.
	//O_WRONLY - Opens file for writing only;
	if ( Misc::dir_Exists(path) )
	  fhandle = _open( path, O_BINARY | O_RDWR | O_RANDOM | O_TRUNC, _S_IREAD | _S_IWRITE);
	else // added by JBP
	  fhandle = _open( path, O_BINARY | O_RDWR | O_RANDOM | O_CREAT, _S_IREAD | _S_IWRITE);

	if ( fhandle < 0 ){
        int err = errno;
        if ( err == ENOENT )
    	    _CLTHROWA(CL_ERR_IO, "File does not exist");
        else if ( err == EACCES )
            _CLTHROWA(CL_ERR_IO, "File Access denied");
        else if ( err == EMFILE )
            _CLTHROWA(CL_ERR_IO, "Too many open files");
    }
  }
  FSDirectory::FSIndexOutput::~FSIndexOutput(){
	if ( fhandle >= 0 ){
	  try {
        FSIndexOutput::close();
	  }catch(...){ //todo: only catch IO Err???
	  }
	}
  }

  /** output methods: */
  void FSDirectory::FSIndexOutput::flushBuffer(const uint8_t* b, const int32_t size) {
	  CND_PRECONDITION(fhandle>=0,"file is not open");
      if ( size > 0 && _write(fhandle,b,size) != size )
        _CLTHROWA(CL_ERR_IO, "File IO Write error");
  }
  void FSDirectory::FSIndexOutput::close() {
    try{
      IndexOutput::close();
    }catch(...){} //todo: only catch IO Err???

    if ( _close(fhandle) != 0 )
      _CLTHROWA(CL_ERR_IO, "File IO Close error");
    else
      fhandle = -1; //-1 now indicates closed
  }

  void FSDirectory::FSIndexOutput::seek(const int64_t pos) {
    CND_PRECONDITION(fhandle>=0,"file is not open");
    IndexOutput::seek(pos);
	int64_t ret = fileSeek(fhandle,pos,SEEK_SET);
	if ( ret != pos ){
      _CLTHROWA(CL_ERR_IO, "File IO Seek error");
	}
  }
  int64_t FSDirectory::FSIndexOutput::length(){
	  CND_PRECONDITION(fhandle>=0,"file is not open");
	  return fileSize(fhandle);
  }


	const char* FSDirectory::LOCK_DIR=NULL;
	const char* FSDirectory::getLockDir(){
		#ifdef LUCENE_LOCK_DIR
		LOCK_DIR = LUCENE_LOCK_DIR	
		#else	
		if ( LOCK_DIR == NULL ){
			#ifdef LUCENE_LOCK_DIR_ENV_1
				LOCK_DIR = getenv(LUCENE_LOCK_DIR_ENV_1);
			#endif			
			#ifdef LUCENE_LOCK_DIR_ENV_2
				if ( LOCK_DIR == NULL && getenv(LUCENE_LOCK_DIR_ENV_2) != NULL )
					LOCK_DIR = getenv(LUCENE_LOCK_DIR_ENV_2);
			#endif
			#ifdef LUCENE_LOCK_DIR_ENV_FALLBACK
				if ( LOCK_DIR == NULL )
					LOCK_DIR=LUCENE_LOCK_DIR_ENV_FALLBACK;
			#endif
		}
	#endif
		
		return LOCK_DIR;
	}

  FSDirectory::FSDirectory(const char* path, const bool createDir):
   Directory(),
   refCount(0),
   useMMap(false)
  {
  	_realpath(path,directory);//set a realpath so that if we change directory, we can still function
  	if ( !directory || !*directory ){
  		strcpy(directory,path);	
  	}
    
	const char* tmplockdir = getLockDir();
    if ( tmplockdir == NULL ) {
      strcpy(lockDir,directory);
    } else {
      strcpy(lockDir,tmplockdir);
    }

    if (createDir) {
      create();
    }

    if (!Misc::dir_Exists(directory)){
		char* err = _CL_NEWARRAY(char,19+strlen(path)+1); //19: len of " is not a directory"
		strcpy(err,path);
		strcat(err," is not a directory");
        _CLTHROWA_DEL(CL_ERR_IO, err );
    }
  }


  void FSDirectory::create(){
    SCOPED_LOCK_MUTEX(THIS_LOCK)
	if ( !Misc::dir_Exists(directory) ){
       //todo: should construct directory using _mkdirs... have to write replacement
      if ( _mkdir(directory) == -1 ){
		  char* err = _CL_NEWARRAY(char,27+strlen(directory)+1); //27: len of "Couldn't create directory: "
		  strcpy(err,"Couldn't create directory: ");
		  strcat(err,directory);
		  _CLTHROWA_DEL(CL_ERR_IO, err );
      }
	}

	  //clear old files
    DIR* dir = opendir(directory);
    struct dirent* fl = readdir(dir);
    struct fileStat buf;

    char path[CL_MAX_DIR];
    while ( fl != NULL ){
      _snprintf(path,CL_MAX_DIR,"%s/%s",directory,fl->d_name);
      int32_t ret = fileStat(path,&buf);
      if ( ret==0 && !(buf.st_mode & S_IFDIR) ) {
        if ( (strcmp(fl->d_name, ".")) && (strcmp(fl->d_name, "..")) ) {
        if ( _unlink( path ) == -1 ) {
          closedir(dir);
          _CLTHROWA(CL_ERR_IO, "Couldn't delete file "); //todo: make richer error
        }
        }
      }
      fl = readdir(dir);
    }
    closedir(dir);

	char* lockPrefix = getLockPrefix(); // clear old locks
	size_t lockPrefixLen = strlen(lockPrefix);
	
    dir = opendir(lockDir);
	fl = readdir(dir);
    while ( fl != NULL ){
		if (strncmp(fl->d_name,lockPrefix,lockPrefixLen)==0){
			_snprintf(path,CL_MAX_DIR,"%s/%s",lockDir,fl->d_name);
			if ( _unlink( path ) == -1 ) {
				closedir(dir);
				_CLDELETE_CaARRAY(lockPrefix);
				_CLTHROWA(CL_ERR_IO, "Couldn't delete file "); //todo: make richer error
			}
		}
      fl = readdir(dir);
    }
    closedir(dir);
    _CLDELETE_CaARRAY(lockPrefix);
  }

  void FSDirectory::priv_getFN(char* buffer, const char* name) const{
      buffer[0] = 0;
      strcpy(buffer,directory);
      strcat(buffer, PATH_DELIMITERA );
      strcat(buffer,name);
  }

  FSDirectory::~FSDirectory(){
  }

  char** FSDirectory::list() const{
    CND_PRECONDITION(directory[0]!=0,"directory is not open");
    DIR* dir = opendir(directory);

⌨️ 快捷键说明

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