/** * 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.server.core.task; import static com.abiquo.model.redis.RedisEntityUtils.getEntityKey; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; import com.abiquo.model.redis.KeyMaker; import com.abiquo.model.redis.RedisDAOBase; import com.abiquo.model.redis.RedisEntityUtils; import com.abiquo.server.core.task.enums.TaskOwnerType; import com.abiquo.server.core.task.enums.TaskState; import com.abiquo.server.core.task.enums.TaskType; /** * This base class provides Redis-persistence logic for {@link Task} entity. <h3>Instance to persist * </h3> * * <pre> * task.ownerId = A * task.taskId = 0 * task.userId = user0 * task.type = DEPLOY * task.state = STARTED * task.timestamp = 123456789 * task.jobs = [Job0, Job1] * * <pre> * <h3>Redis structure</h3> * * <pre> * HMSET Task:0 "ownerId" "A" "taskId" "0" "userId" "user0" "type" "DEPLOY" "state" "STARTED" "timestamp" "12346789" "jobs" "Task:0:jobs" * RPUSH Task:0:jobs Jobs:0 * RPUSH Task:0:jobs Jobs:1 * LPUSH Owner:VirtualMachine:A Task:0 * * <pre> * @author eruiz@abiquo.com */ @Component public class TaskDAO extends RedisDAOBase<Task> { protected final KeyMaker keyMaker = new KeyMaker(Task.class); public Task findById(final String taskId, Jedis jedis) { return find(getEntityKey(Task.class, taskId), jedis); } public List<Task> findByOwnerId(final TaskOwnerType type, final String ownerId, Jedis jedis) { List<Task> tasks = new ArrayList<Task>(); String ownerKey = getOwnerTaskEntityKey(type, ownerId); for (String taskKey : jedis.lrange(ownerKey, 0, -1)) { Task task = find(taskKey, jedis); if (task != null) { tasks.add(task); } } return tasks; } protected Task find(final String taskKey, Jedis jedis) { Map<String, String> hashed = jedis.hgetAll(taskKey); if (hashed.isEmpty()) { return null; } Task task = new Task(); task.setOwnerId(hashed.get("ownerId")); task.setTaskId(hashed.get("taskId")); task.setUserId(hashed.get("userId")); task.setType(TaskType.valueOf(hashed.get("type"))); task.setState(TaskState.valueOf(hashed.get("state"))); task.setTimestamp(Long.parseLong(hashed.get("timestamp"))); return task; } @Override public void delete(Task task, Transaction transaction) { // Build keys String taskJobsKey = getTaskJobsEntityKey(task.getIdAsString()); String ownerTaskKey = getOwnerTaskEntityKey(task); // Delete transaction.del(task.getEntityKey()); transaction.del(taskJobsKey); // Remove task from Owner index transaction.lrem(ownerTaskKey, 0, task.getEntityKey()); } @Override public void save(Task task, Transaction transaction) { // Clear to persist delete(task, transaction); // Hash plain fields Map<String, String> hashed = new HashMap<String, String>(); hashed.put("ownerId", task.getOwnerId()); hashed.put("taskId", task.getTaskId()); hashed.put("userId", task.getUserId()); hashed.put("type", task.getType().name()); hashed.put("state", task.getState().name()); hashed.put("timestamp", String.valueOf(RedisEntityUtils.getUnixtime())); // Hash job collection String taskJobsKey = getTaskJobsEntityKey(task.getIdAsString()); hashed.put("jobs", taskJobsKey); // Persist transaction.hmset(task.getEntityKey(), hashed); for (Job job : task.getJobs()) { transaction.rpush(taskJobsKey, job.getEntityKey()); } // Add task to Owner index transaction.lpush(getOwnerTaskEntityKey(task), task.getEntityKey()); } public String getTaskJobsEntityKey(final String taskId) { return keyMaker.make(taskId, "jobs"); } protected String getOwnerTaskEntityKey(final Task task) { return getOwnerTaskEntityKey(task.getType().getOwnerType(), task.getOwnerId()); } protected String getOwnerTaskEntityKey(final TaskOwnerType type, final String ownerId) { return String.format("Owner:%s:%s", type.getName(), ownerId); } }