View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.backup;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.util.ArrayList;
24  import java.util.Calendar;
25  import java.util.Date;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Map.Entry;
30  import java.util.Set;
31  
32  import org.apache.commons.lang.StringUtils;
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  import org.apache.hadoop.hbase.TableName;
36  import org.apache.hadoop.hbase.backup.BackupType;
37  import org.apache.hadoop.hbase.backup.util.BackupClientUtil;
38  import org.apache.hadoop.hbase.classification.InterfaceAudience;
39  import org.apache.hadoop.hbase.classification.InterfaceStability;
40  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
41  import org.apache.hadoop.hbase.protobuf.generated.BackupProtos;
42  import org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupInfo.Builder;
43  import org.apache.hadoop.hbase.protobuf.generated.BackupProtos.TableBackupStatus;
44  
45  
46  /**
47   * An object to encapsulate the information for each backup request
48   */
49  @InterfaceAudience.Private
50  @InterfaceStability.Evolving
51  public class BackupInfo implements Comparable<BackupInfo> {
52    private static final Log LOG = LogFactory.getLog(BackupInfo.class);
53    // backup status flag
54    public static enum BackupState {
55      WAITING, RUNNING, COMPLETE, FAILED, ANY;
56    }
57    // backup phase    
58    public static enum BackupPhase {
59      SNAPSHOTCOPY, INCREMENTAL_COPY, STORE_MANIFEST;
60    }
61  
62    // backup id: a timestamp when we request the backup
63    private String backupId;
64  
65    // backup type, full or incremental
66    private BackupType type;
67  
68    // target root directory for storing the backup files
69    private String targetRootDir;
70  
71    // overall backup state
72    private BackupState state;
73  
74    // overall backup phase
75    private BackupPhase phase;
76  
77    // overall backup failure message
78    private String failedMsg;
79  
80    // backup status map for all tables
81    private Map<TableName, BackupStatus> backupStatusMap;
82  
83    // actual start timestamp of the backup process
84    private long startTs;
85  
86    // actual end timestamp of the backup process, could be fail or complete
87    private long endTs;
88  
89    // the total bytes of incremental logs copied
90    private long totalBytesCopied;
91  
92    // for incremental backup, the location of the backed-up hlogs
93    private String hlogTargetDir = null;
94  
95    // incremental backup file list
96    transient private List<String> incrBackupFileList;
97  
98    // new region server log timestamps for table set after distributed log roll
99    // key - table name, value - map of RegionServer hostname -> last log rolled timestamp
100   transient private HashMap<TableName, HashMap<String, Long>> tableSetTimestampMap;
101 
102   // backup progress in %% (0-100)
103   private int progress;
104   
105   // distributed job id
106   private String jobId;
107   
108   // Number of parallel workers. -1 - system defined
109   private int workers = -1;
110  
111   // Bandwidth per worker in MB per sec. -1 - unlimited
112   private long bandwidth = -1;  
113   
114   public BackupInfo() {
115   }
116 
117   public BackupInfo(String backupId, BackupType type, TableName[] tables, String targetRootDir) {
118     backupStatusMap = new HashMap<TableName, BackupStatus>();
119 
120     this.backupId = backupId;
121     this.type = type;
122     this.targetRootDir = targetRootDir;
123     if(LOG.isDebugEnabled()){
124       LOG.debug("CreateBackupContext: " + tables.length+" "+tables[0] );
125     }
126     this.addTables(tables);
127 
128     if (type == BackupType.INCREMENTAL) {
129       setHlogTargetDir(BackupClientUtil.getLogBackupDir(targetRootDir, backupId));
130     }
131 
132     this.startTs = 0;
133     this.endTs = 0;
134   }
135 
136   public String getJobId() {
137     return jobId;
138   }
139 
140   public void setJobId(String jobId) {
141     this.jobId = jobId;
142   }
143 
144   public int getWorkers() {
145     return workers;
146   }
147 
148   public void setWorkers(int workers) {
149     this.workers = workers;
150   }
151 
152   public long getBandwidth() {
153     return bandwidth;
154   }
155 
156   public void setBandwidth(long bandwidth) {
157     this.bandwidth = bandwidth;
158   }
159 
160   public void setBackupStatusMap(Map<TableName, BackupStatus> backupStatusMap) {
161     this.backupStatusMap = backupStatusMap;
162   }
163 
164   public HashMap<TableName, HashMap<String, Long>> getTableSetTimestampMap() {
165     return tableSetTimestampMap;
166   }
167   
168   public void setTableSetTimestampMap(HashMap<TableName, HashMap<String, Long>> tableSetTimestampMap) {
169     this.tableSetTimestampMap = tableSetTimestampMap;
170   }
171 
172   public String getHlogTargetDir() {
173     return hlogTargetDir;
174   }
175 
176   public void setType(BackupType type) {
177     this.type = type;
178   }
179 
180   public void setTargetRootDir(String targetRootDir) {
181     this.targetRootDir = targetRootDir;
182   }
183 
184   public void setTotalBytesCopied(long totalBytesCopied) {
185     this.totalBytesCopied = totalBytesCopied;
186   }
187 
188   /**
189    * Set progress (0-100%)
190    * @param msg progress value
191    */
192 
193   public void setProgress(int p) {
194     this.progress = p;
195   }
196 
197   /**
198    * Get current progress
199    */
200   public int getProgress() {
201     return progress;
202   }
203 
204   public String getBackupId() {
205     return backupId;
206   }
207 
208   public void setBackupId(String backupId) {
209     this.backupId = backupId;
210   }
211 
212   public BackupStatus getBackupStatus(TableName table) {
213     return this.backupStatusMap.get(table);
214   }
215 
216   public String getFailedMsg() {
217     return failedMsg;
218   }
219 
220   public void setFailedMsg(String failedMsg) {
221     this.failedMsg = failedMsg;
222   }
223 
224   public long getStartTs() {
225     return startTs;
226   }
227 
228   public void setStartTs(long startTs) {
229     this.startTs = startTs;
230   }
231 
232   public long getEndTs() {
233     return endTs;
234   }
235 
236   public void setEndTs(long endTs) {
237     this.endTs = endTs;
238   }
239 
240   public long getTotalBytesCopied() {
241     return totalBytesCopied;
242   }
243 
244   public BackupState getState() {
245     return state;
246   }
247 
248   public void setState(BackupState flag) {
249     this.state = flag;
250   }
251 
252   public BackupPhase getPhase() {
253     return phase;
254   }
255 
256   public void setPhase(BackupPhase phase) {
257     this.phase = phase;
258   }
259 
260   public BackupType getType() {
261     return type;
262   }
263 
264   public void setSnapshotName(TableName table, String snapshotName) {
265     this.backupStatusMap.get(table).setSnapshotName(snapshotName);
266   }
267 
268   public String getSnapshotName(TableName table) {
269     return this.backupStatusMap.get(table).getSnapshotName();
270   }
271 
272   public List<String> getSnapshotNames() {
273     List<String> snapshotNames = new ArrayList<String>();
274     for (BackupStatus backupStatus : this.backupStatusMap.values()) {
275       snapshotNames.add(backupStatus.getSnapshotName());
276     }
277     return snapshotNames;
278   }
279 
280   public Set<TableName> getTables() {
281     return this.backupStatusMap.keySet();
282   }
283 
284   public List<TableName> getTableNames() {
285     return new ArrayList<TableName>(backupStatusMap.keySet());
286   }
287 
288   public void addTables(TableName[] tables) {
289     for (TableName table : tables) {
290       BackupStatus backupStatus = new BackupStatus(table, this.targetRootDir, this.backupId);
291       this.backupStatusMap.put(table, backupStatus);
292     }
293   }
294 
295   public String getTargetRootDir() {
296     return targetRootDir;
297   }
298 
299   public void setHlogTargetDir(String hlogTagetDir) {
300     this.hlogTargetDir = hlogTagetDir;
301   }
302 
303   public String getHLogTargetDir() {
304     return hlogTargetDir;
305   }
306 
307   public List<String> getIncrBackupFileList() {
308     return incrBackupFileList;
309   }
310 
311   public void setIncrBackupFileList(List<String> incrBackupFileList) {
312     this.incrBackupFileList = incrBackupFileList;
313   }
314 
315   /**
316    * Set the new region server log timestamps after distributed log roll
317    * @param newTableSetTimestampMap table timestamp map
318    */
319   public void setIncrTimestampMap(HashMap<TableName,
320       HashMap<String, Long>> newTableSetTimestampMap) {
321     this.tableSetTimestampMap = newTableSetTimestampMap;
322   }
323 
324   /**
325    * Get new region server log timestamps after distributed log roll
326    * @return new region server log timestamps
327    */
328   public HashMap<TableName, HashMap<String, Long>> getIncrTimestampMap() {
329     return this.tableSetTimestampMap;
330   }
331 
332   public TableName getTableBySnapshot(String snapshotName) {
333     for (Entry<TableName, BackupStatus> entry : this.backupStatusMap.entrySet()) {
334       if (snapshotName.equals(entry.getValue().getSnapshotName())) {
335         return entry.getKey();
336       }
337     }
338     return null;
339   }
340 
341   public BackupProtos.BackupInfo toProtosBackupInfo() {
342     BackupProtos.BackupInfo.Builder builder = BackupProtos.BackupInfo.newBuilder();
343     builder.setBackupId(getBackupId());
344     setBackupStatusMap(builder);
345     builder.setEndTs(getEndTs());
346     if (getFailedMsg() != null) {
347       builder.setFailedMessage(getFailedMsg());
348     }
349     if (getState() != null) {
350       builder.setState(BackupProtos.BackupInfo.BackupState.valueOf(getState().name()));
351     }
352     if (getPhase() != null) {
353       builder.setPhase(BackupProtos.BackupInfo.BackupPhase.valueOf(getPhase().name()));
354     }
355 
356     builder.setProgress(getProgress());
357     builder.setStartTs(getStartTs());
358     builder.setTargetRootDir(getTargetRootDir());
359     builder.setType(BackupProtos.BackupType.valueOf(getType().name()));
360     builder.setWorkersNumber(workers);
361     builder.setBandwidth(bandwidth);
362     if (jobId != null) {
363       builder.setJobId(jobId);
364     }
365     return builder.build();
366   }
367 
368   public byte[] toByteArray() throws IOException {
369     return toProtosBackupInfo().toByteArray();
370   }
371 
372   private void setBackupStatusMap(Builder builder) {
373     for (Entry<TableName, BackupStatus> entry: backupStatusMap.entrySet()) {
374       builder.addTableBackupStatus(entry.getValue().toProto());
375     }
376   }
377 
378   public static BackupInfo fromByteArray(byte[] data) throws IOException {
379     return fromProto(BackupProtos.BackupInfo.parseFrom(data));
380   }
381   
382   public static BackupInfo fromStream(final InputStream stream) throws IOException {
383     return fromProto(BackupProtos.BackupInfo.parseDelimitedFrom(stream));
384   }
385 
386   public static BackupInfo fromProto(BackupProtos.BackupInfo proto) {
387     BackupInfo context = new BackupInfo();
388     context.setBackupId(proto.getBackupId());
389     context.setBackupStatusMap(toMap(proto.getTableBackupStatusList()));
390     context.setEndTs(proto.getEndTs());
391     if (proto.hasFailedMessage()) {
392       context.setFailedMsg(proto.getFailedMessage());
393     }
394     if (proto.hasState()) {
395       context.setState(BackupInfo.BackupState.valueOf(proto.getState().name()));
396     }
397 
398     context.setHlogTargetDir(BackupClientUtil.getLogBackupDir(proto.getTargetRootDir(),
399       proto.getBackupId()));
400 
401     if (proto.hasPhase()) {
402       context.setPhase(BackupPhase.valueOf(proto.getPhase().name()));
403     }
404     if (proto.hasProgress()) {
405       context.setProgress(proto.getProgress());
406     }
407     context.setStartTs(proto.getStartTs());
408     context.setTargetRootDir(proto.getTargetRootDir());
409     context.setType(BackupType.valueOf(proto.getType().name()));
410     context.setWorkers(proto.getWorkersNumber());
411     context.setBandwidth(proto.getBandwidth());
412     if (proto.hasJobId()) {
413       context.setJobId(proto.getJobId());
414     }
415     return context;
416   }
417 
418   private static Map<TableName, BackupStatus> toMap(List<TableBackupStatus> list) {
419     HashMap<TableName, BackupStatus> map = new HashMap<>();
420     for (TableBackupStatus tbs : list){
421       map.put(ProtobufUtil.toTableName(tbs.getTable()), BackupStatus.convert(tbs));
422     }
423     return map;
424   }
425 
426   public String getShortDescription() {
427     StringBuilder sb = new StringBuilder();
428     sb.append("ID             : " + backupId).append("\n");
429     sb.append("Type           : " + getType()).append("\n");
430     sb.append("Tables         : " + getTableListAsString()).append("\n");
431     sb.append("State          : " + getState()).append("\n");
432     Date date = null;
433     Calendar cal = Calendar.getInstance();
434     cal.setTimeInMillis(getStartTs());
435     date = cal.getTime();
436     sb.append("Start time     : " + date).append("\n");
437     if (state == BackupState.FAILED) {
438       sb.append("Failed message : " + getFailedMsg()).append("\n");
439     } else if (state == BackupState.RUNNING) {
440       sb.append("Phase          : " + getPhase()).append("\n");
441     } else if (state == BackupState.COMPLETE) {
442       cal = Calendar.getInstance();
443       cal.setTimeInMillis(getEndTs());
444       date = cal.getTime();
445       sb.append("End time       : " + date).append("\n");
446     }
447     sb.append("Progress       : " + getProgress()).append("\n");
448     return sb.toString();
449   }
450 
451   public String getStatusAndProgressAsString() {
452     StringBuilder sb = new StringBuilder();
453     sb.append("id: ").append(getBackupId()).append(" state: ").append(getState())
454         .append(" progress: ").append(getProgress());
455     return sb.toString();
456   }
457   
458   public String getTableListAsString() {
459     return StringUtils.join(backupStatusMap.keySet(), ",");
460   }
461 
462   @Override
463   public int compareTo(BackupInfo o) {
464       Long thisTS =
465           new Long(this.getBackupId().substring(this.getBackupId().lastIndexOf("_") + 1));
466       Long otherTS =
467           new Long(o.getBackupId().substring(o.getBackupId().lastIndexOf("_") + 1));
468       return thisTS.compareTo(otherTS);
469   }
470    
471   
472 }