001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.hadoop.hdfs.server.protocol;
019    
020    import java.io.DataInput;
021    import java.io.DataOutput;
022    import java.io.IOException;
023    import java.util.Collections;
024    import java.util.List;
025    
026    import org.apache.hadoop.io.Writable;
027    
028    import com.google.common.base.Joiner;
029    import com.google.common.base.Preconditions;
030    import com.google.common.collect.Lists;
031    
032    /**
033     * An enumeration of logs available on a remote NameNode.
034     */
035    public class RemoteEditLogManifest implements Writable {
036    
037      private List<RemoteEditLog> logs;
038      
039      public RemoteEditLogManifest() {
040      }
041      
042      public RemoteEditLogManifest(List<RemoteEditLog> logs) {
043        this.logs = logs;
044        checkState();
045      }
046      
047      
048      /**
049       * Check that the logs are contiguous and non-overlapping
050       * sequences of transactions, in sorted order
051       * @throws IllegalStateException if incorrect
052       */
053      private void checkState()  {
054        Preconditions.checkNotNull(logs);
055        
056        RemoteEditLog prev = null;
057        for (RemoteEditLog log : logs) {
058          if (prev != null) {
059            if (log.getStartTxId() != prev.getEndTxId() + 1) {
060              throw new IllegalStateException("Invalid log manifest:" + this);
061            }
062          }
063          
064          prev = log;
065        }
066      }
067      
068      public List<RemoteEditLog> getLogs() {
069        return Collections.unmodifiableList(logs);
070      }
071    
072    
073      
074      @Override
075      public String toString() {
076        return "[" + Joiner.on(", ").join(logs) + "]";
077      }
078      
079      
080      @Override
081      public void write(DataOutput out) throws IOException {
082        out.writeInt(logs.size());
083        for (RemoteEditLog log : logs) {
084          log.write(out);
085        }
086      }
087    
088      @Override
089      public void readFields(DataInput in) throws IOException {
090        int numLogs = in.readInt();
091        logs = Lists.newArrayList();
092        for (int i = 0; i < numLogs; i++) {
093          RemoteEditLog log = new RemoteEditLog();
094          log.readFields(in);
095          logs.add(log);
096        }
097        checkState();
098      }
099    }