/* * Copyright (c) 2016 EMC Corporation * All Rights Reserved */ package com.emc.vipr.model.sys.backup; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @XmlRootElement(name = "restore_status") public class BackupRestoreStatus { private static final Logger log = LoggerFactory.getLogger(BackupRestoreStatus.class); private static final String KEY_BACKUP_NAME = "backupName"; private static final String KEY_PULL_SIZE = "pullSize"; private static final String KEY_DOWNLOADED_SIZE = "downloadedSize"; private static final String KEY_STATUS = "status"; private static final String KEY_DETAILS_MSG = "details"; private static final String KEY_NODE_COMPLETED= "nodeCompleted"; private static final String KEY_FILE_NAMES= "filenames"; private static final String FILE_NAME_SEPARATOR= ":"; private static final String KEY_VALUE_SEPARATOR= "="; private static final String MAP_ENTRY_SEPARATOR= ":"; private static final String KEY_IS_GEO_ENV= "isGeo"; private String backupName; //key=hostname e.g. vipr1, vipr2 ... //value= the number of bytes to be downloaded on this node private Map<String, Long> sizeToDownload = new HashMap(); //key=hostname e.g. vipr1, vipr2 ... //value= the number of bytes to has been downloaded on this node private Map<String, Long> downloadedSize = new HashMap(); private Status status = Status.READY; private String details = ""; private int nodeCompleted = 0; private boolean isGeo = false; private List<String> backupFileNames = new ArrayList(); public BackupRestoreStatus() { } @XmlElement(name = "backup_name") public String getBackupName() { return this.backupName; } public void setBackupName(String backupName) { this.backupName = backupName; } @XmlElement (name = "status") public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } @XmlElement (name = "details") public String getDetails() { return details; } public void setDetails(String details) { this.details = details; } public void setStatusWithDetails(Status s, String details) { status = s; this.details = details != null ? details : s.getMessage(); } @XmlTransient public int getNodeCompleted() { return nodeCompleted; } public void increaseNodeCompleted() { nodeCompleted++; } @XmlElementWrapper(name = "backup_file_names") public List<String> getBackupFileNames() { return backupFileNames; } public void setBackupFileNames(List<String> backupFileNames) { this.backupFileNames = backupFileNames; } @XmlElement (name = "is_geo") public boolean isGeo() { return isGeo; } public void setGeo(boolean isGeo) { this.isGeo = isGeo; } @XmlElementWrapper(name = "downloaded_size") public Map<String, Long> getDownloadedSize() { return downloadedSize; } public void setDownloadedSize(Map<String, Long> downloadedSize) { this.downloadedSize = downloadedSize; } public void increaseDownloadedSize(String node, long size) { long s = downloadedSize.get(node) + size; downloadedSize.put(node, s); } @XmlElementWrapper(name = "size_to_download") public Map<String, Long> getSizeToDownload() { return sizeToDownload; } public void setSizeToDownload(Map<String, Long> sizes) { sizeToDownload = sizes; } public boolean isNotSuccess() { return status == Status.DOWNLOAD_FAILED || status == Status.RESTORE_FAILED; } /** * The status of pulled backup set */ @XmlType(name = "restore_Status") public enum Status { READY (true, false, "Ready"), DOWNLOADING (true, false, "Downloading"), DOWNLOAD_SUCCESS (false, true, "Download success"), DOWNLOAD_FAILED (false, true, "Download failed"), DOWNLOAD_CANCELLED (false, true, "Download Canceled"), RESTORING(false, false, "Restoring"), RESTORE_FAILED (false, false, "Restore failed"), RESTORE_SUCCESS (false, false, "Restore success"); private boolean cancellable = false; private boolean removeListener = false; private String message = ""; Status(boolean cancellable, boolean removeListener, String msg) { this.cancellable = cancellable; this.removeListener = removeListener; message = msg; } public boolean canBeCanceled() { return cancellable; } public boolean removeListener() { return removeListener; } @XmlTransient public String getMessage () { return message; } } //convert to Map to persist to ZK public Map<String, String> toMap() { Map<String, String> map = new HashMap(); map.put(KEY_BACKUP_NAME, backupName); String str = toString(sizeToDownload); map.put(KEY_PULL_SIZE, str); str = toString(downloadedSize); map.put(KEY_DOWNLOADED_SIZE, str); map.put(KEY_STATUS, status.name()); map.put(KEY_DETAILS_MSG, details); map.put(KEY_NODE_COMPLETED, Integer.toString(nodeCompleted)); map.put(KEY_IS_GEO_ENV, Boolean.toString(isGeo)); String names = String.join(FILE_NAME_SEPARATOR, backupFileNames); map.put(KEY_FILE_NAMES, names); return map; } private String toString(Map<String, Long> map) { StringBuilder builder = new StringBuilder(); for (Map.Entry<String, Long> s : map.entrySet()) { builder.append(MAP_ENTRY_SEPARATOR); builder.append(s.getKey()); builder.append(KEY_VALUE_SEPARATOR); builder.append(s.getValue()); } return builder.toString(); } private Map<String, Long> toMap(String s) { Map<String, Long> map = new HashMap(); if (s.isEmpty()) { return map; } //skip leading MAP_ENTRY_SEPARATOR String str = s.substring(1); String[] entries = str.split(MAP_ENTRY_SEPARATOR); for (String entry : entries) { String[] e = entry.split(KEY_VALUE_SEPARATOR); map.put(e[0], Long.parseLong(e[1])); } return map; } public BackupRestoreStatus(Map<String, String> configs) { update(configs); } private void update(Map<String, String> configs) { for (Map.Entry<String, String> config: configs.entrySet()) { String key = config.getKey(); String value = config.getValue(); switch (key) { case KEY_BACKUP_NAME: backupName = value; break; case KEY_PULL_SIZE: sizeToDownload = toMap(value); break; case KEY_DOWNLOADED_SIZE: downloadedSize = toMap(value); break; case KEY_STATUS: status = Status.valueOf(value); break; case KEY_DETAILS_MSG: details = value; break; case KEY_NODE_COMPLETED: nodeCompleted = Integer.parseInt(value); break; case KEY_FILE_NAMES: String[] names = value.split(FILE_NAME_SEPARATOR); backupFileNames = Arrays.asList(names); break; case KEY_IS_GEO_ENV: isGeo = Boolean.valueOf(value); break; } } } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\nBackupName:") .append(backupName) .append("\nsize to download:") .append(sizeToDownload) .append("\ndownloaded size: ") .append(downloadedSize) .append("\nfilesDownloaded:") .append(backupFileNames) .append("\nnodesCompleted:") .append(nodeCompleted) .append("\nisGeo:") .append(isGeo) .append("\nstatus:") .append(status) .append("\ndetails:") .append(details); return sb.toString(); } }