/** * Abiquo community edition * cloud management application for hybrid clouds * Copyright (C) 2008-2010 - Abiquo Holdings S.L. * * This application 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 under * version 3 of the License * * This software 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 v.3 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.abiquo.am.data; import static java.lang.System.getProperty; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.apache.commons.lang.StringUtils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import com.abiquo.appliancemanager.transport.TemplateStateDto; import com.abiquo.appliancemanager.transport.TemplateStatusEnumType; public class AMRedisDao { // TODO move to AMConfig public static final String REDIS_HOS = getProperty("abiquo.redis.host", "localhost"); public static final Integer REDIS_PORT = Integer.parseInt(getProperty("abiquo.redis.port", "6379")); private static JedisPoolConfig REDIS_POOL_CONF; /** Thread-safe Redis clients pool. */ public static JedisPool REDIS_POOL; static { initPool(); } public static void initPool() { REDIS_POOL_CONF = new JedisPoolConfig(); REDIS_POOL_CONF.setTestOnBorrow(true); // REDIS_POOL_CONF.setMaxIdle(4); // REDIS_POOL_CONF.setMaxActive(4); REDIS_POOL_CONF.setMaxWait(5000); // ms to obtain a redis client REDIS_POOL = new JedisPool(REDIS_POOL_CONF, REDIS_HOS, REDIS_PORT); } /** ########## ########## */ private final static String EREPOS_KEYS = "erepoKeys:"; private final static String EREPO = "erepo:"; private final static String TEMPLATE = "ovf:"; private final static String STATE = "state"; private final static String PROGRESS = "progress"; private final static String ERROR = "error"; /** ########## ########## */ private final Jedis redis; private AMRedisDao() { redis = REDIS_POOL.getResource(); } public static synchronized AMRedisDao getDao() { return new AMRedisDao(); } public static void returnDao(final AMRedisDao dao) { REDIS_POOL.returnResource(dao.redis); } /** ########## SET ########## */ public void init(final String erId, final List<TemplateStateDto> states) { for (String ovfKey : getOvfKeys(erId)) { redis.srem(key(erId), ovfKey); redis.del(ovfKey); } for (TemplateStateDto state : states) { if (state.getStatus() == TemplateStatusEnumType.ERROR) { setError(erId, state.getOvfId(), state.getErrorCause()); } else { setState(erId, state.getOvfId(), state.getStatus()); } } } /** * @retrurn true if the progress is update (false if remain the same) */ public boolean setDownloadProgress(final String erId, final String ovfId, final Integer progress) { checkKeyIndex(erId, ovfId); final String currentSt = redis.hget(key(erId, ovfId), PROGRESS); final Integer current = StringUtils.isEmpty(currentSt) ? 0 : Integer.parseInt(currentSt); if (current == 0) { redis.hset(key(erId, ovfId), STATE, TemplateStatusEnumType.DOWNLOADING.name()); } if (current != progress) { redis.hset(key(erId, ovfId), PROGRESS, String.valueOf(progress)); } return current != progress; } public void setState(final String erId, final String ovfId, final TemplateStatusEnumType state) { checkKeyIndex(erId, ovfId); if (state == TemplateStatusEnumType.NOT_DOWNLOAD) { synchronized (this) { redis.srem(key(erId), key(erId, ovfId)); redis.del(key(erId, ovfId)); } } else { redis.hset(key(erId, ovfId), STATE, state.name()); } } /** setState ERROR */ public void setError(final String erId, final String ovfId, final String error) { checkKeyIndex(erId, ovfId); synchronized (this) { redis.hset(key(erId, ovfId), STATE, TemplateStatusEnumType.ERROR.name()); redis.hset(key(erId, ovfId), ERROR, error); } } /** ########## GET ########## */ public Integer getDownloadProgress(final String erId, final String ovfId) { final String current = redis.hget(key(erId, ovfId), PROGRESS); try { return Integer.parseInt(current != null ? current : "0"); } catch (Exception e) { return 0; } } /** return NOT_FOUND */ public TemplateStatusEnumType getStatus(final String erId, final String ovfId) { if (!redis.sismember(key(erId), key(erId, ovfId))) { return TemplateStatusEnumType.NOT_DOWNLOAD; } // if (current == null) // { // redis.srem(key(erId), key(erId, ovfId)); // return TemplateStatusEnumType.NOT_DOWNLOAD; // } final String current = redis.hget(key(erId, ovfId), STATE); return TemplateStatusEnumType.valueOf(current); } public String getError(final String erId, final String ovfId) { return redis.hget(key(erId, ovfId), ERROR); } public List<TemplateStateDto> getAll(final String erId) { final List<TemplateStateDto> statusLst = new LinkedList<TemplateStateDto>(); for (String keyOvf : getOvfKeys(erId)) { final List<String> fields = redis.hmget(keyOvf, STATE, PROGRESS, ERROR); statusLst.add(createOVFStatus(keyOvf, fields)); } return statusLst; } /** ########## ########## */ private static TemplateStateDto createOVFStatus(final String keyOvf, final List<String> fields) { TemplateStateDto status = new TemplateStateDto(); status.setOvfId(ovfId(keyOvf)); final String st = fields.get(0); final String progress = fields.get(1); final String error = fields.get(2); status.setStatus(st != null ? TemplateStatusEnumType.valueOf(st) : TemplateStatusEnumType.NOT_DOWNLOAD); status.setDownloadingProgress(StringUtils.isEmpty(progress) ? null : Double .valueOf(progress)); status.setErrorCause(StringUtils.isEmpty(error) ? null : error); return status; } /** ########## ########## */ private void checkKeyIndex(final String erId, final String ovfId) { redis.sadd(key(erId), key(erId, ovfId)); } private Set<String> getOvfKeys(final String erId) { return redis.smembers(key(erId)); } private static String key(final String erId) { return EREPOS_KEYS + erId; } private static String key(final String erId, final String ovfId) { return EREPO + erId + ':' + TEMPLATE + ovfId; } private static String ovfId(final String keyOovfId) { return keyOovfId.substring(keyOovfId.indexOf("http://")); } }