Source code for oio.blob.operator
# Copyright (C) 2019 OpenIO SAS, as part of OpenIO SDS
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from oio.common.exceptions import ContentNotFound, OrphanChunk
from oio.common.logger import get_logger
from oio.content.factory import ContentFactory
from oio.rdir.client import RdirClient
[docs]class ChunkOperator(object):
"""
Execute maintenance operations on chunks.
"""
def __init__(self, conf, logger=None):
self.conf = conf
self.logger = logger or get_logger(conf)
self.rdir_client = RdirClient(conf, logger=self.logger)
self.content_factory = ContentFactory(conf, logger=self.logger)
[docs] def rebuild(self, container_id, content_id, chunk_id_or_pos,
rawx_id=None, try_chunk_delete=False,
allow_frozen_container=True, allow_same_rawx=True):
"""
Try to find the chunk in the metadata of the specified object,
then rebuild it.
"""
try:
content = self.content_factory.get(container_id, content_id)
except ContentNotFound:
raise OrphanChunk('Content not found: possible orphan chunk')
chunk_size = 0
chunk_pos = None
if len(chunk_id_or_pos) < 32:
chunk_pos = chunk_id_or_pos
chunk_id = None
metapos = int(chunk_pos.split('.', 1)[0])
chunk_size = content.chunks.filter(metapos=metapos).all()[0].size
else:
if '/' in chunk_id_or_pos:
chunk_id = chunk_id_or_pos.rsplit('/', 1)[-1]
else:
chunk_id = chunk_id_or_pos
chunk = content.chunks.filter(id=chunk_id).one()
if chunk is None:
raise OrphanChunk(
'Chunk not found in content: possible orphan chunk')
elif rawx_id and chunk.host != rawx_id:
raise ValueError('Chunk does not belong to this rawx')
chunk_size = chunk.size
content.rebuild_chunk(
chunk_id, allow_frozen_container=allow_frozen_container,
allow_same_rawx=allow_same_rawx,
chunk_pos=chunk_pos)
if try_chunk_delete:
try:
content.blob_client.chunk_delete(chunk.url)
self.logger.info("Old chunk %s deleted", chunk.url)
except Exception as exc:
self.logger.warn(
'Failed to delete old chunk %s: %s', chunk.url, exc)
# This call does not raise exception if chunk is not referenced
if chunk_id is not None:
try:
self.rdir_client.chunk_delete(
chunk.host, container_id, content_id, chunk_id)
except Exception as exc:
self.logger.warn(
'Failed to delete chunk entry (%s) from the rdir (%s): %s',
chunk_id, chunk.host, exc)
return chunk_size