📄 fsdirectory.cpp
字号:
/*------------------------------------------------------------------------------
* 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 + -