Example #1
0
 def __init__(self, socket, message_data, *args, **kwargs):
     self.socket = socket
     self.message_data = message_data
     threading.Thread.__init__(self, *args, **kwargs)
     # a flag to notify the thread that it should finish up and exit
     self.kill_received = False
     self.reporter = StateReporter()
Example #2
0
class Listener(threading.Thread):
    def __init__(self, socket, message_data, *args, **kwargs):
        self.socket = socket
        self.message_data = message_data
        threading.Thread.__init__(self, *args, **kwargs)
        # a flag to notify the thread that it should finish up and exit
        self.kill_received = False
        self.reporter = StateReporter()

    def reset_grid_data(self):
        logger.debug(
            'Resetting grid data...',
            extra={'subgrid_id': self.reporter.redis_key})
        for k in self.message_data.grid.keys():
            del self.message_data.grid[k]  # try to save memory
        self.message_data.interpolation_ready = False
        self.message_data.pandas = {}

    def _run(self):
        """run the thread"""
        message_data = self.message_data
        socket = self.socket
        while not self.kill_received:
            logger.debug(
                '(a) number of busy workers: %s' %
                self.reporter.get_busy_workers(),
                extra={'subgrid_id': self.reporter.redis_key})
            arr, metadata = recv_array(socket)
            # now it is busy
            self.reporter.set_busy()
            # N.B.: to simulate the wms_busy state uncomment the following
            # line, but do not commit it, never!
            # time.sleep(random.uniform(0.0, 0.5))
            logger.debug(
                '(b) number of busy workers: %s' %
                self.reporter.get_busy_workers(),
                extra={'subgrid_id': self.reporter.redis_key})
            logger.debug(
                'time in seconds wms is considered busy: %s' %
                str(self.reporter.busy_duration),
                extra={'subgrid_id': self.reporter.redis_key})
            if metadata['action'] == 'reset':
                self.reset_grid_data()
            elif metadata['action'] == 'update':
                self.reporter.set_timestep(metadata['sim_time_seconds'])
                logger.debug(
                    'Updating grid data [%s]' % metadata['name'],
                    extra={'subgrid_id': self.reporter.redis_key})
                if 'model' in metadata:
                    restarted = metadata['name'] == 't1' and \
                        metadata['sim_time_seconds'] < 0.1
                    if metadata['model'] != message_data.loaded_model or \
                            restarted:
                        # Since working with 'reset', this part probably never
                        # occur anymore.

                        # New model detected
                        logger.info(
                            'New model detected: %r (old=%r)' % (
                                metadata['model'], message_data.loaded_model),
                            extra={'subgrid_id': self.reporter.redis_key})

                        # Double reset algorithm.
                        message_data.grid = {}
                        message_data.interpolation_ready = False
                        message_data.loaded_model = metadata['model']

                # Update new grid
                if arr.dtype.kind == 'S':
                    # String, for wkt
                    message_data.grid[metadata['name']] = ''.join(arr)
                else:
                    if 'bbox' in metadata:
                        logger.debug("BBOXED update")
                        x0, x1, y0, y1 = metadata['bbox']
                        message_data.grid[metadata['name']][y0:y1, x0:x1] = arr
                    else:
                        # normal case
                        message_data.grid[metadata['name']] = arr.copy()

                # Receive one of the DEPTH_VARS and all DEPTH_VARS are complete
                if (all([v in message_data.grid for v in DEPTH_VARS]) and
                        metadata['name'] in DEPTH_VARS):

                    if 'bbox' in metadata:
                        logger.debug(
                            'Update grids using bbox after receiving '
                            'dps or quad_grid...',
                            extra={'subgrid_id': self.reporter.redis_key})
                        message_data.update_grids_bbox(metadata['bbox'])
                    else:
                        logger.debug(
                            'Update grids after receiving dps or quad_grid...',
                            extra={'subgrid_id': self.reporter.redis_key})
                        message_data.update_grids()
                    logger.debug(
                        'Update grids finished.',
                        extra={'subgrid_id': self.reporter.redis_key})

                # check update indices
                if (all([v in message_data.grid for v in UPDATE_INDICES_VARS])
                        and metadata['name'] in UPDATE_INDICES_VARS):
                    logger.debug(
                        'Update indices...',
                        extra={'subgrid_id': self.reporter.redis_key})
                    message_data.X, message_data.Y, message_data.L = \
                        message_data.calc_indices()
                    logger.debug(
                        'Update indices finished.',
                        extra={'subgrid_id': self.reporter.redis_key})
            elif metadata['action'] == 'update-pandas':
                logger.debug(
                    'Update pandas data [%s]...', metadata['name'],
                    extra={'subgrid_id': self.reporter.redis_key})
                # TODO: in case of weir, delete unused variables.
                message_data.pandas[metadata['name']] = json.loads(
                    metadata['pandas_json'])

            elif metadata['action'] == 'dump':
                output_filename = metadata['output_filename']
                logger.debug(
                    'Dump: checking other threads...',
                    extra={'subgrid_id': self.reporter.redis_key})
                filename_failed = output_filename + '.failed'
                if os.path.exists(filename_failed):
                    os.remove(filename_failed)
                if i_am_the_boss(output_filename):
                    # TODO: with statement
                    nc_dump = NCDump(output_filename, message_data)
                    nc_dump.dump_nc('wkt', 'S1', ('i', ), '-',
                                    list(message_data.grid['wkt']))
                    nc_dump.dump_nc('x0p', 'f8', (), '-')
                    nc_dump.dump_nc('y0p', 'f8', (), '-')
                    nc_dump.dump_nc('x1p', 'f8', (), '-')
                    nc_dump.dump_nc('y1p', 'f8', (), '-')
                    nc_dump.dump_nc('dxp', 'f8', (), '-')
                    nc_dump.dump_nc('dyp', 'f8', (), '-')
                    nc_dump.dump_nc('imax', 'i4', (), '-')
                    nc_dump.dump_nc('jmax', 'i4', (), '-')
                    nc_dump.dump_nc('imaxk', 'i4', ('k', ), '-')  #
                    nc_dump.dump_nc('jmaxk', 'i4', ('k', ), '-')
                    nc_dump.dump_nc('nodm', 'i4', ('nFlowElem2', ), '-')
                    nc_dump.dump_nc('nodn', 'i4', ('nFlowElem2', ), '-')
                    nc_dump.dump_nc('nodk', 'i4', ('nFlowElem2', ), '-')
                    nc_dump.dump_nc('nod_type', 'i4', ('nFlowElem2', ), '-')

                    nc_dump.dump_nc('dsnop', 'f4', (), '-')
                    nc_dump.dump_nc('dps', 'f4', ('x', 'y', ), '-')

                    try:
                        nc_dump.close()
                    except:
                        # I don't know when nc_dump will fail, but if it fails,
                        # it is probably here.
                        with file(filename_failed, 'w') as f:
                            f.write('I failed...')
                    # So others can see we are finished.
                    os.remove(output_filename + '.busy')
            else:
                logger.debug(
                    'Got an unknown message: %r' % metadata,
                    extra={'subgrid_id': self.reporter.redis_key})
            # set this worker to not busy
            self.reporter.set_not_busy()
            self.reporter.handle_busy_flag()

    def run(self):
        """Run the thread fail-safe"""
        while not self.kill_received:
            try:
                self._run()
            except:
                logger.exception(
                    'An unknown exception occured, subgrid_id: %s' %
                    self.reporter.redis_key)
                # Throw away existing data: can be corrupt.
                # you have to restart a model or 'beam to wms'.
                self.reset_grid_data()