Пример #1
0
def _validate_mapped_segment_file(filename):
    """Callable used by MappedSegmentInfo, validating a mapped segment file.

    In this initial version, we just check the existence of the file.

    """
    validated = filename is not None and os.path.exists(filename)
    logger.info(LIBMEMMGR_MAPPED_SEGMENT_VALIDATE,
                filename if filename is not None else '<unknown>',
                'ok' if validated else 'failed')
    return validated
Пример #2
0
def _validate_mapped_segment_file(filename):
    """Callable used by MappedSegmentInfo, validating a mapped segment file.

    In this initial version, we just check the existence of the file.

    """
    validated = filename is not None and os.path.exists(filename)
    logger.info(LIBMEMMGR_MAPPED_SEGMENT_VALIDATE,
                filename if filename is not None else '<unknown>',
                'ok' if validated else 'failed')
    return validated
Пример #3
0
        def rmfile(path):
            """Trivial internal helper to remove a specific file.

            Failure of removing these files is not expected but not critical,
            so we only log any failure and move on.

            """
            if os.path.exists(path):
                try:
                    os.unlink(path)
                except Exception as ex:
                    logger.info(LIBMEMMGR_MAPPED_SEGMENT_RMFILE_FAIL, ex)
Пример #4
0
    def __do_load_zone(self, writer, zname, rrclass, dsrc_name, dsrc_info):
        """A short helper for handle_load().

        Try incremental load until the load is completed or any cancel event
        happens.  The number of load items per iteration is arbitrarily chosen,
        and may have to be adjusted or customizable in future.  It returns
        True if the load is completed and False if it's canceled.

        """
        while not writer.load(1000):
            if self.__cmd_canceled(dsrc_info):
                logger.info(LIBMEMMGR_BUILDER_SEGMENT_LOAD_CANCELED,
                            zname, rrclass, dsrc_name, dsrc_info.gen_id)
                writer.cleanup()
                return False
        return True
Пример #5
0
    def _remove(self):
        def rmfile(path):
            """Trivial internal helper to remove a specific file.

            Failure of removing these files is not expected but not critical,
            so we only log any failure and move on.

            """
            if os.path.exists(path):
                try:
                    os.unlink(path)
                except Exception as ex:
                    logger.info(LIBMEMMGR_MAPPED_SEGMENT_RMFILE_FAIL, ex)

        rmfile(self.__map_versions_file)
        for vers in (0, 1):
            mapped_file = '%s.%d' % (self.__mapped_file_base, vers)
            rmfile(mapped_file)
        logger.info(LIBMEMMGR_MAPPED_SEGMENT_REMOVED, self.get_generation_id())
Пример #6
0
 def __reset_segment(self, clist, dsrc_name, rrclass, params):
     try:
         clist.reset_memory_segment(dsrc_name,
                                    ConfigurableClientList.READ_WRITE,
                                    params)
         logger.debug(logger.DBGLVL_TRACE_BASIC,
                      LIBMEMMGR_BUILDER_SEGMENT_RESET, dsrc_name, rrclass)
         return self.__RESET_SEGMENT_OK
     except Exception as ex:
         logger.error(LIBMEMMGR_BUILDER_RESET_SEGMENT_ERROR, dsrc_name,
                      rrclass, ex)
     try:
         clist.reset_memory_segment(dsrc_name, ConfigurableClientList.CREATE,
                                    params)
         logger.info(LIBMEMMGR_BUILDER_SEGMENT_CREATED, dsrc_name, rrclass)
         return self.__RESET_SEGMENT_CREATED
     except Exception as ex:
         logger.error(LIBMEMMGR_BUILDER_SEGMENT_CREATE_ERROR, dsrc_name,
                      rrclass, ex)
     return self.__RESET_SEGMENT_FAILED
Пример #7
0
 def __reset_segment(self, clist, dsrc_name, rrclass, params):
     try:
         clist.reset_memory_segment(dsrc_name,
                                    ConfigurableClientList.READ_WRITE,
                                    params)
         logger.debug(logger.DBGLVL_TRACE_BASIC,
                      LIBMEMMGR_BUILDER_SEGMENT_RESET, dsrc_name, rrclass)
         return self.__RESET_SEGMENT_OK
     except Exception as ex:
         logger.error(LIBMEMMGR_BUILDER_RESET_SEGMENT_ERROR, dsrc_name,
                      rrclass, ex)
     try:
         clist.reset_memory_segment(dsrc_name, ConfigurableClientList.CREATE,
                                    params)
         logger.info(LIBMEMMGR_BUILDER_SEGMENT_CREATED, dsrc_name, rrclass)
         return self.__RESET_SEGMENT_CREATED
     except Exception as ex:
         logger.error(LIBMEMMGR_BUILDER_SEGMENT_CREATE_ERROR, dsrc_name,
                      rrclass, ex)
     return self.__RESET_SEGMENT_FAILED
Пример #8
0
    def _handle_load(self, zone_name, dsrc_info, rrclass, dsrc_name):
        # This method is called when handling the 'load' command. The
        # following tuple is passed:
        #
        # ('load', zone_name, dsrc_info, rrclass, dsrc_name)
        #
        # where:
        #
        #  * zone_name is None or bundy.dns.Name, specifying the zone name
        #    to load. If it's None, it means all zones to be cached in
        #    the specified data source (used for initialization).
        #
        #  * dsrc_info is a DataSrcInfo object corresponding to the
        #    generation ID of the set of data sources for this loading.
        #
        #  * rrclass is an bundy.dns.RRClass object, the RR class of the
        #    data source.
        #
        #  * dsrc_name is a string, specifying a data source name.
        #
        # This is essentially a 'private' method, but allows tests to call it
        # directly; for other purposes shouldn't be called outside of the class.

        clist = dsrc_info.clients_map[rrclass]
        sgmt_info = dsrc_info.segment_info_map[(rrclass, dsrc_name)]
        params = json.dumps(sgmt_info.get_reset_param(SegmentInfo.WRITER))
        result = self.__reset_segment(clist, dsrc_name, rrclass, params)
        if result == self.__RESET_SEGMENT_FAILED:
            self.__send_response(('load-completed', dsrc_info, rrclass,
                                  dsrc_name, False))
            return

        # If we were told to load a single zone but had to create a new
        # segment, we'll need to load all zones, not just this one.
        if result == self.__RESET_SEGMENT_CREATED and zone_name is not None:
            logger.info(LIBMEMMGR_BUILDER_SEGMENT_LOAD_ALL, zone_name, rrclass,
                        dsrc_name)
            zone_name = None
        if zone_name is not None:
            zones = [(None, zone_name)]
        else:
            zones = clist.get_zone_table_accessor(dsrc_name, True)

        errors = 0
        for _, zname in zones:  # note: don't override zone_name here
            # install empty zone initially
            catch_load_error = (zname is None)
            try:
                result, writer = clist.get_cached_zone_writer(zname,
                                                              catch_load_error,
                                                              dsrc_name)
                if result != ConfigurableClientList.CACHE_STATUS_ZONE_SUCCESS:
                    # handle this with other genuine exceptions below
                    raise bundy.datasrc.Error('result=%d' % result)
            except bundy.datasrc.Error as ex:
                logger.error(LIBMEMMGR_BUILDER_GET_ZONE_WRITER_ERROR,
                             zname, dsrc_name, ex)
                errors += 1
                continue

            try:
                error = writer.load()
                if error is not None:
                    logger.error(LIBMEMMGR_BUILDER_ZONE_WRITER_LOAD_1_ERROR,
                                 zname, dsrc_name, error)
                    errors += 1
                    continue
                writer.install()
            except Exception as e:
                logger.error(LIBMEMMGR_BUILDER_ZONE_WRITER_LOAD_2_ERROR,
                             zname, dsrc_name, e)
                errors += 1
                # fall through to cleanup
            writer.cleanup()

        # need to reset the segment so readers can read it (note: memmgr
        # itself doesn't have to keep it open, but there's currently no
        # public API to just clear the segment).  This 'reset' should succeed,
        # so we'll let any exception be propagated.
        clist.reset_memory_segment(dsrc_name,
                                   ConfigurableClientList.READ_ONLY,
                                   params)

        # At this point, we consider the load a failure only if loading a
        # specific zone has failed.
        succeeded = True if (zone_name is None or errors == 0) else False
        self.__send_response(('load-completed', dsrc_info, rrclass, dsrc_name,
                              succeeded))
Пример #9
0
    def _handle_load(self, zone_name, dsrc_info, rrclass, dsrc_name):
        # This method is called when handling the 'load' command. The
        # following tuple is passed:
        #
        # ('load', zone_name, dsrc_info, rrclass, dsrc_name)
        #
        # where:
        #
        #  * zone_name is None or bundy.dns.Name, specifying the zone name
        #    to load. If it's None, it means all zones to be cached in
        #    the specified data source (used for initialization).
        #
        #  * dsrc_info is a DataSrcInfo object corresponding to the
        #    generation ID of the set of data sources for this loading.
        #
        #  * rrclass is an bundy.dns.RRClass object, the RR class of the
        #    data source.
        #
        #  * dsrc_name is a string, specifying a data source name.
        #
        # This is essentially a 'private' method, but allows tests to call it
        # directly; for other purposes shouldn't be called outside of the class.

        clist = dsrc_info.clients_map[rrclass]
        sgmt_info = dsrc_info.segment_info_map[(rrclass, dsrc_name)]
        params = json.dumps(sgmt_info.get_reset_param(SegmentInfo.WRITER))
        result = self.__reset_segment(clist, dsrc_name, rrclass, params)
        if result == self.__RESET_SEGMENT_FAILED:
            self.__send_response(('load-completed', dsrc_info, rrclass,
                                  dsrc_name, False))
            return

        # If we were told to load a single zone but had to create a new
        # segment, we'll need to load all zones, not just this one.
        if result == self.__RESET_SEGMENT_CREATED and zone_name is not None:
            logger.info(LIBMEMMGR_BUILDER_SEGMENT_LOAD_ALL, zone_name, rrclass,
                        dsrc_name)
            zone_name = None
        if zone_name is not None:
            zones = [(None, zone_name)]
        else:
            zones = clist.get_zone_table_accessor(dsrc_name, True)

        errors = 0
        canceled = False
        for _, zname in zones:  # note: don't override zone_name here
            # install empty zone initially
            catch_load_error = (zone_name is None)
            try:
                result, writer = clist.get_cached_zone_writer(zname,
                                                              catch_load_error,
                                                              dsrc_name)
                if result != ConfigurableClientList.CACHE_STATUS_ZONE_SUCCESS:
                    # handle this with other genuine exceptions below
                    raise bundy.datasrc.Error('result=%d' % result)
            except bundy.datasrc.Error as ex:
                logger.error(LIBMEMMGR_BUILDER_GET_ZONE_WRITER_ERROR,
                             zname, dsrc_name, ex)
                errors += 1
                continue

            try:
                try:
                    if not self.__do_load_zone(writer, zname, rrclass,
                                               dsrc_name, dsrc_info):
                        canceled = True
                        break
                except bundy.datasrc.Error as error:
                    logger.error(LIBMEMMGR_BUILDER_ZONE_WRITER_LOAD_1_ERROR,
                                 zname, dsrc_name, error)
                    errors += 1
                    # If this is initial full load, we'll add an empty zone
                    # for failed zones.
                    if catch_load_error:
                        writer.install()
                    continue
                writer.install()
            except Exception as e:
                logger.error(LIBMEMMGR_BUILDER_ZONE_WRITER_LOAD_2_ERROR,
                             zname, dsrc_name, e)
                errors += 1
                # fall through to cleanup
            writer.cleanup()

        # Make sure the writer is destroyed no matter how we reach here
        # befoe resetting the segment; otherwise the temporary resource
        # maintained in the writer could cause a disruption.
        writer = None

        # need to reset the segment so readers can read it (note: memmgr
        # itself doesn't have to keep it open, but there's currently no
        # public API to just clear the segment).  This 'reset' should succeed,
        # so we'll let any exception be propagated.
        clist.reset_memory_segment(dsrc_name,
                                   ConfigurableClientList.READ_ONLY, params)

        # If the load has been canceled, we are not expected to return a
        # response.  We should return after all cleanups are completed.
        if canceled:
            return

        # At this point, we consider the load a failure only if loading a
        # specific zone has failed.
        succeeded = (zone_name is None or errors == 0)
        self.__send_response(('load-completed', dsrc_info, rrclass, dsrc_name,
                              succeeded))