/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.ha.dao;
import java.util.Date;
import java.util.List;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.ha.HighAvailabilityManager;
import com.cloud.ha.WorkVO;
import com.cloud.ha.HighAvailabilityManager.Step;
import com.cloud.ha.WorkVO.WorkType;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
@Local(value={HighAvailabilityDao.class})
public class HighAvailabilityDaoImpl extends GenericDaoBase<WorkVO, Long> implements HighAvailabilityDao {
private static final Logger s_logger = Logger.getLogger(HighAvailabilityDaoImpl.class);
private final SearchBuilder<WorkVO> TBASearch;
private final SearchBuilder<WorkVO> PreviousInstanceSearch;
private final SearchBuilder<WorkVO> UntakenMigrationSearch;
private final SearchBuilder<WorkVO> CleanupSearch;
private final SearchBuilder<WorkVO> PreviousWorkSearch;
private final SearchBuilder<WorkVO> TakenWorkSearch;
protected HighAvailabilityDaoImpl() {
super();
CleanupSearch = createSearchBuilder();
CleanupSearch.and("time", CleanupSearch.entity().getTimeToTry(), SearchCriteria.Op.LTEQ);
CleanupSearch.and("step", CleanupSearch.entity().getStep(), SearchCriteria.Op.IN);
CleanupSearch.done();
TBASearch = createSearchBuilder();
TBASearch.and("server", TBASearch.entity().getServerId(), SearchCriteria.Op.NULL);
TBASearch.and("taken", TBASearch.entity().getDateTaken(), SearchCriteria.Op.NULL);
TBASearch.and("time", TBASearch.entity().getTimeToTry(), SearchCriteria.Op.LTEQ);
TBASearch.done();
PreviousInstanceSearch = createSearchBuilder();
PreviousInstanceSearch.and("instance", PreviousInstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
PreviousInstanceSearch.done();
UntakenMigrationSearch = createSearchBuilder();
UntakenMigrationSearch.and("host", UntakenMigrationSearch.entity().getHostId(), SearchCriteria.Op.EQ);
UntakenMigrationSearch.and("type", UntakenMigrationSearch.entity().getWorkType(), SearchCriteria.Op.EQ);
UntakenMigrationSearch.and("server", UntakenMigrationSearch.entity().getServerId(), SearchCriteria.Op.NULL);
UntakenMigrationSearch.and("taken", UntakenMigrationSearch.entity().getDateTaken(), SearchCriteria.Op.NULL);
UntakenMigrationSearch.done();
TakenWorkSearch = createSearchBuilder();
TakenWorkSearch.and("type", TakenWorkSearch.entity().getWorkType(), SearchCriteria.Op.EQ);
TakenWorkSearch.and("server", TakenWorkSearch.entity().getServerId(), SearchCriteria.Op.NNULL);
TakenWorkSearch.and("taken", TakenWorkSearch.entity().getDateTaken(), SearchCriteria.Op.NNULL);
TakenWorkSearch.and("step", TakenWorkSearch.entity().getStep(), SearchCriteria.Op.NIN);
TakenWorkSearch.done();
PreviousWorkSearch = createSearchBuilder();
PreviousWorkSearch.and("instance", PreviousWorkSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
PreviousWorkSearch.and("type", PreviousWorkSearch.entity().getWorkType(), SearchCriteria.Op.EQ);
PreviousWorkSearch.and("taken", PreviousWorkSearch.entity().getDateTaken(), SearchCriteria.Op.NULL);
PreviousWorkSearch.done();
}
@Override
public WorkVO take(final long serverId) {
final Transaction txn = Transaction.currentTxn();
try {
final SearchCriteria sc = TBASearch.create();
sc.setParameters("time", System.currentTimeMillis() >> 10);
final Filter filter = new Filter(WorkVO.class, null, true, 0l, 1l);
txn.start();
final List<WorkVO> vos = lock(sc, filter, true);
if (vos.size() == 0) {
txn.commit();
return null;
}
final WorkVO work = vos.get(0);
work.setServerId(serverId);
work.setDateTaken(new Date());
update(work.getId(), work);
txn.commit();
return work;
} catch (final Throwable e) {
throw new CloudRuntimeException("Unable to execute take", e);
}
}
@Override
public List<WorkVO> findPreviousHA(final long instanceId) {
final SearchCriteria sc = PreviousInstanceSearch.create();
sc.setParameters("instance", instanceId);
return listBy(sc);
}
@Override
public void cleanup(final long time) {
final SearchCriteria sc = CleanupSearch.create();
sc.setParameters("time", time);
sc.setParameters("step", HighAvailabilityManager.Step.Done, HighAvailabilityManager.Step.Cancelled);
delete(sc);
}
@Override
public void deleteMigrationWorkItems(final long hostId, final WorkType type, final long serverId) {
final SearchCriteria sc = UntakenMigrationSearch.create();
sc.setParameters("host", hostId);
sc.setParameters("type", type.toString());
WorkVO work = createForUpdate();
Date date = new Date();
work.setDateTaken(date);
work.setServerId(serverId);
work.setStep(HighAvailabilityManager.Step.Cancelled);
update(work, sc);
}
@Override
public List<WorkVO> findTakenWorkItems(WorkType type) {
SearchCriteria sc = TakenWorkSearch.create();
sc.setParameters("type", type);
sc.setParameters("step", Step.Done, Step.Cancelled, Step.Error);
return listActiveBy(sc);
}
@Override
public boolean delete(long instanceId, WorkType type) {
SearchCriteria sc = PreviousWorkSearch.create();
sc.setParameters("instance", instanceId);
sc.setParameters("type", type);
return delete(sc) > 0;
}
@Override
public boolean hasBeenScheduled(long instanceId, WorkType type) {
SearchCriteria sc = PreviousWorkSearch.create();
sc.setParameters("instance", instanceId);
sc.setParameters("type", type);
return listActiveBy(sc, null).size() > 0;
}
}