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 * <p>
010 * http://www.apache.org/licenses/LICENSE-2.0
011 * <p>
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 */
018package org.apache.hadoop.fs;
019
020import org.apache.hadoop.conf.Configuration;
021import org.apache.hadoop.util.Shell;
022import org.slf4j.Logger;
023import org.slf4j.LoggerFactory;
024
025import java.io.File;
026import java.io.IOException;
027import java.lang.reflect.Constructor;
028import java.lang.reflect.InvocationTargetException;
029import java.util.concurrent.TimeUnit;
030
031public interface GetSpaceUsed {
032
033
034  long getUsed() throws IOException;
035
036  /**
037   * The builder class
038   */
039  final class Builder {
040    static final Logger LOG = LoggerFactory.getLogger(Builder.class);
041
042    static final String CLASSNAME_KEY = "fs.getspaceused.classname";
043    static final String JITTER_KEY = "fs.getspaceused.jitterMillis";
044    static final long DEFAULT_JITTER = TimeUnit.MINUTES.toMillis(1);
045
046
047    private Configuration conf;
048    private Class<? extends GetSpaceUsed> klass = null;
049    private File path = null;
050    private Long interval = null;
051    private Long jitter = null;
052    private Long initialUsed = null;
053
054    public Configuration getConf() {
055      return conf;
056    }
057
058    public Builder setConf(Configuration conf) {
059      this.conf = conf;
060      return this;
061    }
062
063    public long getInterval() {
064      if (interval != null) {
065        return interval;
066      }
067      long result = CommonConfigurationKeys.FS_DU_INTERVAL_DEFAULT;
068      if (conf == null) {
069        return result;
070      }
071      return conf.getLong(CommonConfigurationKeys.FS_DU_INTERVAL_KEY, result);
072    }
073
074    public Builder setInterval(long interval) {
075      this.interval = interval;
076      return this;
077    }
078
079    public Class<? extends GetSpaceUsed> getKlass() {
080      if (klass != null) {
081        return klass;
082      }
083      Class<? extends GetSpaceUsed> result = null;
084      if (Shell.WINDOWS) {
085        result = WindowsGetSpaceUsed.class;
086      } else {
087        result = DU.class;
088      }
089      if (conf == null) {
090        return result;
091      }
092      return conf.getClass(CLASSNAME_KEY, result, GetSpaceUsed.class);
093    }
094
095    public Builder setKlass(Class<? extends GetSpaceUsed> klass) {
096      this.klass = klass;
097      return this;
098    }
099
100    public File getPath() {
101      return path;
102    }
103
104    public Builder setPath(File path) {
105      this.path = path;
106      return this;
107    }
108
109    public long getInitialUsed() {
110      if (initialUsed == null) {
111        return -1;
112      }
113      return initialUsed;
114    }
115
116    public Builder setInitialUsed(long initialUsed) {
117      this.initialUsed = initialUsed;
118      return this;
119    }
120
121
122    public long getJitter() {
123      if (jitter == null) {
124        Configuration configuration = this.conf;
125
126        if (configuration == null) {
127          return DEFAULT_JITTER;
128        }
129        return configuration.getLong(JITTER_KEY, DEFAULT_JITTER);
130      }
131      return jitter;
132    }
133
134    public Builder setJitter(Long jit) {
135      this.jitter = jit;
136      return this;
137    }
138
139    public GetSpaceUsed build() throws IOException {
140      GetSpaceUsed getSpaceUsed = null;
141      try {
142        Constructor<? extends GetSpaceUsed> cons =
143            getKlass().getConstructor(Builder.class);
144        getSpaceUsed = cons.newInstance(this);
145      } catch (InstantiationException e) {
146        LOG.warn("Error trying to create an instance of " + getKlass(), e);
147      } catch (IllegalAccessException e) {
148        LOG.warn("Error trying to create " + getKlass(), e);
149      } catch (InvocationTargetException e) {
150        LOG.warn("Error trying to create " + getKlass(), e);
151      } catch (NoSuchMethodException e) {
152        LOG.warn("Doesn't look like the class " + getKlass() +
153            " have the needed constructor", e);
154      }
155      // If there were any exceptions then du will be null.
156      // Construct our best guess fallback.
157      if (getSpaceUsed == null) {
158        if (Shell.WINDOWS) {
159          getSpaceUsed = new WindowsGetSpaceUsed(this);
160        } else {
161          getSpaceUsed = new DU(this);
162        }
163      }
164      // Call init after classes constructors have finished.
165      if (getSpaceUsed instanceof CachingGetSpaceUsed) {
166        ((CachingGetSpaceUsed) getSpaceUsed).init();
167      }
168      return getSpaceUsed;
169    }
170
171  }
172}