📄 fsdirectory.cpp
字号:
struct dirent* fl = readdir(dir);
struct fileStat buf;
AStringArray names;
char path[CL_MAX_DIR];
strncpy(path,directory,CL_MAX_DIR);
strcat(path,PATH_DELIMITERA);
char* pathP = path + strlen(path);
while ( fl != NULL ){
strcpy(pathP,fl->d_name);
fileStat(path,&buf);
if ( !(buf.st_mode & S_IFDIR) ) {
names.push_back( STRDUP_AtoA(fl->d_name) );
}
fl = readdir(dir);
}
closedir(dir);
size_t size = names.size();
char** ret = _CL_NEWARRAY(char*,size+1);
for ( size_t i=0;i<size;i++ )
ret[i] = names[i];
ret[size]=NULL;
return ret;
}
bool FSDirectory::fileExists(const char* name) const {
CND_PRECONDITION(directory[0]!=0,"directory is not open");
char fl[CL_MAX_DIR];
priv_getFN(fl, name);
return Misc::dir_Exists( fl );
}
const char* FSDirectory::getDirName() const{
return directory;
}
//static
FSDirectory* FSDirectory::getDirectory(const char* file, const bool _create){
FSDirectory* dir = NULL;
{
if ( !file || !*file )
_CLTHROWA(CL_ERR_IO,"Invalid directory");
SCOPED_LOCK_MUTEX(DIRECTORIES.THIS_LOCK)
dir = DIRECTORIES.get(file);
if ( dir == NULL ){
dir = _CLNEW FSDirectory(file,_create);
DIRECTORIES.put( dir->directory, dir);
}else if ( _create ){
dir->create();
}
}
{
SCOPED_LOCK_MUTEX(dir->THIS_LOCK)
dir->refCount++;
}
return _CL_POINTER(dir);
}
int64_t FSDirectory::fileModified(const char* name) const {
CND_PRECONDITION(directory[0]!=0,"directory is not open");
struct fileStat buf;
char buffer[CL_MAX_DIR];
priv_getFN(buffer,name);
if (fileStat( buffer, &buf ) == -1 )
return 0;
else
return buf.st_mtime;
}
//static
int64_t FSDirectory::fileModified(const char* dir, const char* name){
struct fileStat buf;
char buffer[CL_MAX_DIR];
_snprintf(buffer,CL_MAX_DIR,"%s%s%s",dir,PATH_DELIMITERA,name);
fileStat( buffer, &buf );
return buf.st_mtime;
}
void FSDirectory::touchFile(const char* name){
CND_PRECONDITION(directory[0]!=0,"directory is not open");
char buffer[CL_MAX_DIR];
_snprintf(buffer,CL_MAX_DIR,"%s%s%s",directory,PATH_DELIMITERA,name);
//todo: haven't checked this:
int32_t r = _open(buffer, O_RDWR, _S_IWRITE);
if ( r < 0 )
_CLTHROWA(CL_ERR_IO,"IO Error while touching file");
_close(r);
}
int64_t FSDirectory::fileLength(const char* name) const {
CND_PRECONDITION(directory[0]!=0,"directory is not open");
struct fileStat buf;
char buffer[CL_MAX_DIR];
priv_getFN(buffer,name);
if ( fileStat( buffer, &buf ) == -1 )
return 0;
else
return buf.st_size;
}
IndexInput* FSDirectory::openInput(const char* name ) {
return openInput(name, LUCENE_STREAM_BUFFER_SIZE);
}
#ifdef LUCENE_FS_MMAP
IndexInput* FSDirectory::openMMapFile(const char* name, int32_t bufferSize){
char fl[CL_MAX_DIR];
priv_getFN(fl, name);
if ( Misc::file_Size(fl) < LUCENE_INT32_MAX_SHOULDBE ) //todo: would this be bigger on 64bit systems?. i suppose it would be...test first
return _CLNEW MMapIndexInput( fl );
else
return _CLNEW FSIndexInput( fl, bufferSize );
}
#endif
IndexInput* FSDirectory::openInput(const char* name, int32_t bufferSize ){
CND_PRECONDITION(directory[0]!=0,"directory is not open")
char fl[CL_MAX_DIR];
priv_getFN(fl, name);
#ifdef LUCENE_FS_MMAP
//todo: do some tests here... like if the file
//is >2gb, then some system cannot mmap the file
//also some file systems mmap will fail?? could detect here too
if ( useMMap && Misc::file_Size(fl) < LUCENE_INT32_MAX_SHOULDBE ) //todo: would this be bigger on 64bit systems?. i suppose it would be...test first
return _CLNEW MMapIndexInput( fl );
else
#endif
return _CLNEW FSIndexInput( fl, bufferSize );
}
void FSDirectory::close(){
SCOPED_LOCK_MUTEX(DIRECTORIES.THIS_LOCK)
{
SCOPED_LOCK_MUTEX(THIS_LOCK)
CND_PRECONDITION(directory[0]!=0,"directory is not open");
if (--refCount <= 0 ) {//refcount starts at 1
Directory* dir = DIRECTORIES.get(getDirName());
if(dir){
DIRECTORIES.remove( getDirName() ); //this will be removed in ~FSDirectory
_CLDECDELETE(dir);
}
}
}
}
/**
* So we can do some byte-to-hexchar conversion below
*/
char HEX_DIGITS[] =
{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
char* FSDirectory::getLockPrefix() const{
char dirName[CL_MAX_PATH]; // name to be hashed
if ( _realpath(directory,dirName) == NULL ){
_CLTHROWA(CL_ERR_Runtime,"Invalid directory path");
}
//to make a compatible name with jlucene, we need to make some changes...
if ( dirName[1] == ':' )
dirName[0] = (char)_totupper((char)dirName[0]);
char* smd5 = MD5String(dirName);
char* ret=_CL_NEWARRAY(char,32+7+1); //32=2*16, 7=strlen("lucene-")
strcpy(ret,"lucene-");
strcat(ret,smd5);
_CLDELETE_CaARRAY(smd5);
return ret;
}
bool FSDirectory::deleteFile(const char* name) {
CND_PRECONDITION(directory[0]!=0,"directory is not open");
char fl[CL_MAX_DIR];
priv_getFN(fl, name);
return _unlink(fl) != -1;
}
void FSDirectory::renameFile(const char* from, const char* to){
CND_PRECONDITION(directory[0]!=0,"directory is not open");
SCOPED_LOCK_MUTEX(THIS_LOCK)
char old[CL_MAX_DIR];
priv_getFN(old, from);
char nu[CL_MAX_DIR];
priv_getFN(nu, to);
/* This is not atomic. If the program crashes between the call to
delete() and the call to renameTo() then we're screwed, but I've
been unable to figure out how else to do this... */
if ( Misc::dir_Exists(nu) )
if( _unlink(nu) != 0 ){
char* err = _CL_NEWARRAY(char,16+strlen(to)+1); //16: len of "couldn't delete "
strcpy(err,"couldn't delete ");
strcat(err,to);
_CLTHROWA_DEL(CL_ERR_IO, err );
}
if ( _rename(old,nu) != 0 ){
//todo: jlucene has some extra rename code - if the rename fails, it copies
//the whole file to the new file... might want to implement that if renaming
//fails on some platforms
char buffer[200];
strcpy(buffer,"couldn't rename ");
strcat(buffer,from);
strcat(buffer," to ");
strcat(buffer,to);
_CLTHROWA(CL_ERR_IO, buffer );
}
}
IndexOutput* FSDirectory::createOutput(const char* name) {
CND_PRECONDITION(directory[0]!=0,"directory is not open");
char fl[CL_MAX_DIR];
priv_getFN(fl, name);
return _CLNEW FSIndexOutput( fl );
}
LuceneLock* FSDirectory::makeLock(const char* name) {
CND_PRECONDITION(directory[0]!=0,"directory is not open");
char* tmp = getLockPrefix();
char* lockFile = _CL_NEWARRAY(char,strlen(tmp)+strlen(name)+2);
strcpy(lockFile,tmp);
strcat(lockFile,"-");
strcat(lockFile,name);
_CLDELETE_CaARRAY(tmp);
// create a lock file
LuceneLock* ret = _CLNEW FSLock( lockDir, lockFile );
_CLDELETE_CaARRAY(lockFile);
return ret;
}
FSDirectory::FSLock::FSLock ( const char* _lockDir, const char* name )
{
this->lockDir = STRDUP_AtoA(_lockDir);
strcpy(lockFile,_lockDir);
strcat(lockFile,PATH_DELIMITERA);
strcat(lockFile,name);
}
FSDirectory::FSLock::~FSLock(){
_CLDELETE_LCaARRAY( lockDir );
}
TCHAR* FSDirectory::FSLock::toString(){
size_t lflen = strlen(lockFile);
TCHAR* ret = _CL_NEWARRAY(TCHAR,lflen+6);
_tcscpy(ret,_T("Lock@"));
STRCPY_AtoT(ret+5,lockFile,lflen+1);
return ret;
}
bool FSDirectory::FSLock::obtain() {
if (LUCENE_DISABLE_LOCKS)
return true;
if ( Misc::dir_Exists(lockFile) )
return false;
if ( !Misc::dir_Exists(lockDir) ){
//todo: should construct directory using _mkdirs... have to write replacement
if ( _mkdir(lockDir) == -1 ){
char* err = _CL_NEWARRAY(char,34+strlen(lockDir)+1); //34: len of "Couldn't create lock directory: "
strcpy(err,"Couldn't create lock directory: ");
strcat(err,lockDir);
_CLTHROWA_DEL(CL_ERR_IO, err );
}
}
int32_t r = _open(lockFile, O_RDWR | O_CREAT | O_RANDOM , _S_IREAD | _S_IWRITE); //must do this or file will be created Read only
if ( r < 0 )
return false;
else{
_close(r);
return true;
}
}
bool FSDirectory::FSLock::isLocked(){
if (LUCENE_DISABLE_LOCKS)
return false;
return Misc::dir_Exists(lockFile);
}
void FSDirectory::FSLock::release() {
if (LUCENE_DISABLE_LOCKS)
return;
_unlink( lockFile );
}
TCHAR* FSDirectory::toString() const{
TCHAR* ret = _CL_NEWARRAY(TCHAR, strlen(this->directory) + 13); //strlen("FSDirectory@")
_tcscpy(ret,_T("FSDirectory@"));
STRCPY_AtoT(ret+12,directory,strlen(directory)+1);
return ret;
}
CL_NS_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -