Exemple #1
0
/* precond: fileCache locked or single thread use */
iFuseDesc_t *newIFuseDesc (char *objPath, char *localPath, fileCache_t *fileCache, int *status) {
	iFuseDesc_t *desc;
	LOCK_STRUCT(*IFuseDescFreeList);
	/*
	printf("******************************************************\n");
	printf("num of desc slots free = %d\n", _listSize(IFuseDescFreeList));
	printf("******************************************************\n"); */
	if(_listSize(IFuseDescFreeList)!=0) {
		ListNode *node = IFuseDescFreeList->list->head;
		desc = (iFuseDesc_t *) node->value;
		listRemoveNoRegion(IFuseDescFreeList->list, node);
		UNLOCK_STRUCT(*IFuseDescFreeList);
        REF_NO_LOCK(desc->fileCache, fileCache);
		desc->objPath = strdup (objPath);
		desc->localPath = strdup (localPath);
        INIT_STRUCT_LOCK(*desc);
        *status = 0;
        return desc;
	} else {
		UNLOCK_STRUCT(*IFuseDescFreeList);
		rodsLog (LOG_ERROR,
		  "allocIFuseDesc: Out of iFuseDesc");
		*status = SYS_OUT_OF_FILE_DESC;

		return NULL;
	}
}
Exemple #2
0
int
renameLocalPath( PathCacheTable *pctable, char *from, char *to, char *toIrodsPath ) {

    /* do not check existing path here as path cache may be out of date */
    pathCache_t *fromPathCache = matchPathCache( pctable, from );
    if ( NULL == fromPathCache ) {
        return 0;
    }
    LOCK_STRUCT( *fromPathCache );

    if ( fromPathCache->fileCache != NULL ) {
        LOCK_STRUCT( *( fromPathCache->fileCache ) );
        free( fromPathCache->fileCache->localPath );
        fromPathCache->fileCache->localPath = strdup( to );
        free( fromPathCache->fileCache->objPath );
        fromPathCache->fileCache->objPath = strdup( toIrodsPath );
        UNLOCK_STRUCT( *( fromPathCache->fileCache ) );
    }

    pathCache_t *tmpPathCache = NULL;
    LOCK( *pctable -> PathCacheLock );
    pathReplace( pctable, ( char * ) to, fromPathCache->fileCache, &fromPathCache->stbuf, &tmpPathCache );

    pathNotExist( pctable, ( char * ) from );

    UNLOCK( *pctable -> PathCacheLock );
    UNLOCK_STRUCT( *fromPathCache );
    return 0;
}
Exemple #3
0
int
ifuseConnect( iFuseConn_t *iFuseConn, rodsEnv *myRodsEnv ) {
    int status = 0;
    LOCK_STRUCT( *iFuseConn );
    if ( iFuseConn->conn == NULL ) {
        rErrMsg_t errMsg;
        iFuseConn->conn = rcConnect( myRodsEnv->rodsHost, myRodsEnv->rodsPort,
                                     myRodsEnv->rodsUserName, myRodsEnv->rodsZone, NO_RECONN, &errMsg );

        if ( iFuseConn->conn == NULL ) {
            /* try one more */
            iFuseConn->conn = rcConnect( myRodsEnv->rodsHost, myRodsEnv->rodsPort,
                                         myRodsEnv->rodsUserName, myRodsEnv->rodsZone, NO_RECONN, &errMsg );
            if ( iFuseConn->conn == NULL ) {
                rodsLogError( LOG_ERROR, errMsg.status,
                              "ifuseConnect: rcConnect failure %s", errMsg.msg );
                UNLOCK_STRUCT( *iFuseConn );
                if ( errMsg.status < 0 ) {
                    return errMsg.status;
                }
                else {
                    return -1;
                }
            }
        }

        status = clientLogin( iFuseConn->conn );
        if ( status != 0 ) {
            rcDisconnect( iFuseConn->conn );
            iFuseConn->conn = NULL;
        }
    }
    UNLOCK_STRUCT( *iFuseConn );
    return status;
}
Exemple #4
0
fileCache_t *addFileCache( int iFd, char *objPath, char *localPath, char *cachePath, int mode, rodsLong_t fileSize, cacheState_t state ) {
    uint cachedTime = time( 0 );
    fileCache_t *fileCache, *swapCache;

    if ( state == NO_FILE_CACHE ) {
        return newFileCache( iFd, objPath, localPath, cachePath, cachedTime, mode, fileSize, state );
    }
    else {

        fileCache = newFileCache( iFd, objPath, localPath, cachePath, cachedTime, mode, fileSize, state );
        LOCK_STRUCT( *FileCacheList );


        if ( _listSize( FileCacheList ) >= NUM_NEWLY_CREATED_SLOT ) {
            ListNode *node = FileCacheList->list->head;
            swapCache = ( fileCache_t * ) node->value;
            listRemoveNoRegion( FileCacheList->list, node );

            UNLOCK_STRUCT( *FileCacheList );
            ifuseFileCacheSwapOut( swapCache );
            LOCK_STRUCT( *FileCacheList );

            listAppendNoRegion( FileCacheList->list, fileCache );

        }

        UNLOCK_STRUCT( *FileCacheList );
        return fileCache;
    }
}
int
renmeLocalPath( char *from, char *to, char *toIrodsPath ) {
    pathCache_t *fromPathCache = NULL;
    pathCache_t *tmpPathCache = NULL;

    /* do not check existing path here as path cache may be out of date */
    matchAndLockPathCache( from, &fromPathCache );
    if ( fromPathCache == NULL ) {
        return 0;
    }

    LOCK( PathCacheLock );
    if ( fromPathCache->fileCache != NULL ) {
        LOCK_STRUCT( *( fromPathCache->fileCache ) );
        free( fromPathCache->fileCache->localPath );
        fromPathCache->fileCache->localPath = strdup( to );
        free( fromPathCache->fileCache->objPath );
        fromPathCache->fileCache->objPath = strdup( toIrodsPath );

        _pathReplace( ( char * ) to, fromPathCache->fileCache, &fromPathCache->stbuf, &tmpPathCache );

        UNLOCK_STRUCT( *( fromPathCache->fileCache ) );
    }
    else {
        _pathReplace( ( char * ) to, NULL /* fromPathCache->fileCache */, &fromPathCache->stbuf, &tmpPathCache );

    }

    /* need to unlock fileCache here since the following function call ness to lock fileCache */
    _pathNotExist( ( char * ) from );

    UNLOCK_STRUCT( *fromPathCache );
    UNLOCK( PathCacheLock );
    return 0;
}
Exemple #6
0
void
connManager() {
    time_t curTime;
    iFuseConn_t *tmpIFuseConn;
    ListNode *node;
    List *TimeOutList = newListNoRegion();

    while ( 1 ) {
        curTime = time( NULL );

        /* exceed high water mark for number of connection ? */
        if ( listSize( ConnectedConn ) > HIGH_NUM_CONN ) {

            LOCK_STRUCT( *ConnectedConn );
            int disconnTarget = _listSize( ConnectedConn ) - HIGH_NUM_CONN;
            node = ConnectedConn->list->head;
            while ( node != NULL ) {
                tmpIFuseConn = ( iFuseConn_t * ) node->value;
                if ( tmpIFuseConn->inuseCnt == 0 && tmpIFuseConn->pendingCnt == 0 && curTime - tmpIFuseConn->actTime > IFUSE_CONN_TIMEOUT ) {
                    listAppendNoRegion( TimeOutList, tmpIFuseConn );

                }
                node = node->next;
            }
            UNLOCK_STRUCT( *ConnectedConn );

            node = TimeOutList->head;
            int disconned = 0;
            while ( node != NULL && disconned < disconnTarget ) {
                tmpIFuseConn = ( iFuseConn_t * ) node->value;
                LOCK_STRUCT( *tmpIFuseConn );
                if ( tmpIFuseConn->inuseCnt == 0 && tmpIFuseConn->pendingCnt == 0 && curTime - tmpIFuseConn->actTime > IFUSE_CONN_TIMEOUT ) {
                    removeFromConcurrentList2( FreeConn, tmpIFuseConn );
                    removeFromConcurrentList2( ConnectedConn, tmpIFuseConn );
                    if ( tmpIFuseConn->status == 0 ) { /* no struct is referring to it, we can unlock it and free it */
                        UNLOCK_STRUCT( *tmpIFuseConn );
                        /* rodsLog(LOG_ERROR, "[FREE IFUSE CONN] %s:%d %p", __FILE__, __LINE__, tmpIFuseConn); */
                        _freeIFuseConn( tmpIFuseConn );
                    }
                    else {   /* set to timed out */
                        _ifuseDisconnect( tmpIFuseConn );
                        UNLOCK_STRUCT( *tmpIFuseConn );
                    }
                    disconned ++;
                }
                else {
                    UNLOCK_STRUCT( *tmpIFuseConn );
                }
                node = node->next;
            }
            clearListNoRegion( TimeOutList );
        }

        notifyWait( &connReqWait.mutex, &connReqWait.cond );
        timeoutWait( &ConnManagerLock, &ConnManagerCond, CONN_MANAGER_SLEEP_TIME );

    }
    deleteListNoRegion( TimeOutList );
}
Exemple #7
0
int
irodsTruncate (const char *path, off_t size)
{
    dataObjInp_t dataObjInp;
    int status;
    pathCache_t *tmpPathCache;
    iFuseConn_t *iFuseConn = NULL;

    rodsLog (LOG_DEBUG, "irodsTruncate: %s", path);

    if (matchAndLockPathCache ((char *) path, &tmpPathCache) == 1) {
        if(tmpPathCache->fileCache != NULL) {
            LOCK_STRUCT(*tmpPathCache->fileCache);
            if(tmpPathCache->fileCache->state == HAVE_NEWLY_CREATED_CACHE) {
                status = truncate (tmpPathCache->fileCache->fileCachePath, size);
                if (status >= 0) {
                    updatePathCacheStatFromFileCache (tmpPathCache);
                    UNLOCK_STRUCT(*(tmpPathCache->fileCache));
                    UNLOCK_STRUCT(*tmpPathCache);
                    return (0);
                }
            }
            UNLOCK_STRUCT(*(tmpPathCache->fileCache));
        }

    }
    UNLOCK_STRUCT(*tmpPathCache);


    memset (&dataObjInp, 0, sizeof (dataObjInp));
    status = parseRodsPathStr ((char *) (path + 1) , &MyRodsEnv, dataObjInp.objPath);
    if (status < 0) {
        rodsLogError (LOG_ERROR, status, "irodsTruncate: parseRodsPathStr of %s error", path);
        /* use ENOTDIR for this type of error */
        return -ENOTDIR;
    }

    dataObjInp.dataSize = size;

    getAndUseIFuseConn (&iFuseConn, &MyRodsEnv);
    RECONNECT_IF_NECESSARY(status, iFuseConn, rcDataObjTruncate (iFuseConn->conn, &dataObjInp));
    if (status >= 0) {
        pathCache_t *tmpPathCache;

        if (matchAndLockPathCache ((char *) path, &tmpPathCache) == 1) {
            tmpPathCache->stbuf.st_size = size;
        }
        UNLOCK_STRUCT(*tmpPathCache);
        status = 0;
    } else {
        rodsLogError (LOG_ERROR, status,
                      "irodsTruncate: rcDataObjTruncate of %s error", path);
        status = -ENOENT;
    }
    unuseIFuseConn (iFuseConn);

    return (status);
}
void fl_deleteConcurrentList(fl_concurrentList_t *l) {
    LOCK_STRUCT(*l);
    fl_clearList(l->list);
	fl_deleteList(l->list);
    UNLOCK_STRUCT(*l);
	free(l);
}
/* close a iFuse file */
int
ifuseClose (iFuseDesc_t *desc)
{
	int status;

    LOCK_STRUCT(*desc);

	status = _ifuseFlush(desc);
	if(status < 0) {
		rodsLogError(LOG_ERROR, status, "ifuseClose: flush of %s error",
				desc->localPath);

	}
	status = ifuseFileCacheClose(desc->fileCache);
	if(status < 0) {
		rodsLogError(LOG_ERROR, status, "ifuseClose: close of %s error",
				desc->localPath);

	}
	status = _freeIFuseDesc(desc);

	UNLOCK_STRUCT(*desc);
	if(status < 0) {
		rodsLogError(LOG_ERROR, status, "ifuseClose: free desc struct error",
				desc->localPath);

	}

	return status;
}
Exemple #10
0
/* precond: lock paca */
int _getAndUseConnForPathCache( iFuseConn_t **iFuseConn, pathCache_t *paca ) {
    int status;
    /* if connection already closed by connection manager, get new ifuseconn */
    if ( paca->iFuseConn != NULL ) {
        LOCK_STRUCT( *( paca->iFuseConn ) );
        if ( paca->iFuseConn->conn != NULL ) {
            if ( paca->iFuseConn->inuseCnt == 0 ) {
                _useIFuseConn( paca->iFuseConn );
                UNLOCK_STRUCT( *( paca->iFuseConn ) );
                /* ifuseReconnect(paca->iFuseConn); */
                *iFuseConn = paca->iFuseConn;
                return 0;
            }
            else {
                UNLOCK_STRUCT( *( paca->iFuseConn ) );
            }
        }
        else {
            UNLOCK_STRUCT( *( paca->iFuseConn ) );
            /* disconnect by not freed yet */
            UNREF( paca->iFuseConn, IFuseConn );
        }
    }

    iFuseConn_t *tmpIFuseConn;
    // UNLOCK_STRUCT( *paca );
    status = getAndUseIFuseConn( &tmpIFuseConn );
    // LOCK_STRUCT( *paca );
    if ( status < 0 ) {
        rodsLog( LOG_ERROR,
                 "ifuseClose: cannot get ifuse connection for %s error, status = %d",
                 paca->localPath, status );
        return status;
    }
    // if ( paca->iFuseConn != NULL ) {
        /* has been changed by other threads, or current paca->ifuseconn inuse,
         * return new ifuseconn without setting paca->ifuseconn */
    //    *iFuseConn = tmpIFuseConn;
    //}
    //else {
        /* conn in use, cannot be deleted by conn manager
         * therefore, it is safe to do the following without locking conn */
        REF( paca->iFuseConn, tmpIFuseConn );
        *iFuseConn = paca->iFuseConn;
    //}
    return 0;
}
Exemple #11
0
int iFuseFileCacheFlush( fileCache_t *fileCache ) {
    int status;

    LOCK_STRUCT( *fileCache );
    status = _iFuseFileCacheFlush( fileCache );
    UNLOCK_STRUCT( *fileCache );
    return status;
}
int
ifuseFlush (int descInx)
{
    int status;
    LOCK_STRUCT(IFuseDesc[descInx]);
	status = _ifuseFlush (&IFuseDesc[descInx]);
    UNLOCK_STRUCT(IFuseDesc[descInx]);

    return status;
}
Exemple #13
0
int
useIFuseConn( iFuseConn_t *iFuseConn ) {
    int status;
    if ( iFuseConn == NULL || iFuseConn->conn == NULL ) {
        return USER__NULL_INPUT_ERR;
    }
    LOCK_STRUCT( *iFuseConn );
    status = _useIFuseConn( iFuseConn );
    UNLOCK_STRUCT( *iFuseConn );

    return status;
}
Exemple #14
0
void* removeFirstElementOfConcurrentList(concurrentList_t *l) {
	LOCK_STRUCT(*l);
	void* tmp;
	if(l->list->head == NULL) {
		tmp = NULL;
	} else {
		tmp = l->list->head->value;
		listRemoveNoRegion(l->list, l->list->head);
	}
	UNLOCK_STRUCT(*l);
	return tmp;
}
/**************************************************************************
 * private functions
 **************************************************************************/
static void *_preloadThread(void *arg) {
    int status;
    preloadThreadData_t *threadData = (preloadThreadData_t *)arg;
    preloadThreadInfo_t *threadInfo = NULL;

    if(threadData == NULL) {
        rodsLog (LOG_DEBUG, "_preloadThread: given thread argument is null");
        pthread_exit(NULL);
    }

    threadInfo = threadData->threadInfo;

    rodsLog (LOG_DEBUG, "_preloadThread: preload - %s", threadData->path);
    
    status = _download(threadData->path, &threadData->stbuf);
    if(status != 0) {
        rodsLog (LOG_DEBUG, "_preloadThread: download error - %d", status);
    }

    // downloading is done
    LOCK(PreloadLock);

    // change thread status
    LOCK_STRUCT(*threadInfo);
    threadInfo->running = PRELOAD_THREAD_IDLE;
    UNLOCK_STRUCT(*threadInfo);

    // release threadData
    rodsLog (LOG_DEBUG, "_preloadThread: thread finished - %s", threadData->path);
    if(threadData->path != NULL) {
        free(threadData->path);
        threadData->path = NULL;
    }

    free(threadData);

    // remove from hash table
    removeFromConcurrentList2(PreloadThreadList, threadInfo);
    deleteFromHashTable(PreloadThreadTable, threadInfo->path);

    if(threadInfo != NULL) {
        if(threadInfo->path != NULL) {
            free(threadInfo->path);
            threadInfo->path = NULL;
        }
        free(threadInfo);
    }

    UNLOCK(PreloadLock);
    pthread_exit(NULL);
}
void *fl_removeLastElementOfConcurrentList(fl_concurrentList_t *l) {
	LOCK_STRUCT(*l);
	void* tmp;
	if(l->list->head == NULL) {
		tmp = NULL;
    }
    else {
		tmp = l->list->tail->value;
		fl_listRemove(l->list, l->list->tail);
	}
	UNLOCK_STRUCT(*l);
	return tmp;

}
Exemple #17
0
int
unuseIFuseConn( iFuseConn_t *iFuseConn ) {
    if ( iFuseConn == NULL || iFuseConn->conn == NULL ) {
        return USER__NULL_INPUT_ERR;
    }
    LOCK_STRUCT( *iFuseConn );
    iFuseConn->actTime = time( NULL );
    iFuseConn->inuseCnt--;
    if ( iFuseConn->pendingCnt == 0 ) {
        addToConcurrentList( FreeConn, iFuseConn );
    }
    UNLOCK_STRUCT( *iFuseConn );
    signalConnManager();
    return 0;
}
Exemple #18
0
/* getIFuseConnByPath - try to use the same conn as opened desc of the
 * same path */
iFuseConn_t *getAndUseConnByPath( char *localPath, int *status ) {
    iFuseConn_t *iFuseConn;
    /* make sure iFuseConn is not released after getAndLockIFuseDescByPath finishes */
    pathCache_t *tmpPathCache = matchPathCache( pctable, localPath );
    if ( tmpPathCache ) {
        LOCK_STRUCT( *tmpPathCache );
        *status = _getAndUseConnForPathCache( &iFuseConn, tmpPathCache );
        UNLOCK_STRUCT( *tmpPathCache );
    }
    else {
        /* no match. just assign one */
        pathExist( pctable, localPath, NULL, NULL, NULL ); // need to find a way to clean up
        *status = getAndUseIFuseConn( &iFuseConn );

    }

    return iFuseConn;
}
Exemple #19
0
/* close any open files inside the file cache */
int ifuseFileCacheClose( fileCache_t *fileCache ) {
    int status = 0;
    LOCK_STRUCT( *fileCache );
    if ( fileCache->state == NO_FILE_CACHE ) {
        /* close remote file */
        //UNLOCK_STRUCT( *fileCache );
        iFuseConn_t *conn = getAndUseConnByPath( fileCache->localPath, &status );
        //LOCK_STRUCT( *fileCache );
        status = closeIrodsFd( conn->conn, fileCache->iFd );
        unuseIFuseConn( conn );
        fileCache->offset = 0;
    }
    else {
        /* close local file */
        status = close( fileCache->iFd );
        fileCache->iFd = 0;
        fileCache->offset = 0;
    }
    UNLOCK_STRUCT( *fileCache );
    return status;
}
Exemple #20
0
int
_useIFuseConn( iFuseConn_t *iFuseConn ) {
    if ( iFuseConn == NULL || iFuseConn->conn == NULL ) {
        return USER__NULL_INPUT_ERR;
    }

    iFuseConn->actTime = time( NULL );
    iFuseConn->pendingCnt++;
    UNLOCK_STRUCT( *iFuseConn );

    /* wait for iFuseConn to be unlocked */
    LOCK( iFuseConn->inuseLock );

    LOCK_STRUCT( *iFuseConn );
    iFuseConn->inuseCnt++;
    iFuseConn->pendingCnt--;

    /* move unlock to caller site */
    /* UNLOCK (ConnLock); */
    return 0;
}
void fl_removeFromConcurrentList2(fl_concurrentList_t *l, void *v) {
	LOCK_STRUCT(*l);
	fl_listRemove2(l->list, v);
	UNLOCK_STRUCT(*l);

}
Exemple #22
0
void removeFromConcurrentList(concurrentList_t *l, ListNode *v) {	LOCK_STRUCT(*l);
listRemoveNoRegion(l->list, v);
UNLOCK_STRUCT(*l);
}
Exemple #23
0
void removeFromConcurrentList2(concurrentList_t *l, void *v) {
	LOCK_STRUCT(*l);
	listRemoveNoRegion2(l->list, v);
	UNLOCK_STRUCT(*l);

}
Exemple #24
0
/*#define FUSE_DEBUG 0*/
void addToConcurrentList(concurrentList_t *l, void *v) {
	LOCK_STRUCT(*l);
	listAppendNoRegion(l->list, v);
	UNLOCK_STRUCT(*l);
}
Exemple #25
0
int ifuseFileCacheRead( fileCache_t *fileCache, char *buf, size_t size, off_t offset ) {
    LOCK_STRUCT( *fileCache );
    int status = _ifuseFileCacheRead( fileCache, buf, size, offset );
    UNLOCK_STRUCT( *fileCache );
    return status;
}
Exemple #26
0
int iFuseFileCacheLseek( fileCache_t *fileCache, off_t offset ) {
    LOCK_STRUCT( *fileCache );
    int status = _iFuseFileCacheLseek( fileCache, offset );
    UNLOCK_STRUCT( *fileCache );
    return status;
}
Exemple #27
0
int ifuseFileCacheSwapOut( fileCache_t *fileCache ) {
    int status = 0;
    if ( fileCache == NULL ) {
        return USER__NULL_INPUT_ERR;
    }
    /* flush local cache file to remote server */

    LOCK_STRUCT( *fileCache );
    /* simply return if no file cache or the file cache hasn't been updated */
    if ( fileCache->state != HAVE_NEWLY_CREATED_CACHE ) {
        UNLOCK_STRUCT( *fileCache );
        return 0;
    }

    /* no need to flush cache file as we are using low-level io */
    /* status = fsync (fileCache->iFd);
    if (status < 0) {
    	status = (errno ? (-1 * errno) : -1);
    	rodsLog (LOG_ERROR,
    			"ifuseFlush: flush of cache file for %s error, status = %d",
    			fileCache->localPath, status);
    	return -EBADF;
    }*/

    struct stat stbuf;
    int error_code = stat( fileCache->fileCachePath, &stbuf );
    if ( error_code != 0 ) {
        rodsLog( LOG_ERROR, "stat failed in _iFuseFileCacheFlush with status %d", error_code );
    }
    /* put cache file to server */
    iFuseConn_t *conn = getAndUseConnByPath( fileCache->localPath, &status );
    RECONNECT_IF_NECESSARY( status, conn, ifusePut( conn->conn, fileCache->objPath, fileCache->fileCachePath, fileCache->mode, stbuf.st_size ) );
    unuseIFuseConn( conn );

    if ( status < 0 ) {
        rodsLog( LOG_ERROR,
                 "ifuseClose: ifusePut of %s error, status = %d",
                 fileCache->localPath, status );
        status = -EBADF;
        UNLOCK_STRUCT( *fileCache );
        return status;
    }

    int objFd = status;

    /* close cache file */
    status = close( fileCache->iFd );
    if ( status < 0 ) {
        status = ( errno ? ( -1 * errno ) : -1 );
        rodsLog( LOG_ERROR,
                 "ifuseClose: close of cache file for %s error, status = %d",
                 fileCache->localPath, status );
        UNLOCK_STRUCT( *fileCache );
        return -EBADF;
    }
    fileCache->iFd = objFd;
    fileCache->state = NO_FILE_CACHE;

    return status;

}
Exemple #28
0
int listSize(concurrentList_t *l) {
	LOCK_STRUCT(*l);
	int s = _listSize(l);
	UNLOCK_STRUCT(*l);
	return s;
}
Exemple #29
0
void ifuseDisconnect( iFuseConn_t *tmpIFuseConn ) {
    LOCK_STRUCT( *tmpIFuseConn );
    _ifuseDisconnect( tmpIFuseConn );
    UNLOCK_STRUCT( *tmpIFuseConn );
}
Exemple #30
0
void
connManager() {
    time_t curTime;
    iFuseConn_t *tmpIFuseConn;
    ListNode *node;
    List *TimeOutList = newListNoRegion();

    while ( 1 ) {
        curTime = time( NULL );

        /* exceed high water mark for number of connection ? */
        if ( listSize( ConnectedConn ) > HIGH_NUM_CONN ) {

            LOCK_STRUCT( *ConnectedConn );
            int disconnTarget = _listSize( ConnectedConn ) - HIGH_NUM_CONN;
            node = ConnectedConn->list->head;
            while ( node != NULL ) {
                tmpIFuseConn = ( iFuseConn_t * ) node->value;
                if ( tmpIFuseConn->inuseCnt == 0 && tmpIFuseConn->pendingCnt == 0 && curTime - tmpIFuseConn->actTime > IFUSE_CONN_TIMEOUT ) {
                    listAppendNoRegion( TimeOutList, tmpIFuseConn );

                }
                node = node->next;            
            }
            UNLOCK_STRUCT( *ConnectedConn );

            node = TimeOutList->head;
            int disconned = 0;
            while ( node != NULL && disconned < disconnTarget ) {
                tmpIFuseConn = ( iFuseConn_t * ) node->value;
                LOCK_STRUCT( *tmpIFuseConn );
                if ( tmpIFuseConn->inuseCnt == 0 && tmpIFuseConn->pendingCnt == 0 && curTime - tmpIFuseConn->actTime > IFUSE_CONN_TIMEOUT ) {
                    removeFromConcurrentList2( FreeConn, tmpIFuseConn );
                    removeFromConcurrentList2( ConnectedConn, tmpIFuseConn );
                    if ( tmpIFuseConn->status == 0 ) { /* no struct is referring to it, we can unlock it and free it */
                        UNLOCK_STRUCT( *tmpIFuseConn );
                        /* rodsLog(LOG_ERROR, "[FREE IFUSE CONN] %s:%d %p", __FILE__, __LINE__, tmpIFuseConn); */
                        _freeIFuseConn( tmpIFuseConn );
                    }
                    else {   /* set to timed out */
                        _ifuseDisconnect( tmpIFuseConn );
                        UNLOCK_STRUCT( *tmpIFuseConn );
                    }
                    disconned ++;
                }
                else {
                    UNLOCK_STRUCT( *tmpIFuseConn );
                }
                node = node->next;
            }
            clearListNoRegion( TimeOutList );
        }

        while ( listSize( ConnectedConn ) <= MAX_NUM_CONN || listSize( FreeConn ) != 0 ) {
            /* signal one in the wait queue */
            connReqWait_t *myConnReqWait = ( connReqWait_t * ) removeFirstElementOfConcurrentList( ConnReqWaitQue );
            /* if there is no conn req left, exit loop */
            if ( myConnReqWait == NULL ) {
                break;
            }
            myConnReqWait->state = 1;
            notifyTimeoutWait( &myConnReqWait->mutex, &myConnReqWait->cond );
        }
#if 0
        rodsSleep( CONN_MANAGER_SLEEP_TIME, 0 );
#else
        timeoutWait( &ConnManagerLock, &ConnManagerCond, CONN_MANAGER_SLEEP_TIME );
#endif


    }
    deleteListNoRegion( TimeOutList );
}