def update_replicas_states(replicas, nowait=False, session=None): """ Update File replica information and state. :param replicas: The list of replicas. :param nowait: Nowait parameter for the for_update queries. :param session: The database session in use. """ rse_ids = {} for replica in replicas: if 'rse_id' not in replica: if replica['rse'] not in rse_ids: rse_ids[replica['rse']] = get_rse_id(rse=replica['rse'], session=session) replica['rse_id'] = rse_ids[replica['rse']] query = session.query(models.RSEFileAssociation).filter_by(rse_id=replica['rse_id'], scope=replica['scope'], name=replica['name']) if isinstance(replica['state'], str) or isinstance(replica['state'], unicode): replica['state'] = ReplicaState.from_string(replica['state']) if replica['state'] == ReplicaState.BEING_DELETED: query = query.filter_by(lock_cnt=0) if replica['state'] == ReplicaState.AVAILABLE: rucio.core.lock.successful_transfer(scope=replica['scope'], name=replica['name'], rse_id=replica['rse_id'], nowait=nowait, session=session) if 'path' in replica and replica['path']: rowcount = query.update({'state': replica['state'], 'path': replica['path']}, synchronize_session=False) else: rowcount = query.update({'state': replica['state']}, synchronize_session=False) if not rowcount: raise exception.UnsupportedOperation('State %(state)s for replica %(scope)s:%(name)s cannot be updated' % replica) return True
def __bulk_add_replicas(rse_id, files, account, session=None): """ Bulk add new dids. :param rse_id: the RSE id. :param dids: the list of files. :param account: The account owner. :param session: The database session in use. :returns: True is successful. """ nbfiles, bytes = 0, 0 # Check for the replicas already available condition = or_() for f in files: condition.append(and_(models.RSEFileAssociation.scope == f['scope'], models.RSEFileAssociation.name == f['name'], models.RSEFileAssociation.rse_id == rse_id)) q = session.query(models.RSEFileAssociation.scope, models.RSEFileAssociation.name, models.RSEFileAssociation.rse_id).\ with_hint(models.RSEFileAssociation, text="INDEX(REPLICAS REPLICAS_PK)", dialect_name='oracle').\ filter(condition) available_replicas = [dict([(column, getattr(row, column)) for column in row._fields]) for row in q] for file in files: found = False for available_replica in available_replicas: if file['scope'] == available_replica['scope'] and file['name'] == available_replica['name'] and rse_id == available_replica['rse_id']: found = True break if not found: nbfiles += 1 bytes += file['bytes'] new_replica = models.RSEFileAssociation(rse_id=rse_id, scope=file['scope'], name=file['name'], bytes=file['bytes'], path=file.get('path'), state=ReplicaState.from_string(file.get('state', 'A')), md5=file.get('md5'), adler32=file.get('adler32'), lock_cnt=file.get('lock_cnt', 0), tombstone=file.get('tombstone')) new_replica.save(session=session, flush=False) try: session.flush() return nbfiles, bytes except IntegrityError, e: if match('.*IntegrityError.*ORA-00001: unique constraint .*REPLICAS_PK.*violated.*', e.args[0]) \ or match('.*IntegrityError.*1062.*Duplicate entry.*', e.args[0]) \ or e.args[0] == '(IntegrityError) columns rse_id, scope, name are not unique' \ or match('.*IntegrityError.*duplicate key value violates unique constraint.*', e.args[0]): raise exception.Duplicate("File replica already exists!") raise exception.RucioException(e.args)