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;
}
Exemple #2
0
int
dataObjUnlinkS (rsComm_t *rsComm, dataObjInp_t *dataObjUnlinkInp,
dataObjInfo_t *dataObjInfo)
{
    int status;
    unregDataObj_t unregDataObjInp;

    if (dataObjInfo->specColl == NULL) {
	if (dataObjUnlinkInp->oprType == UNREG_OPR && 
	  rsComm->clientUser.authInfo.authFlag != LOCAL_PRIV_USER_AUTH) {
	    ruleExecInfo_t rei;

            initReiWithDataObjInp (&rei, rsComm, dataObjUnlinkInp);
            rei.doi = dataObjInfo;
            rei.status = DO_CHK_PATH_PERM;         /* default */
            applyRule ("acSetChkFilePathPerm", NULL, &rei, NO_SAVE_REI);
            if (rei.status != NO_CHK_PATH_PERM) {
                char *outVaultPath;
                rodsServerHost_t *rodsServerHost;
	        status = resolveHostByRescInfo (dataObjInfo->rescInfo, 
	          &rodsServerHost);
	        if (status < 0) return status;
	        /* unregistering but not an admin user */
	        status = matchVaultPath (rsComm, dataObjInfo->filePath, 
	          rodsServerHost, &outVaultPath);
	        if (status != 0) {
		    /* in the vault */
                    rodsLog (LOG_DEBUG,
                      "dataObjUnlinkS: unregistering in vault file %s",
                      dataObjInfo->filePath);
                    return CANT_UNREG_IN_VAULT_FILE;
		}
	    }
#if 0	/* don't need this since we are doing orphan */
	} else if (RescTypeDef[dataObjInfo->rescInfo->rescTypeInx].driverType 
	  == WOS_FILE_TYPE && dataObjUnlinkInp->oprType != UNREG_OPR) {
	    /* WOS_FILE_TYPE, unlink first before unreg because orphan files
	     * cannot be reclaimed */
            status = l3Unlink (rsComm, dataObjInfo);
            if (status < 0) {
                rodsLog (LOG_NOTICE,
                  "dataObjUnlinkS: l3Unlink error for WOS file %s. status = %d",
                  dataObjUnlinkInp->objPath, status);
		return status;
	    }
            unregDataObjInp.dataObjInfo = dataObjInfo;
            unregDataObjInp.condInput = &dataObjUnlinkInp->condInput;
            status = rsUnregDataObj (rsComm, &unregDataObjInp);
            if (status < 0) {
                rodsLog (LOG_NOTICE,
                  "dataObjUnlinkS: rsUnregDataObj error for %s. status = %d",
                  dataObjUnlinkInp->objPath, status);
            }
            return status;
#endif
	}
        unregDataObjInp.dataObjInfo = dataObjInfo;
        unregDataObjInp.condInput = &dataObjUnlinkInp->condInput;
        status = rsUnregDataObj (rsComm, &unregDataObjInp);

        if (status < 0) {
            rodsLog (LOG_NOTICE,
              "dataObjUnlinkS: rsUnregDataObj error for %s. status = %d",
              dataObjUnlinkInp->objPath, status);
	    return status;
        }
    }
    
    if (dataObjUnlinkInp->oprType != UNREG_OPR) {
        status = l3Unlink (rsComm, dataObjInfo);
        if (status < 0) {
	    int myError = getErrno (status);
            rodsLog (LOG_NOTICE,
              "dataObjUnlinkS: l3Unlink error for %s. status = %d",
              dataObjUnlinkInp->objPath, status);
	    /* allow ENOENT to go on and unregister */
	    if (myError != ENOENT && myError != EACCES) {
		char orphanPath[MAX_NAME_LEN];
		int status1 = 0;
                rodsLog (LOG_NOTICE,
                  "dataObjUnlinkS: orphan file %s", dataObjInfo->filePath);
		while (1) { 
		    if (isOrphanPath (dataObjUnlinkInp->objPath) == 
		      NOT_ORPHAN_PATH) {
			/* don't rename orphan path */
		        status1 = rsMkOrphanPath (rsComm, dataObjInfo->objPath,
		          orphanPath);
		        if (status1 < 0) break;
		        /* reg the orphan path */
		        rstrcpy (dataObjInfo->objPath, orphanPath,MAX_NAME_LEN);
		    }
		    status1 = svrRegDataObj (rsComm, dataObjInfo);
		    if (status1 == CAT_NAME_EXISTS_AS_DATAOBJ ||
		      status1 == CATALOG_ALREADY_HAS_ITEM_BY_THAT_NAME) {
			continue;
		    } else if (status1 < 0) {
			rodsLogError (LOG_ERROR, status1,
			  "dataObjUnlinkS: svrRegDataObj of orphan %s error",
			  dataObjInfo->objPath);
		    }
		    break;
		}
	        return (status);
	    } else {
	        status = 0;
	    }
	}
    }

    return (status);
}
Exemple #3
0
int
dataObjUnlinkS( rsComm_t *rsComm, dataObjInp_t *dataObjUnlinkInp,
                dataObjInfo_t *dataObjInfo ) {
    int status = 0;
    unregDataObj_t unregDataObjInp;

    if ( dataObjInfo->specColl == NULL ) {
        if ( dataObjUnlinkInp->oprType            == UNREG_OPR &&
                rsComm->clientUser.authInfo.authFlag != LOCAL_PRIV_USER_AUTH ) {
            ruleExecInfo_t rei;

            initReiWithDataObjInp( &rei, rsComm, dataObjUnlinkInp );
            rei.doi = dataObjInfo;
            rei.status = DO_CHK_PATH_PERM;         /* default */ // JMC - backport 4758

            // make resource properties available as rule session variables
            rei.condInputData = (keyValPair_t *)malloc(sizeof(keyValPair_t));
            memset(rei.condInputData, 0, sizeof(keyValPair_t));
            irods::get_resc_properties_as_kvp(rei.doi->rescHier, rei.condInputData);

            applyRule( "acSetChkFilePathPerm", NULL, &rei, NO_SAVE_REI );
            if ( rei.status != NO_CHK_PATH_PERM ) {
                // =-=-=-=-=-=-=-
                // extract the host location from the resource hierarchy
                std::string location;
                irods::error ret = irods::get_loc_for_hier_string( dataObjInfo->rescHier, location );
                if ( !ret.ok() ) {
                    irods::log( PASSMSG( "dataObjUnlinkS - failed in get_loc_for_hier_string", ret ) );
                    return ret.code();
                }

                rodsHostAddr_t addr;
                rodsServerHost_t *rodsServerHost = 0;

                memset( &addr, 0, sizeof( addr ) );
                rstrcpy( addr.hostAddr, location.c_str(), NAME_LEN );
                int remoteFlag = resolveHost( &addr, &rodsServerHost );
                if ( remoteFlag < 0 ) {
                    // error condition?
                }

                /* unregistering but not an admin user */
                std::string out_path;
                ret = resc_mgr.validate_vault_path( dataObjInfo->filePath, rodsServerHost, out_path );
                if ( !ret.ok() ) {
                    /* in the vault */
                    std::stringstream msg;
                    msg << "unregistering a data object which is in a vault [";
                    msg << dataObjInfo->filePath << "]";
                    irods::log( PASSMSG( msg.str(), ret ) );
                    return CANT_UNREG_IN_VAULT_FILE;
                }
            }
        }

        unregDataObjInp.dataObjInfo = dataObjInfo;
        unregDataObjInp.condInput = &dataObjUnlinkInp->condInput;
        status = rsUnregDataObj( rsComm, &unregDataObjInp );

        if ( status < 0 ) {
            rodsLog( LOG_NOTICE,
                     "dataObjUnlinkS: rsUnregDataObj error for %s. status = %d",
                     dataObjUnlinkInp->objPath, status );
            return status;
        }
    }

    if ( dataObjUnlinkInp->oprType != UNREG_OPR ) {

        // Set the in_pdmo flag
        char* in_pdmo = getValByKey( &dataObjUnlinkInp->condInput, IN_PDMO_KW );
        if ( in_pdmo != NULL ) {
            rstrcpy( dataObjInfo->in_pdmo, in_pdmo, MAX_NAME_LEN );
        }
        else {
            dataObjInfo->in_pdmo[0] = '\0';
        }

        status = l3Unlink( rsComm, dataObjInfo );
        if ( status < 0 ) {
            int myError = getErrno( status );
            rodsLog( LOG_NOTICE,
                     "dataObjUnlinkS: l3Unlink error for %s. status = %d",
                     dataObjUnlinkInp->objPath, status );
            /* allow ENOENT to go on and unregister */
            if ( myError != ENOENT && myError != EACCES ) {
                char orphanPath[MAX_NAME_LEN];
                int status1 = 0;
                rodsLog( LOG_NOTICE,
                         "dataObjUnlinkS: orphan file %s", dataObjInfo->filePath );
                while ( 1 ) {
                    if ( isOrphanPath( dataObjUnlinkInp->objPath ) ==
                            NOT_ORPHAN_PATH ) {
                        /* don't rename orphan path */
                        status1 = rsMkOrphanPath( rsComm, dataObjInfo->objPath,
                                                  orphanPath );
                        if ( status1 < 0 ) {
                            break;
                        }
                        /* reg the orphan path */
                        rstrcpy( dataObjInfo->objPath, orphanPath, MAX_NAME_LEN );
                    }
                    status1 = svrRegDataObj( rsComm, dataObjInfo );
                    if ( status1 == CAT_NAME_EXISTS_AS_DATAOBJ ||
                            status1 == CATALOG_ALREADY_HAS_ITEM_BY_THAT_NAME ) {
                        continue;
                    }
                    else if ( status1 < 0 ) {
                        rodsLogError( LOG_ERROR, status1,
                                      "dataObjUnlinkS: svrRegDataObj of orphan %s error",
                                      dataObjInfo->objPath );
                    }
                    break;
                }
                return status;
            }
            else {
                status = 0;
            }
        }
    }

    return status;
}