#
# Project name: MXCuBE
# https://github.com/mxcube
#
# This file is part of MXCuBE software.
#
# MXCuBE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# MXCuBE 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with MXCuBE. If not, see <http://www.gnu.org/licenses/>.
"""
Redis hardware object acts as a client to Redis DB and saves
graphical objects and queue after closing MXCuBE.
Install redis: sudo pip install redis
Start server on local pc: redis-server &
It is recommended to start redis with mxcube
example xml:
NBNB OBSOLETE there is no longer a beamline_setup
<object class="RedisClient">
<object href="/beamline-setup" role="beamline_setup"/>
<object href="/queue-model" role="queue_model"/>
</object>
"""
import gevent
import jsonpickle
import redis
from mxcubecore import HardwareRepository as HWR
from mxcubecore.BaseHardwareObjects import HardwareObject
__version__ = "2.3."
__category__ = "General"
[docs]class RedisClient(HardwareObject):
def __init__(self, name):
HardwareObject.__init__(self, name)
self.host = None
self.port = None
self.active = None
self.proposal_id = None
self.beamline_name = None
self.redis_client = None
[docs] def init(self):
self.host = self.get_property("host")
if self.host is None:
self.host = "localhost"
self.port = self.get_property("port")
if self.port is None:
self.port = 6379
self.redis_client = redis.StrictRedis(host=self.host, port=self.port, db=0)
try:
if self.redis_client.ping():
self.active = True
except Exception:
self.active = False
if self.active:
self.log.info(
"RedisClient: listening to connections on %s:%d"
% (self.host, self.port)
)
else:
self.log.error(
"RedisClient: Redis server %s:%d is not available"
% (self.host, self.port)
)
try:
self.connect(HWR.beamline.flux, "fluxChanged", self.flux_changed)
except Exception:
self.log.exception("")
self.proposal_id = HWR.beamline.session.get_proposal()
self.beamline_name = HWR.beamline.session.beamline_name
if self.active:
self.init_beamline_setup()
[docs] def save_queue(self):
"""Saves queue in RedisDB"""
if self.active:
gevent.spawn(self.save_queue_task)
[docs] def save_queue_task(self):
"""Queue saving tasks"""
selected_model, queue_list = HWR.beamline.queue_model.get_queue_as_json_list()
self.redis_client.set(
"mxcube:%s:%s:queue_model" % (self.proposal_id, self.beamline_name),
selected_model,
)
self.redis_client.set(
"mxcube:%s:%s:queue_current" % (self.proposal_id, self.beamline_name),
queue_list,
)
self.log.debug("RedisClient: Current queue saved")
[docs] def load_queue(self):
"""Loads queue from redis DB"""
if self.active:
self.active = False
selected_model = None
selected_model = self.redis_client.get(
"mxcube:%s:%s:queue_model" % (self.proposal_id, self.beamline_name)
)
serialized_queue = self.redis_client.get(
"mxcube:%s:%s:queue_current" % (self.proposal_id, self.beamline_name)
)
if selected_model is not None:
HWR.beamline.queue_model.select_model(selected_model)
HWR.beamline.queue_model.load_queue_from_json_list(
eval(serialized_queue),
snapshot=HWR.beamline.sample_view.get_scene_snapshot(),
)
self.active = True
self.log.debug("RedisClient: Queue loaded")
return selected_model
[docs] def save_graphics(self):
"""Saves graphics objects in RedisDB"""
if self.active:
self.log.debug(
"RedisClient: Graphics saved at "
+ "mxcube:%s:%s:graphics" % (self.proposal_id, self.beamline_name)
)
graphic_objects = HWR.beamline.sample_view.dump_shapes()
self.redis_client.set(
"mxcube:%s:%s:graphics" % (self.proposal_id, self.beamline_name),
jsonpickle.encode(graphic_objects),
)
[docs] def load_graphics(self):
"""Loads graphics from RedisDB"""
if self.active:
try:
graphics_objects = self.redis_client.get(
"mxcube:%s:%s:graphics" % (self.proposal_id, self.beamline_name)
)
HWR.beamline.sample_view.load_shapes(
jsonpickle.decode(graphics_objects)
)
self.log.debug("RedisClient: Graphics loaded")
except Exception:
self.log.exception("")
[docs] def save_queue_history_item(self, item):
"""Saves queue history in redisDB"""
if self.active:
self.redis_client.lpush(
"mxcube:%s:%s:queue_history" % (self.proposal_id, self.beamline_name),
str(item),
)
self.log.debug("RedisClient: History queue saved")
[docs] def load_queue_history(self):
"""Loads queue history from redisDB"""
result = []
if self.active:
try:
items = self.redis_client.lrange(
"mxcube:%s:%s:queue_history"
% (self.proposal_id, self.beamline_name),
0,
-1,
)
for item in items:
result.append(eval(item))
except Exception:
self.log.exception("")
return result
[docs] def clear_db(self):
"""Cleans redisDB"""
if self.active:
self.redis_client.flushdb()
def flux_changed(self, value, beam_info, transmission):
self.save_beamline_setup_item("flux", (value, beam_info, transmission))
def init_beamline_setup(self):
try:
self.active = False
flux_value = self.redis_client.get(
"mxcube:%s:%s:flux" % (self.proposal_id, self.beamline_name)
)
self.active = True
except Exception as ex:
self.log.debug("Redis: Exception in reading beamline setup: %s" % str(ex))
def save_beamline_setup_item(self, key, value):
if self.active:
if key == "flux":
self.log.debug("RedisClient: Flux value saved")
self.redis_client.set(
"mxcube:%s:%s:flux" % (self.proposal_id, self.beamline_name),
value[0],
)