コード例 #1
0
ファイル: rsRmColl.cpp プロジェクト: bpow/irods
int
_rsPhyRmColl( rsComm_t *rsComm, collInp_t *rmCollInp,
              dataObjInfo_t *dataObjInfo, collOprStat_t **collOprStat ) {

    char *tmpValue;
    int status;
    collInp_t openCollInp;
    collEnt_t *collEnt;
    int handleInx;
    dataObjInp_t dataObjInp;
    collInp_t tmpCollInp;
    int rmtrashFlag = 0;
    int savedStatus = 0;
    int fileCntPerStatOut = FILE_CNT_PER_STAT_OUT;
    int entCnt = 0;
    ruleExecInfo_t rei;
    collInfo_t collInfo;

    memset( &openCollInp, 0, sizeof( openCollInp ) );
    rstrcpy( openCollInp.collName, rmCollInp->collName, MAX_NAME_LEN );
    /* cannot query recur because collection is sorted in wrong order */
    openCollInp.flags = 0;
    handleInx = rsOpenCollection( rsComm, &openCollInp );
    if ( handleInx < 0 ) {
        rodsLog( LOG_ERROR,
                 "_rsPhyRmColl: rsOpenCollection of %s error. status = %d",
                 openCollInp.collName, handleInx );
        return handleInx;
    }

    memset( &dataObjInp, 0, sizeof( dataObjInp ) );
    memset( &tmpCollInp, 0, sizeof( tmpCollInp ) );
    /* catch the UNREG_OPR */
    dataObjInp.oprType = tmpCollInp.oprType = rmCollInp->oprType;

    if ( ( tmpValue = getValByKey( &rmCollInp->condInput, AGE_KW ) ) != NULL ) {
        if ( CollHandle[handleInx].rodsObjStat != NULL ) {
            /* when a collection is moved, the modfiyTime of the object in
              * the collectin does not change. So, we'll depend on the
              * modfiyTime of the collection */
            int ageLimit = atoi( tmpValue ) * 60;
            int modifyTime =
                atoi( CollHandle[handleInx].rodsObjStat->modifyTime );
            if ( ( time( 0 ) - modifyTime ) < ageLimit ) {
                rsCloseCollection( rsComm, &handleInx );
                return 0;
            }
        }
        addKeyVal( &dataObjInp.condInput, AGE_KW, tmpValue );
        addKeyVal( &tmpCollInp.condInput, AGE_KW, tmpValue );
    }
    addKeyVal( &dataObjInp.condInput, FORCE_FLAG_KW, "" );
    addKeyVal( &tmpCollInp.condInput, FORCE_FLAG_KW, "" );

    if ( ( tmpValue = getValByKey( &rmCollInp->condInput, AGE_KW ) ) != NULL ) {
        addKeyVal( &dataObjInp.condInput, AGE_KW, tmpValue );
        addKeyVal( &tmpCollInp.condInput, AGE_KW, tmpValue );
    }

    if ( collOprStat != NULL && *collOprStat == NULL ) {
        *collOprStat = ( collOprStat_t* )malloc( sizeof( collOprStat_t ) );
        memset( *collOprStat, 0, sizeof( collOprStat_t ) );
    }



    if ( getValByKey( &rmCollInp->condInput, ADMIN_RMTRASH_KW ) != NULL ) {
        if ( isTrashPath( rmCollInp->collName ) == False ) {
            return SYS_INVALID_FILE_PATH;
        }
        if ( rsComm->clientUser.authInfo.authFlag != LOCAL_PRIV_USER_AUTH ) {
            return CAT_INSUFFICIENT_PRIVILEGE_LEVEL;
        }
        addKeyVal( &tmpCollInp.condInput, ADMIN_RMTRASH_KW, "" );
        addKeyVal( &dataObjInp.condInput, ADMIN_RMTRASH_KW, "" );
        rmtrashFlag = 2;
    }
    else if ( getValByKey( &rmCollInp->condInput, RMTRASH_KW ) != NULL ) {
        if ( isTrashPath( rmCollInp->collName ) == False ) {
            return SYS_INVALID_FILE_PATH;
        }
        addKeyVal( &tmpCollInp.condInput, RMTRASH_KW, "" );
        addKeyVal( &dataObjInp.condInput, RMTRASH_KW, "" );
        rmtrashFlag = 1;
    }
    // =-=-=-=-=-=-=-
    // JMC - backport 4552
    if ( getValByKey( &rmCollInp->condInput, EMPTY_BUNDLE_ONLY_KW ) != NULL ) {
        addKeyVal( &tmpCollInp.condInput, EMPTY_BUNDLE_ONLY_KW, "" );
        addKeyVal( &dataObjInp.condInput, EMPTY_BUNDLE_ONLY_KW, "" );
    }
    // =-=-=-=-=-=-=-
    while ( ( status = rsReadCollection( rsComm, &handleInx, &collEnt ) ) >= 0 ) {
        if ( entCnt == 0 ) {
            entCnt ++;
            /* cannot rm non-empty home collection */
            if ( isHomeColl( rmCollInp->collName ) ) {
                return CANT_RM_NON_EMPTY_HOME_COLL;
            }
        }
        if ( collEnt->objType == DATA_OBJ_T ) {
            snprintf( dataObjInp.objPath, MAX_NAME_LEN, "%s/%s",
                      collEnt->collName, collEnt->dataName );

            status = rsDataObjUnlink( rsComm, &dataObjInp );
            if ( status < 0 ) {
                rodsLog( LOG_ERROR,
                         "_rsPhyRmColl:rsDataObjUnlink failed for %s. stat = %d",
                         dataObjInp.objPath, status );
                /* need to set global error here */
                savedStatus = status;
            }
            else if ( collOprStat != NULL ) {
                ( *collOprStat )->filesCnt ++;
                if ( ( *collOprStat )->filesCnt >= fileCntPerStatOut ) {
                    rstrcpy( ( *collOprStat )->lastObjPath, dataObjInp.objPath,
                             MAX_NAME_LEN );
                    status = svrSendCollOprStat( rsComm, *collOprStat );
                    if ( status < 0 ) {
                        rodsLogError( LOG_ERROR, status,
                                      "_rsPhyRmColl: svrSendCollOprStat failed for %s. status = %d",
                                      rmCollInp->collName, status );
                        *collOprStat = NULL;
                        savedStatus = status;
                        break;
                    }
                    *collOprStat = ( collOprStat_t* )malloc( sizeof( collOprStat_t ) );
                    memset( *collOprStat, 0, sizeof( collOprStat_t ) );
                }
            }
        }
        else if ( collEnt->objType == COLL_OBJ_T ) {
            if ( strcmp( collEnt->collName, rmCollInp->collName ) == 0 ) {
                continue;    /* duplicate */
            }
            rstrcpy( tmpCollInp.collName, collEnt->collName, MAX_NAME_LEN );
            if ( collEnt->specColl.collClass != NO_SPEC_COLL ) {
                if ( strcmp( collEnt->collName, collEnt->specColl.collection )
                        == 0 ) {
                    continue;    /* no mount point */
                }
            }
            initReiWithCollInp( &rei, rsComm, &tmpCollInp, &collInfo );
            status = applyRule( "acPreprocForRmColl", NULL, &rei, NO_SAVE_REI );
            if ( status < 0 ) {
                if ( rei.status < 0 ) {
                    status = rei.status;
                }
                rodsLog( LOG_ERROR,
                         "_rsPhyRmColl:acPreprocForRmColl error for %s,stat=%d",
                         tmpCollInp.collName, status );
                return status;
            }
            status = _rsRmCollRecur( rsComm, &tmpCollInp, collOprStat );
            rei.status = status;
            rei.status = applyRule( "acPostProcForRmColl", NULL, &rei,
                                    NO_SAVE_REI );
            if ( rei.status < 0 ) {
                rodsLog( LOG_ERROR,
                         "_rsRmColl:acPostProcForRmColl error for %s,stat=%d",
                         tmpCollInp.collName, status );
            }
        }
        if ( status < 0 ) {
            savedStatus = status;
        }
        free( collEnt );    /* just free collEnt but not content */
    }
    rsCloseCollection( rsComm, &handleInx );

    if ( ( rmtrashFlag > 0 && ( isTrashHome( rmCollInp->collName ) > 0 || // JMC - backport 4561
                                isOrphanPath( rmCollInp->collName ) == is_ORPHAN_HOME ) )   ||
            ( isBundlePath( rmCollInp->collName ) == True                 &&
              getValByKey( &rmCollInp->condInput, EMPTY_BUNDLE_ONLY_KW ) != NULL ) ) {
        /* don't rm user's home trash coll or orphan collection */
        status = 0;
    }
    else {
        if ( dataObjInfo != NULL && dataObjInfo->specColl != NULL ) {
            if ( dataObjInfo->specColl->collClass == LINKED_COLL ) {
                rstrcpy( rmCollInp->collName, dataObjInfo->objPath,
                         MAX_NAME_LEN );
                status = svrUnregColl( rsComm, rmCollInp );
            }
            else {
                status = l3Rmdir( rsComm, dataObjInfo );
            }
        }
        else {
            status = svrUnregColl( rsComm, rmCollInp );
            if ( status < 0 ) {
                savedStatus = status;
            }
        }
    }
    clearKeyVal( &tmpCollInp.condInput );
    clearKeyVal( &dataObjInp.condInput );

    return savedStatus;
}
コード例 #2
0
static int process_single_obj( rsComm_t *conn, char *parColl, char *fileName,
                               int required_num_replicas, char *grpRescForReplication, char *emailToNotify ) {
    genQueryInp_t genQueryInp;
    int i;
    genQueryOut_t *genQueryOut = NULL;
    sqlResult_t *replNumStruct, *rescStruct, *dataPathStruct, *chkSumStruct;
    char *replNum, *rescName, *dataPathName, *chkSum;
    int t;

    int i1a[10];
    int i1b[10];
    int i2a[10];
    char *condVal[2];
    char v1[200], v2[200];
    char vault_path[2048];

    char *chksum_str = NULL;
    dataObjInp_t myDataObjInp;
    dataObjInfo_t *myDataObjInfo = NULL;
    unregDataObj_t myUnregDataObjInp;
    transferStat_t *transStat = NULL;

    ReplicaCheckStatusStruct *pReplicaStatus;
    int nReplicas;

    char tmpstr[1024];

    int at_least_one_copy_is_good = 0;
    int newN;
    int rn;

    int validKwFlags;
    char *outBadKeyWd;
    msParam_t msGrpRescStr;   /* it can be a single resc name or a paired values. */

    /* fprintf(stderr,"msiAutoReplicateService():process_single_obj()\n");  */

    memset( &genQueryInp, 0, sizeof( genQueryInp_t ) );
    i1a[0] = COL_DATA_REPL_NUM;
    i1b[0] = 0;
    i1a[1] = COL_D_RESC_NAME;
    i1b[1] = 0;
    i1a[2] = COL_D_RESC_GROUP_NAME;
    i1b[2] = 0;
    i1a[3] = COL_D_DATA_PATH;
    i1b[3] = 0;
    i1a[4] = COL_D_DATA_CHECKSUM;
    i1b[4] = 0;
    genQueryInp.selectInp.inx = i1a;
    genQueryInp.selectInp.value = i1b;
    genQueryInp.selectInp.len = 5;

    i2a[0] = COL_COLL_NAME;
    i2a[1] = COL_DATA_NAME;
    genQueryInp.sqlCondInp.inx = i2a;
    sprintf( v1, "='%s'", parColl );
    condVal[0] = v1;
    sprintf( v2, "='%s'", fileName );
    condVal[1] = v2;
    genQueryInp.sqlCondInp.value = condVal;
    genQueryInp.sqlCondInp.len = 2;

    genQueryInp.maxRows = 10;
    genQueryInp.continueInx = 0;
    t = rsGenQuery( conn, &genQueryInp, &genQueryOut );
    if ( t < 0 ) {
        rodsLog( LOG_NOTICE, "msiAutoReplicateService():process_single_obj(): rsGenQuery failed errocode=%d", t );
        if ( t == CAT_NO_ROWS_FOUND ) { /* no data is found */
            return 0;
        }

        return( t );
    }

    if ( genQueryOut->rowCnt <= 0 ) {
        rodsLog( LOG_ERROR, "msiAutoReplicateService():process_single_obj(): return 0 record from calling rsGenQuery() for objid=%s/%s", parColl, fileName );
        return 0;
    }

    nReplicas = genQueryOut->rowCnt;
    pReplicaStatus = ( ReplicaCheckStatusStruct * )calloc( nReplicas, sizeof( ReplicaCheckStatusStruct ) );

    for ( i = 0; i < nReplicas; i++ ) {
        pReplicaStatus[i].registered = 0;
        pReplicaStatus[i].checksum[0] = '\0';
    }

    for ( i = 0; i < genQueryOut->rowCnt; i++ ) {
        replNumStruct = getSqlResultByInx( genQueryOut, COL_DATA_REPL_NUM );
        replNum = &replNumStruct->value[replNumStruct->len * i];
        pReplicaStatus[i].repl_num = atoi( replNum );

        rescStruct = getSqlResultByInx( genQueryOut, COL_D_RESC_NAME );
        rescName = &rescStruct->value[rescStruct->len * i];

        getSqlResultByInx( genQueryOut, COL_D_RESC_GROUP_NAME );

        dataPathStruct = getSqlResultByInx( genQueryOut, COL_D_DATA_PATH );
        dataPathName = &dataPathStruct->value[dataPathStruct->len * i];

        chkSumStruct = getSqlResultByInx( genQueryOut, COL_D_DATA_CHECKSUM );
        chkSum = &chkSumStruct->value[chkSumStruct->len * i];

        vault_path[0] = '\0';
        t = get_resource_path( conn, rescName, vault_path );
        if ( t < 0 ) {
            rodsLog( LOG_NOTICE, "msiAutoReplicateService():process_single_obj():get_resource_path failed, status=%d", t );
            free( pReplicaStatus ); // JMc cppcheck - leak
            return t;
        }

        if ( strncmp( dataPathName, vault_path, strlen( vault_path ) ) != 0 ) {
            /* fprintf(stderr,"AB1-> %s/%s, v=%s, is a registered copy.\n", parColl,fileName, replNum); */
            pReplicaStatus[i].registered = 1;
        }
        else {
            pReplicaStatus[i].registered = 0;
        }

        if ( ( chkSum != NULL ) && ( strlen( chkSum ) > 0 ) ) {
            strcpy( pReplicaStatus[i].checksum, chkSum );
        }
    }
    freeGenQueryOut( &genQueryOut );

    /* check replica status */
    at_least_one_copy_is_good = 0;
    for ( i = 0; i < nReplicas; i++ ) {
        /* check the file existence first */
        memset( &myDataObjInp, 0, sizeof( dataObjInp_t ) );
        snprintf( myDataObjInp.objPath, MAX_NAME_LEN, "%s/%s", parColl, fileName );
        myDataObjInp.openFlags = O_RDONLY;
        sprintf( tmpstr, "%d", pReplicaStatus[i].repl_num );
        addKeyVal( &myDataObjInp.condInput, REPL_NUM_KW, tmpstr );
        rn = pReplicaStatus[i].repl_num;
        t = rsDataObjOpen( conn, &myDataObjInp );
        if ( t < 0 ) {
            /* fprintf(stderr,"%d. %s/%s, %d failed to open and has checksum status=%d\n", i, parColl, fileName, rn, t); */
            if ( t == SYS_OUT_OF_FILE_DESC ) {
                free( pReplicaStatus ); // JMc cppcheck - leak
                return t;
            }
            else {
                pReplicaStatus[i].chksum_status = t;
            }
        }
        else {
            openedDataObjInp_t myDataObjCloseInp;
            memset( &myDataObjCloseInp, 0, sizeof( openedDataObjInp_t ) );
            myDataObjCloseInp.l1descInx = t;
            t = rsDataObjClose( conn, &myDataObjCloseInp );

            chksum_str =  NULL;
            /* compute checksum rsDataObjChksum() */
            memset( &myDataObjInp, 0, sizeof( dataObjInp_t ) );
            sprintf( myDataObjInp.objPath, "%s/%s", parColl, fileName );
            addKeyVal( &myDataObjInp.condInput, FORCE_CHKSUM_KW, "" );
            sprintf( tmpstr, "%d", pReplicaStatus[i].repl_num );
            addKeyVal( &myDataObjInp.condInput, REPL_NUM_KW, tmpstr );
            t = rsDataObjChksum( conn, &myDataObjInp, &chksum_str );
            pReplicaStatus[i].chksum_status = t;     /* t == USER_CHKSUM_MISMATCH means a bad copy */
            /* fprintf(stderr,"%d. %s/%s, %d has checksum status=%d\n", i, parColl, fileName, rn, t); */
            if ( t >= 0 ) {
                if ( strlen( pReplicaStatus[i].checksum ) > 0 ) {
                    if ( strcmp( pReplicaStatus[i].checksum, chksum_str ) != 0 ) { /* mismatch */
                        pReplicaStatus[i].chksum_status = USER_CHKSUM_MISMATCH;
                    }
                    else {
                        at_least_one_copy_is_good = 1;
                    }
                }
                else {
                    at_least_one_copy_is_good = 1;
                }
            }
        }
    }

    /* if there is none good copies left. In some casee, the checksum failed due
       to the fact that the server is down. We leave this case to be taken care of next time. */
    if ( at_least_one_copy_is_good == 0 ) {
        rodsLog( LOG_ERROR, "msiAutoReplicateService():process_single_obj(): Obj='%s/%s': Warning: The system detects that all copies might be corrupted.", parColl, fileName );

#ifndef windows_platform
        if ( ( emailToNotify != NULL ) && ( strlen( emailToNotify ) > 0 ) ) {
            char msg_sub[1024], msg_body[1024];
            strcpy( msg_sub, "iRODS msiAutoReplicateService() error" );
            sprintf( msg_body, "msiAutoReplicateService():process_single_obj(): Obj='%s/%s': at least one storage server is down or all copies are corrupted.",
                     parColl, fileName );
            UnixSendEmail( emailToNotify, msg_sub, msg_body );
        }
#endif

        free( pReplicaStatus ); // JMc cppcheck - leak
        return 0;
    }

    /* since we have at least one copy is good. We delete those bad copies (USER_CHKSUM_MISMATCH). */
    newN = nReplicas;
    for ( i = 0; i < nReplicas; i++ ) {
        memset( &myDataObjInp, 0, sizeof( dataObjInp_t ) );
        sprintf( myDataObjInp.objPath, "%s/%s", parColl, fileName );
        sprintf( tmpstr, "%d", pReplicaStatus[i].repl_num );
        addKeyVal( &myDataObjInp.condInput, REPL_NUM_KW, tmpstr );
        rn = pReplicaStatus[i].repl_num;
        if ( pReplicaStatus[i].registered == 1 ) {
            /* here is the catch. iRODS. */
            int adchksum;
            /* fprintf(stderr,"CD->%s/%s, v=%d, is a registered copy.\n", parColl, fileName, rn); */
            adchksum = ( ( int )( pReplicaStatus[i].chksum_status / 1000 ) ) * 1000;
            if ( ( pReplicaStatus[i].chksum_status == USER_CHKSUM_MISMATCH ) || ( pReplicaStatus[i].chksum_status == UNIX_FILE_OPEN_ERR ) || ( adchksum == UNIX_FILE_OPEN_ERR ) )
                /* USER_CHKSUM_MISMATCH  -> indicates the registered file is changed.
                 * UNIX_FILE_OPEN_ERR --> indicates the registered file is removed by original owner.
                 * -510002 is transformed from UNIX open error.
                 */
            {
                rodsLog( LOG_NOTICE, "msiAutoReplicateService():process_single_obj(): registered copy will be removed: %s, repl=%d", myDataObjInp.objPath, rn );
                t = getDataObjInfo( conn, &myDataObjInp, &myDataObjInfo, NULL, 0 );
                if ( t >= 0 ) {
                    myUnregDataObjInp.dataObjInfo = myDataObjInfo;
                    myUnregDataObjInp.condInput = &myDataObjInp.condInput;
                    t = rsUnregDataObj( conn, &myUnregDataObjInp );
                    if ( t >= 0 ) {
                        newN = newN - 1;
                    }
                    else  {
                        rodsLog( LOG_ERROR, "msiAutoReplicateService():rsUnregDataObj(): failed for %s/%s:%d. erStat=%d", parColl, fileName, rn, t );
                        return t;
                    }
                }
                else {
                    rodsLog( LOG_ERROR, "msiAutoReplicateService():getDataObjInfo(): failed for %s/%s:%d. erStat=%d", parColl, fileName, rn, t );
                    return t;
                }
            }
            else {
                rodsLog( LOG_ERROR, "%s:%d, the registered copy has errored checksum status=%d.", myDataObjInp.objPath, rn, pReplicaStatus[i].chksum_status );
                return t;
            }
        }
        else { /* the data file is in vault */
            if ( pReplicaStatus[i].chksum_status == USER_CHKSUM_MISMATCH ) {
                t = rsDataObjUnlink( conn, &myDataObjInp );
                if ( t >= 0 ) {
                    newN = newN - 1;
                }
                else  {
                    rodsLog( LOG_ERROR, "msiAutoReplicateService():rsDataObjUnlink() for %s:%d failed. errStat=%d", myDataObjInp.objPath, rn, t );
                    free( pReplicaStatus ); // JMc cppcheck - leak
                    return t;
                }
            }
        }
    }

    fillStrInMsParam( &msGrpRescStr, grpRescForReplication );

    /* make necessary copies based on the required number of copies */
    if ( newN < required_num_replicas ) {
        rodsLog( LOG_NOTICE, "msiAutoReplicateService():process_single_obj(): making necessary %d copies as required.", ( required_num_replicas - newN ) );
        for ( i = 0; i < ( required_num_replicas - newN ); i++ ) {
            memset( &myDataObjInp, 0, sizeof( dataObjInp_t ) );
            snprintf( myDataObjInp.objPath, MAX_NAME_LEN, "%s/%s", parColl, fileName );
            /* addKeyVal(&myDataObjInp.condInput, DEST_RESC_NAME_KW, grpRescForReplication); */
            validKwFlags = OBJ_PATH_FLAG | DEST_RESC_NAME_FLAG | NUM_THREADS_FLAG |
                           BACKUP_RESC_NAME_FLAG | RESC_NAME_FLAG | UPDATE_REPL_FLAG |
                           REPL_NUM_FLAG | ALL_FLAG | ADMIN_FLAG | VERIFY_CHKSUM_FLAG |
                           RBUDP_TRANSFER_FLAG | RBUDP_SEND_RATE_FLAG | RBUDP_PACK_SIZE_FLAG;
            t = parseMsKeyValStrForDataObjInp( &msGrpRescStr, &myDataObjInp, DEST_RESC_NAME_KW, validKwFlags, &outBadKeyWd );
            if ( t < 0 ) {
                if ( outBadKeyWd != NULL ) {
                    rodsLog( LOG_ERROR, "msiAutoReplicateService():rsDataObjRepl(): input keyWd - %s error. status = %d", outBadKeyWd, t );
                    free( outBadKeyWd );
                }
                else {
                    rodsLog( LOG_ERROR, "msiAutoReplicateService():rsDataObjRepl(): input msKeyValStr error. status = %d", t );
                }

                free( pReplicaStatus ); // JMc cppcheck - leak
                return t;
            }

            t = rsDataObjRepl( conn, &myDataObjInp, &transStat );
            if ( t < 0 ) {
                rodsLog( LOG_ERROR, "msiAutoReplicateService():rsDataObjRepl() failed for %s/%s:%d into '%s'. err code=%d.", parColl, fileName, rn, grpRescForReplication, t );
                repl_storage_error = 1;
                free( pReplicaStatus ); // JMc cppcheck - leak
                return t;
            }
            if ( transStat != NULL ) {
                free( transStat );
            }
        }
    }

    free( pReplicaStatus ); // JMC cppcheck - leak
    return 0;
}