/* Function   : killStuckUploadingTransferers
 * Description: kills uploading transferer processes, the working time of which
 *              exceeds MAX_TRANSFER_LIFETIME seconds, and clears all the data,
 *				regarding them, i.e. pids and last times of creation
 */
void 
ReplicatorStateMachine::killStuckUploadingTransferers( time_t currentTime )
{
	m_uploadTransfererMetadataList.Rewind( );

	ProcessMetadata* uploadTransfererMetadata = NULL;    

	// killing stuck uploading 'condor_transferers'
    while( m_uploadTransfererMetadataList.Next( uploadTransfererMetadata ) ) {
        if( uploadTransfererMetadata->isValid( ) &&
			currentTime - uploadTransfererMetadata->m_lastTimeCreated >
              m_maxTransfererLifeTime ) {
            dprintf( D_FULLDEBUG, 
					"ReplicatorStateMachine::killStuckUploadingTransferers "
                    "killing uploading condor_transferer pid = %d\n",
                    uploadTransfererMetadata->m_pid );
			// sending SIGKILL signal, wrapped in daemon core function for
        	// portability
			if( !daemonCore->Send_Signal( 
				uploadTransfererMetadata->m_pid, SIGKILL ) ) {
				dprintf( D_ALWAYS, 
						 "ReplicatorStateMachine::killStuckUploadingTransferers"
						 " kill signal failed, reason = %s\n", strerror(errno));
			}
			// when the process is killed, it could have not yet erased its
        	// temporary files, this is why we ensure it by erasing it in killer
        	// function	
			MyString extension( uploadTransfererMetadata->m_pid );
            // the .up ending is needed in order not to confuse between
            // upload and download processes temporary files
            extension += ".";
            extension += UPLOADING_TEMPORARY_FILES_EXTENSION;

            FilesOperations::safeUnlinkFile( m_versionFilePath.Value( ),
                                             extension.Value( ) );
            FilesOperations::safeUnlinkFile( m_stateFilePath.Value( ),
                                             extension.Value( ) );
			delete uploadTransfererMetadata;
			m_uploadTransfererMetadataList.DeleteCurrent( );
		}
    }
	m_uploadTransfererMetadataList.Rewind( );
}
// cancels all the data, considering transferers, both uploading and downloading
// such as pids and last times of creation, and sends SIGKILL signals to the
// stuck processes
void
AbstractReplicatorStateMachine::killTransferers()
{
    if( m_downloadTransfererMetadata.isValid() ) {
       /* Beware of sending SIGKILL with download transferer's pid = -1, because
        * according to POSIX it will be sent to every process that the
        * current process is able to sent signals to
        */
        dprintf( D_FULLDEBUG,
            "AbstractReplicatorStateMachine::killTransferers "
            "killing downloading condor_transferer pid = %d\n",
                   m_downloadTransfererMetadata.m_pid );
        //kill( m_downloadTransfererMetadata.m_pid, SIGKILL );
        daemonCore->Send_Signal( m_downloadTransfererMetadata.m_pid, SIGKILL );
		// when the process is killed, it could have not yet erased its
        // temporary files, this is why we ensure it by erasing it in killer
        // function
        MyString extension( m_downloadTransfererMetadata.m_pid );
        // the .down ending is needed in order not to confuse between upload and
        // download processes temporary files
        extension += ".";
        extension += DOWNLOADING_TEMPORARY_FILES_EXTENSION;

        FilesOperations::safeUnlinkFile( m_versionFilePath.Value( ),
                                         extension.Value( ) );
        FilesOperations::safeUnlinkFile( m_stateFilePath.Value( ),
                                         extension.Value( ) );
		m_downloadTransfererMetadata.set();
    }

	m_uploadTransfererMetadataList.Rewind( );

	ProcessMetadata* uploadTransfererMetadata = NULL;    

    while( m_uploadTransfererMetadataList.Next( uploadTransfererMetadata ) ) {
        if( uploadTransfererMetadata->isValid( ) ) {
            dprintf( D_FULLDEBUG,
                "AbstractReplicatorStateMachine::killTransferers "
                "killing uploading condor_transferer pid = %d\n",
                uploadTransfererMetadata->m_pid );
            //kill( uploadTransfererMetadata->m_pid, SIGKILL );
			daemonCore->Send_Signal( uploadTransfererMetadata->m_pid, SIGKILL );
			
			            // when the process is killed, it could have not yet
			            // erased its
            // temporary files, this is why we ensure it by erasing it in killer
            // function
            MyString extension( uploadTransfererMetadata->m_pid );
            // the .up ending is needed in order not to confuse between
            // upload and download processes temporary files
            extension += ".";
            extension += UPLOADING_TEMPORARY_FILES_EXTENSION;

            FilesOperations::safeUnlinkFile( m_versionFilePath.Value( ),
                                             extension.Value( ) );
            FilesOperations::safeUnlinkFile( m_stateFilePath.Value( ),
                                             extension.Value( ) );
			delete uploadTransfererMetadata;
			// after deletion the iterator is moved to the previous member
			// so advancing the iterator twice and missing one entry does not
			// happen
        	m_uploadTransfererMetadataList.DeleteCurrent( );
		}
    }
	m_uploadTransfererMetadataList.Rewind( );
}