package org.ovirt.engine.core.dao.gluster; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.inject.Named; import javax.inject.Singleton; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.common.businessentities.gluster.BrickDetails; import org.ovirt.engine.core.common.businessentities.gluster.BrickProperties; import org.ovirt.engine.core.common.businessentities.gluster.GlusterBrickEntity; import org.ovirt.engine.core.common.businessentities.gluster.GlusterStatus; import org.ovirt.engine.core.common.utils.EnumUtils; import org.ovirt.engine.core.common.utils.SizeConverter; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.MapSqlParameterMapper; import org.ovirt.engine.core.dao.MassOperationsGenericDao; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; @Named @Singleton public class GlusterBrickDaoImpl extends MassOperationsGenericDao<GlusterBrickEntity, Guid> implements GlusterBrickDao { private static final RowMapper<GlusterBrickEntity> brickRowMapper = (rs, rowNum) -> { GlusterBrickEntity brick = new GlusterBrickEntity(); brick.setId(getGuidDefaultEmpty(rs, "id")); brick.setVolumeId(getGuidDefaultEmpty(rs, "volume_id")); brick.setVolumeName(rs.getString("volume_name")); Guid serverId = getGuidDefaultEmpty(rs, "server_id"); brick.setServerId(serverId); brick.setServerName(rs.getString("vds_name")); brick.setBrickDirectory(rs.getString("brick_dir")); brick.setBrickOrder(rs.getInt("brick_order")); brick.setStatus(GlusterStatus.valueOf(rs.getString("status"))); brick.getAsyncTask().setTaskId(getGuid(rs, "task_id")); brick.setNetworkId(getGuid(rs, "network_id")); brick.setNetworkAddress(rs.getString("interface_address")); brick.setUnSyncedEntries( (rs.getObject("unsynced_entries") != null) ? rs.getInt("unsynced_entries") : null); brick.setUnSyncedEntriesTrend(asIntList((String) rs.getObject("unsynced_entries_history"))); brick.setIsArbiter(rs.getBoolean("is_arbiter")); return brick; }; private static final RowMapper<BrickProperties> brickPropertiesRowMappeer = (rs, rowNum) -> { BrickProperties brickProperties = new BrickProperties(); brickProperties.setTotalSize(rs.getDouble("total_space") / SizeConverter.BYTES_IN_MB); brickProperties.setFreeSize(rs.getDouble("free_space") / SizeConverter.BYTES_IN_MB); return brickProperties; }; public GlusterBrickDaoImpl() { super("GlusterBrick"); setProcedureNameForGet("GetGlusterBrickById"); setProcedureNameForRemove("DeleteGlusterVolumeBrick"); } @Override public void save(GlusterBrickEntity brick) { getCallsHandler().executeModification("InsertGlusterVolumeBrick", createBrickParams(brick)); } @Override public void removeBrick(Guid brickId) { getCallsHandler().executeModification("DeleteGlusterVolumeBrick", getCustomMapSqlParameterSource().addValue("id", brickId)); } @Override public void removeAll(Collection<Guid> ids) { getCallsHandler().executeModification("DeleteGlusterVolumeBricks", getCustomMapSqlParameterSource().addValue("ids", StringUtils.join(ids, ','))); } @Override public void replaceBrick(GlusterBrickEntity oldBrick, GlusterBrickEntity newBrick) { getCallsHandler().executeModification("UpdateGlusterVolumeBrick", getCustomMapSqlParameterSource().addValue("id", oldBrick.getId()) .addValue("new_id", newBrick.getId()) .addValue("new_server_id", newBrick.getServerId()) .addValue("new_brick_dir", newBrick.getBrickDirectory()) .addValue("new_status", EnumUtils.nameOrNull(newBrick.getStatus())) .addValue("new_network_id", newBrick.getNetworkId()) .addValue("is_arbiter", newBrick.getIsArbiter())); } @Override public void updateBrickStatus(Guid brickId, GlusterStatus status) { getCallsHandler().executeModification("UpdateGlusterVolumeBrickStatus", getCustomMapSqlParameterSource() .addValue("id", brickId) .addValue("status", EnumUtils.nameOrNull(status))); } @Override public void updateBrickStatuses(List<GlusterBrickEntity> bricks) { updateAllInBatch("UpdateGlusterVolumeBrickStatus", bricks, getBatchMapper()); } @Override public void updateBrickProperties(List<GlusterBrickEntity> bricks) { updateAllInBatch("UpdateGlusterVolumeBrickDetails", bricks, getBrickPropertiesMapper()); } @Override public void updateBrickOrder(Guid brickId, int brickOrder) { getCallsHandler().executeModification("UpdateGlusterVolumeBrickOrder", getCustomMapSqlParameterSource() .addValue("id", brickId) .addValue("brick_order", brickOrder)); } @Override public GlusterBrickEntity getById(Guid id) { GlusterBrickEntity brick = getCallsHandler().executeRead( "GetGlusterBrickById", brickRowMapper, createIdParameterMapper(id)); populateBrickDetails(brick); return brick; } @Override public List<GlusterBrickEntity> getBricksOfVolume(Guid volumeId) { List<GlusterBrickEntity> bricks = getCallsHandler().executeReadList( "GetBricksByGlusterVolumeGuid", brickRowMapper, getCustomMapSqlParameterSource().addValue("volume_id", volumeId)); populateBrickDetails(bricks); return bricks; } private void populateBrickDetails(List<GlusterBrickEntity> bricks) { bricks.forEach(this::populateBrickDetails); } private void populateBrickDetails(GlusterBrickEntity brick) { if (brick != null) { BrickProperties brickProperties = fetchBrickProperties(brick.getId()); if (brickProperties != null) { BrickDetails brickDetails = new BrickDetails(); brickDetails.setBrickProperties(brickProperties); brick.setBrickDetails(brickDetails); } } } private BrickProperties fetchBrickProperties(Guid brickId) { return getCallsHandler().executeRead( "GetBrickDetailsByID", brickPropertiesRowMappeer, createBrickIdParams(brickId)); } private MapSqlParameterSource createBrickParams(GlusterBrickEntity brick) { return getCustomMapSqlParameterSource().addValue("id", brick.getId()) .addValue("volume_id", brick.getVolumeId()) .addValue("server_id", brick.getServerId()) .addValue("brick_dir", brick.getBrickDirectory()) .addValue("brick_order", (brick.getBrickOrder() == null) ? Integer.valueOf(0) : brick.getBrickOrder()) .addValue("status", EnumUtils.nameOrNull(brick.getStatus())) .addValue("network_id", brick.getNetworkId()) .addValue("is_arbiter", brick.getIsArbiter()); } private static List<Integer> asIntList(String str) { if (str == null || "".equals(str)) { return Collections.emptyList(); } List<Integer> res = new ArrayList<>(); for (String s : StringUtils.split(str, ",")) { try { res.add(Integer.parseInt(s)); } catch (NumberFormatException e) { // add nothing if malformed } } return res; } @Override public List<GlusterBrickEntity> getGlusterVolumeBricksByServerId(Guid serverId) { List<GlusterBrickEntity> bricks = getCallsHandler().executeReadList( "GetGlusterVolumeBricksByServerGuid", brickRowMapper, getCustomMapSqlParameterSource().addValue("server_id", serverId)); populateBrickDetails(bricks); return bricks; } @Override public GlusterBrickEntity getBrickByServerIdAndDirectory(Guid serverId, String brickDirectory) { return getCallsHandler().executeRead( "GetBrickByServerIdAndDirectory", brickRowMapper, getCustomMapSqlParameterSource() .addValue("server_id", serverId) .addValue("brick_dir", brickDirectory)); } @Override public List<GlusterBrickEntity> getGlusterVolumeBricksByTaskId(Guid taskId) { return getCallsHandler().executeReadList("GetBricksByTaskId", brickRowMapper, getCustomMapSqlParameterSource().addValue("task_id", taskId)); } @Override public List<GlusterBrickEntity> getAllByClusterAndNetworkId(Guid clusterId, Guid networkId) { return getCallsHandler().executeReadList("GetBricksByClusterIdAndNetworkId", brickRowMapper, getCustomMapSqlParameterSource() .addValue("cluster_id", clusterId) .addValue("network_id", networkId)); } @Override protected MapSqlParameterSource createFullParametersMapper(GlusterBrickEntity brick) { return createBrickParams(brick); } @Override protected MapSqlParameterSource createIdParameterMapper(Guid id) { return getCustomMapSqlParameterSource().addValue("id", id); } @Override protected RowMapper<GlusterBrickEntity> createEntityRowMapper() { return brickRowMapper; } @Override public MapSqlParameterMapper<GlusterBrickEntity> getBatchMapper() { return entity -> new MapSqlParameterSource() .addValue("volume_id", entity.getVolumeId()) .addValue("server_id", entity.getServerId()) .addValue("brick_dir", entity.getBrickDirectory()) .addValue("status", entity.getStatus().name()) .addValue("id", entity.getId().toString()) .addValue("brick_order", entity.getBrickOrder()) .addValue("network_id", entity.getNetworkId()) .addValue("task_id", entity.getAsyncTask().getTaskId() != null ? entity.getAsyncTask() .getTaskId() .toString() : "") .addValue("unsynced_entries", entity.getUnSyncedEntries()) .addValue("unsynced_entries_history", StringUtils.join(entity.getUnSyncedEntriesTrend(), ",")) .addValue("is_arbiter", entity.getIsArbiter()); } public MapSqlParameterMapper<GlusterBrickEntity> getBrickPropertiesMapper() { return brick -> createBrickPropertiesParam(brick.getBrickProperties()); } @Override public void updateBrickTask(Guid brickId, Guid taskId) { getCallsHandler().executeModification("UpdateGlusterVolumeBrickAsyncTask", getCustomMapSqlParameterSource(). addValue("id", brickId). addValue("task_id", taskId)); } @Override public void updateBrickTasksInBatch(Collection<GlusterBrickEntity> bricks) { getCallsHandler().executeStoredProcAsBatch("UpdateGlusterVolumeBrickAsyncTask", bricks, getBatchMapper()); } @Override public void updateBrickTaskByHostIdBrickDir(Guid serverId, String brickDir, Guid taskId) { getCallsHandler().executeModification("UpdateGlusterBrickTaskByServerIdBrickDir", getCustomMapSqlParameterSource(). addValue("server_id", serverId). addValue("brick_dir", brickDir). addValue("task_id", taskId)); } @Override public void updateBrickNetworkId(Guid brickId, Guid networkId) { getCallsHandler().executeModification("UpdateGlusterVolumeBrickNetworkId", getCustomMapSqlParameterSource(). addValue("id", brickId). addValue("network_id", networkId)); } @Override public void updateAllBrickTasksByHostIdBrickDirInBatch(Collection<GlusterBrickEntity> bricks) { getCallsHandler().executeStoredProcAsBatch("UpdateGlusterBrickTaskByServerIdBrickDir", bricks, getBatchMapper()); } @Override public void updateBrickProperties(BrickProperties brickProperties) { getCallsHandler().executeModification("UpdateGlusterVolumeBrickDetails", createBrickPropertiesParam(brickProperties)); } @Override public void addBrickProperties(BrickProperties brickProperties) { getCallsHandler().executeModification("InsertGlusterVolumeBrickDetails", createBrickPropertiesParam(brickProperties)); } @Override public void addBrickProperties(List<GlusterBrickEntity> bricks) { updateAllInBatch("InsertGlusterVolumeBrickDetails", bricks, getBrickPropertiesMapper()); } private MapSqlParameterSource createBrickPropertiesParam(BrickProperties brickProperties) { return getCustomMapSqlParameterSource() .addValue("brick_id", brickProperties.getBrickId()) .addValue("total_space", brickProperties.getTotalSize() * SizeConverter.BYTES_IN_MB) .addValue("used_space", (brickProperties.getTotalSize() - brickProperties.getFreeSize()) * SizeConverter.BYTES_IN_MB) .addValue("free_space", brickProperties.getFreeSize() * SizeConverter.BYTES_IN_MB); } private MapSqlParameterSource createBrickIdParams(Guid brickId) { return getCustomMapSqlParameterSource().addValue("brick_id", brickId); } @Override public void updateUnSyncedEntries(List<GlusterBrickEntity> bricks) { getCallsHandler().executeStoredProcAsBatch("UpdateGlusterVolumeBrickUnSyncedEntries", bricks, getBatchMapper()); } }