浏览代码

HUE-19. Add get_content_summaries call to NameNode plugin.

Addressing bc's code review.
Aaron T. Myers 15 年之前
父节点
当前提交
2d3da3e977

+ 7 - 0
desktop/libs/hadoop/gen-py/hadoop/api/hdfs/Namenode-remote

@@ -38,6 +38,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':
   print '  void reportBadBlocks(RequestContext ctx,  blocks)'
   print '  Stat stat(RequestContext ctx, string path)'
   print '  ContentSummary getContentSummary(RequestContext ctx, string Path)'
+  print '   multiGetContentSummary(RequestContext ctx,  paths)'
   print '  void setQuota(RequestContext ctx, string path, i64 namespaceQuota, i64 diskspaceQuota)'
   print '  bool setReplication(RequestContext ctx, string path, i16 replication)'
   print '  bool unlink(RequestContext ctx, string path, bool recursive)'
@@ -194,6 +195,12 @@ elif cmd == 'getContentSummary':
     sys.exit(1)
   pp.pprint(client.getContentSummary(eval(args[0]),args[1],))
 
+elif cmd == 'multiGetContentSummary':
+  if len(args) != 2:
+    print 'multiGetContentSummary requires 2 args'
+    sys.exit(1)
+  pp.pprint(client.multiGetContentSummary(eval(args[0]),eval(args[1]),))
+
 elif cmd == 'setQuota':
   if len(args) != 4:
     print 'setQuota requires 4 args'

+ 229 - 2
desktop/libs/hadoop/gen-py/hadoop/api/hdfs/Namenode.py

@@ -85,6 +85,7 @@ class Iface(hadoop.api.common.HadoopServiceBase.Iface):
   def getDatanodeReport(self, ctx, type):
     """
     Get a report on the system's current data nodes.
+    Note that ctx is currently ignored by the server.
     
     Parameters:
      - ctx
@@ -95,7 +96,7 @@ class Iface(hadoop.api.common.HadoopServiceBase.Iface):
 
   def getHealthReport(self, ctx):
     """
-    Get a health report of DFS
+    Get a health report of DFS.  Note that ctx is ignored by the server.
     
     Parameters:
      - ctx
@@ -216,6 +217,17 @@ class Iface(hadoop.api.common.HadoopServiceBase.Iface):
     """
     pass
 
+  def multiGetContentSummary(self, ctx, paths):
+    """
+    Get ContentSummary objects for multiple directories simultaneously. The same warnings
+    apply as for getContentSummary(...) above.
+    
+    Parameters:
+     - ctx
+     - paths
+    """
+    pass
+
   def setQuota(self, ctx, path, namespaceQuota, diskspaceQuota):
     """
     Set the quota for a directory.
@@ -509,6 +521,7 @@ class Client(hadoop.api.common.HadoopServiceBase.Client, Iface):
   def getDatanodeReport(self, ctx, type):
     """
     Get a report on the system's current data nodes.
+    Note that ctx is currently ignored by the server.
     
     Parameters:
      - ctx
@@ -545,7 +558,7 @@ class Client(hadoop.api.common.HadoopServiceBase.Client, Iface):
 
   def getHealthReport(self, ctx):
     """
-    Get a health report of DFS
+    Get a health report of DFS.  Note that ctx is ignored by the server.
     
     Parameters:
      - ctx
@@ -944,6 +957,43 @@ class Client(hadoop.api.common.HadoopServiceBase.Client, Iface):
       raise result.err
     raise TApplicationException(TApplicationException.MISSING_RESULT, "getContentSummary failed: unknown result");
 
+  def multiGetContentSummary(self, ctx, paths):
+    """
+    Get ContentSummary objects for multiple directories simultaneously. The same warnings
+    apply as for getContentSummary(...) above.
+    
+    Parameters:
+     - ctx
+     - paths
+    """
+    self.send_multiGetContentSummary(ctx, paths)
+    return self.recv_multiGetContentSummary()
+
+  def send_multiGetContentSummary(self, ctx, paths):
+    self._oprot.writeMessageBegin('multiGetContentSummary', TMessageType.CALL, self._seqid)
+    args = multiGetContentSummary_args()
+    args.ctx = ctx
+    args.paths = paths
+    args.write(self._oprot)
+    self._oprot.writeMessageEnd()
+    self._oprot.trans.flush()
+
+  def recv_multiGetContentSummary(self, ):
+    (fname, mtype, rseqid) = self._iprot.readMessageBegin()
+    if mtype == TMessageType.EXCEPTION:
+      x = TApplicationException()
+      x.read(self._iprot)
+      self._iprot.readMessageEnd()
+      raise x
+    result = multiGetContentSummary_result()
+    result.read(self._iprot)
+    self._iprot.readMessageEnd()
+    if result.success != None:
+      return result.success
+    if result.err != None:
+      raise result.err
+    raise TApplicationException(TApplicationException.MISSING_RESULT, "multiGetContentSummary failed: unknown result");
+
   def setQuota(self, ctx, path, namespaceQuota, diskspaceQuota):
     """
     Set the quota for a directory.
@@ -1210,6 +1260,7 @@ class Processor(hadoop.api.common.HadoopServiceBase.Processor, Iface, TProcessor
     self._processMap["reportBadBlocks"] = Processor.process_reportBadBlocks
     self._processMap["stat"] = Processor.process_stat
     self._processMap["getContentSummary"] = Processor.process_getContentSummary
+    self._processMap["multiGetContentSummary"] = Processor.process_multiGetContentSummary
     self._processMap["setQuota"] = Processor.process_setQuota
     self._processMap["setReplication"] = Processor.process_setReplication
     self._processMap["unlink"] = Processor.process_unlink
@@ -1470,6 +1521,20 @@ class Processor(hadoop.api.common.HadoopServiceBase.Processor, Iface, TProcessor
     oprot.writeMessageEnd()
     oprot.trans.flush()
 
+  def process_multiGetContentSummary(self, seqid, iprot, oprot):
+    args = multiGetContentSummary_args()
+    args.read(iprot)
+    iprot.readMessageEnd()
+    result = multiGetContentSummary_result()
+    try:
+      result.success = self._handler.multiGetContentSummary(args.ctx, args.paths)
+    except hadoop.api.common.ttypes.IOException, err:
+      result.err = err
+    oprot.writeMessageBegin("multiGetContentSummary", TMessageType.REPLY, seqid)
+    result.write(oprot)
+    oprot.writeMessageEnd()
+    oprot.trans.flush()
+
   def process_setQuota(self, seqid, iprot, oprot):
     args = setQuota_args()
     args.read(iprot)
@@ -4009,6 +4074,168 @@ class getContentSummary_result(object):
   def __ne__(self, other):
     return not (self == other)
 
+class multiGetContentSummary_args(object):
+  """
+  Attributes:
+   - ctx
+   - paths
+  """
+
+  thrift_spec = (
+    None, # 0
+    (1, TType.LIST, 'paths', (TType.STRING,None), None, ), # 1
+    None, # 2
+    None, # 3
+    None, # 4
+    None, # 5
+    None, # 6
+    None, # 7
+    None, # 8
+    None, # 9
+    (10, TType.STRUCT, 'ctx', (hadoop.api.common.ttypes.RequestContext, hadoop.api.common.ttypes.RequestContext.thrift_spec), None, ), # 10
+  )
+
+  def __init__(self, ctx=None, paths=None,):
+    self.ctx = ctx
+    self.paths = paths
+
+  def read(self, iprot):
+    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
+      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
+      return
+    iprot.readStructBegin()
+    while True:
+      (fname, ftype, fid) = iprot.readFieldBegin()
+      if ftype == TType.STOP:
+        break
+      if fid == 10:
+        if ftype == TType.STRUCT:
+          self.ctx = hadoop.api.common.ttypes.RequestContext()
+          self.ctx.read(iprot)
+        else:
+          iprot.skip(ftype)
+      elif fid == 1:
+        if ftype == TType.LIST:
+          self.paths = []
+          (_etype45, _size42) = iprot.readListBegin()
+          for _i46 in xrange(_size42):
+            _elem47 = iprot.readString();
+            self.paths.append(_elem47)
+          iprot.readListEnd()
+        else:
+          iprot.skip(ftype)
+      else:
+        iprot.skip(ftype)
+      iprot.readFieldEnd()
+    iprot.readStructEnd()
+
+  def write(self, oprot):
+    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
+      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
+      return
+    oprot.writeStructBegin('multiGetContentSummary_args')
+    if self.paths != None:
+      oprot.writeFieldBegin('paths', TType.LIST, 1)
+      oprot.writeListBegin(TType.STRING, len(self.paths))
+      for iter48 in self.paths:
+        oprot.writeString(iter48)
+      oprot.writeListEnd()
+      oprot.writeFieldEnd()
+    if self.ctx != None:
+      oprot.writeFieldBegin('ctx', TType.STRUCT, 10)
+      self.ctx.write(oprot)
+      oprot.writeFieldEnd()
+    oprot.writeFieldStop()
+    oprot.writeStructEnd()
+
+  def __repr__(self):
+    L = ['%s=%r' % (key, value)
+      for key, value in self.__dict__.iteritems()]
+    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+  def __ne__(self, other):
+    return not (self == other)
+
+class multiGetContentSummary_result(object):
+  """
+  Attributes:
+   - success
+   - err
+  """
+
+  thrift_spec = (
+    (0, TType.LIST, 'success', (TType.STRUCT,(ContentSummary, ContentSummary.thrift_spec)), None, ), # 0
+    (1, TType.STRUCT, 'err', (hadoop.api.common.ttypes.IOException, hadoop.api.common.ttypes.IOException.thrift_spec), None, ), # 1
+  )
+
+  def __init__(self, success=None, err=None,):
+    self.success = success
+    self.err = err
+
+  def read(self, iprot):
+    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
+      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
+      return
+    iprot.readStructBegin()
+    while True:
+      (fname, ftype, fid) = iprot.readFieldBegin()
+      if ftype == TType.STOP:
+        break
+      if fid == 0:
+        if ftype == TType.LIST:
+          self.success = []
+          (_etype52, _size49) = iprot.readListBegin()
+          for _i53 in xrange(_size49):
+            _elem54 = ContentSummary()
+            _elem54.read(iprot)
+            self.success.append(_elem54)
+          iprot.readListEnd()
+        else:
+          iprot.skip(ftype)
+      elif fid == 1:
+        if ftype == TType.STRUCT:
+          self.err = hadoop.api.common.ttypes.IOException()
+          self.err.read(iprot)
+        else:
+          iprot.skip(ftype)
+      else:
+        iprot.skip(ftype)
+      iprot.readFieldEnd()
+    iprot.readStructEnd()
+
+  def write(self, oprot):
+    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
+      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
+      return
+    oprot.writeStructBegin('multiGetContentSummary_result')
+    if self.success != None:
+      oprot.writeFieldBegin('success', TType.LIST, 0)
+      oprot.writeListBegin(TType.STRUCT, len(self.success))
+      for iter55 in self.success:
+        iter55.write(oprot)
+      oprot.writeListEnd()
+      oprot.writeFieldEnd()
+    if self.err != None:
+      oprot.writeFieldBegin('err', TType.STRUCT, 1)
+      self.err.write(oprot)
+      oprot.writeFieldEnd()
+    oprot.writeFieldStop()
+    oprot.writeStructEnd()
+
+  def __repr__(self):
+    L = ['%s=%r' % (key, value)
+      for key, value in self.__dict__.iteritems()]
+    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+  def __ne__(self, other):
+    return not (self == other)
+
 class setQuota_args(object):
   """
   Attributes:

+ 14 - 2
desktop/libs/hadoop/gen-py/hadoop/api/hdfs/ttypes.py

@@ -542,9 +542,10 @@ class ContentSummary(object):
   Attributes:
    - fileCount: Number of files in this directory
    - directoryCount: Number of directories in this directory
-   - quota: Quota for this directory (in bytes).
+   - quota: Quota for this directory (number of files).
    - spaceConsumed: Space consumed in disk (in bytes).
    - spaceQuota: Quota consumed in disk (in bytes).
+   - path: The path
   """
 
   thrift_spec = (
@@ -554,14 +555,16 @@ class ContentSummary(object):
     (3, TType.I64, 'quota', None, None, ), # 3
     (4, TType.I64, 'spaceConsumed', None, None, ), # 4
     (5, TType.I64, 'spaceQuota', None, None, ), # 5
+    (6, TType.STRING, 'path', None, None, ), # 6
   )
 
-  def __init__(self, fileCount=None, directoryCount=None, quota=None, spaceConsumed=None, spaceQuota=None,):
+  def __init__(self, fileCount=None, directoryCount=None, quota=None, spaceConsumed=None, spaceQuota=None, path=None,):
     self.fileCount = fileCount
     self.directoryCount = directoryCount
     self.quota = quota
     self.spaceConsumed = spaceConsumed
     self.spaceQuota = spaceQuota
+    self.path = path
 
   def read(self, iprot):
     if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
@@ -597,6 +600,11 @@ class ContentSummary(object):
           self.spaceQuota = iprot.readI64();
         else:
           iprot.skip(ftype)
+      elif fid == 6:
+        if ftype == TType.STRING:
+          self.path = iprot.readString();
+        else:
+          iprot.skip(ftype)
       else:
         iprot.skip(ftype)
       iprot.readFieldEnd()
@@ -627,6 +635,10 @@ class ContentSummary(object):
       oprot.writeFieldBegin('spaceQuota', TType.I64, 5)
       oprot.writeI64(self.spaceQuota)
       oprot.writeFieldEnd()
+    if self.path != None:
+      oprot.writeFieldBegin('path', TType.STRING, 6)
+      oprot.writeString(self.path)
+      oprot.writeFieldEnd()
     oprot.writeFieldStop()
     oprot.writeStructEnd()
 

+ 102 - 6
desktop/libs/hadoop/java/gen-java/org/apache/hadoop/thriftfs/api/ContentSummary.java

@@ -35,6 +35,7 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
   private static final TField QUOTA_FIELD_DESC = new TField("quota", TType.I64, (short)3);
   private static final TField SPACE_CONSUMED_FIELD_DESC = new TField("spaceConsumed", TType.I64, (short)4);
   private static final TField SPACE_QUOTA_FIELD_DESC = new TField("spaceQuota", TType.I64, (short)5);
+  private static final TField PATH_FIELD_DESC = new TField("path", TType.STRING, (short)6);
 
   /**
    * Number of files in this directory
@@ -45,7 +46,7 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
    */
   public long directoryCount;
   /**
-   * Quota for this directory (in bytes).
+   * Quota for this directory (number of files).
    */
   public long quota;
   /**
@@ -56,6 +57,10 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
    * Quota consumed in disk (in bytes).
    */
   public long spaceQuota;
+  /**
+   * The path
+   */
+  public String path;
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements TFieldIdEnum {
@@ -68,7 +73,7 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
      */
     DIRECTORY_COUNT((short)2, "directoryCount"),
     /**
-     * Quota for this directory (in bytes).
+     * Quota for this directory (number of files).
      */
     QUOTA((short)3, "quota"),
     /**
@@ -78,7 +83,11 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     /**
      * Quota consumed in disk (in bytes).
      */
-    SPACE_QUOTA((short)5, "spaceQuota");
+    SPACE_QUOTA((short)5, "spaceQuota"),
+    /**
+     * The path
+     */
+    PATH((short)6, "path");
 
     private static final Map<Integer, _Fields> byId = new HashMap<Integer, _Fields>();
     private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
@@ -150,6 +159,8 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
         new FieldValueMetaData(TType.I64)));
     put(_Fields.SPACE_QUOTA, new FieldMetaData("spaceQuota", TFieldRequirementType.DEFAULT, 
         new FieldValueMetaData(TType.I64)));
+    put(_Fields.PATH, new FieldMetaData("path", TFieldRequirementType.DEFAULT, 
+        new FieldValueMetaData(TType.STRING)));
   }});
 
   static {
@@ -164,7 +175,8 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     long directoryCount,
     long quota,
     long spaceConsumed,
-    long spaceQuota)
+    long spaceQuota,
+    String path)
   {
     this();
     this.fileCount = fileCount;
@@ -177,6 +189,7 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     setSpaceConsumedIsSet(true);
     this.spaceQuota = spaceQuota;
     setSpaceQuotaIsSet(true);
+    this.path = path;
   }
 
   /**
@@ -190,6 +203,9 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     this.quota = other.quota;
     this.spaceConsumed = other.spaceConsumed;
     this.spaceQuota = other.spaceQuota;
+    if (other.isSetPath()) {
+      this.path = other.path;
+    }
   }
 
   public ContentSummary deepCopy() {
@@ -260,14 +276,14 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
   }
 
   /**
-   * Quota for this directory (in bytes).
+   * Quota for this directory (number of files).
    */
   public long getQuota() {
     return this.quota;
   }
 
   /**
-   * Quota for this directory (in bytes).
+   * Quota for this directory (number of files).
    */
   public ContentSummary setQuota(long quota) {
     this.quota = quota;
@@ -346,6 +362,36 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     __isset_bit_vector.set(__SPACEQUOTA_ISSET_ID, value);
   }
 
+  /**
+   * The path
+   */
+  public String getPath() {
+    return this.path;
+  }
+
+  /**
+   * The path
+   */
+  public ContentSummary setPath(String path) {
+    this.path = path;
+    return this;
+  }
+
+  public void unsetPath() {
+    this.path = null;
+  }
+
+  /** Returns true if field path is set (has been asigned a value) and false otherwise */
+  public boolean isSetPath() {
+    return this.path != null;
+  }
+
+  public void setPathIsSet(boolean value) {
+    if (!value) {
+      this.path = null;
+    }
+  }
+
   public void setFieldValue(_Fields field, Object value) {
     switch (field) {
     case FILE_COUNT:
@@ -388,6 +434,14 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
       }
       break;
 
+    case PATH:
+      if (value == null) {
+        unsetPath();
+      } else {
+        setPath((String)value);
+      }
+      break;
+
     }
   }
 
@@ -412,6 +466,9 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     case SPACE_QUOTA:
       return new Long(getSpaceQuota());
 
+    case PATH:
+      return getPath();
+
     }
     throw new IllegalStateException();
   }
@@ -433,6 +490,8 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
       return isSetSpaceConsumed();
     case SPACE_QUOTA:
       return isSetSpaceQuota();
+    case PATH:
+      return isSetPath();
     }
     throw new IllegalStateException();
   }
@@ -499,6 +558,15 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
         return false;
     }
 
+    boolean this_present_path = true && this.isSetPath();
+    boolean that_present_path = true && that.isSetPath();
+    if (this_present_path || that_present_path) {
+      if (!(this_present_path && that_present_path))
+        return false;
+      if (!this.path.equals(that.path))
+        return false;
+    }
+
     return true;
   }
 
@@ -555,6 +623,14 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     if (lastComparison != 0) {
       return lastComparison;
     }
+    lastComparison = Boolean.valueOf(isSetPath()).compareTo(isSetPath());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    lastComparison = TBaseHelper.compareTo(path, typedOther.path);
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
     return 0;
   }
 
@@ -612,6 +688,13 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
               TProtocolUtil.skip(iprot, field.type);
             }
             break;
+          case PATH:
+            if (field.type == TType.STRING) {
+              this.path = iprot.readString();
+            } else { 
+              TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
         }
         iprot.readFieldEnd();
       }
@@ -641,6 +724,11 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     oprot.writeFieldBegin(SPACE_QUOTA_FIELD_DESC);
     oprot.writeI64(this.spaceQuota);
     oprot.writeFieldEnd();
+    if (this.path != null) {
+      oprot.writeFieldBegin(PATH_FIELD_DESC);
+      oprot.writeString(this.path);
+      oprot.writeFieldEnd();
+    }
     oprot.writeFieldStop();
     oprot.writeStructEnd();
   }
@@ -669,6 +757,14 @@ public class ContentSummary implements TBase<ContentSummary._Fields>, java.io.Se
     sb.append("spaceQuota:");
     sb.append(this.spaceQuota);
     first = false;
+    if (!first) sb.append(", ");
+    sb.append("path:");
+    if (this.path == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.path);
+    }
+    first = false;
     sb.append(")");
     return sb.toString();
   }

+ 859 - 1
desktop/libs/hadoop/java/gen-java/org/apache/hadoop/thriftfs/api/Namenode.java

@@ -89,6 +89,7 @@ public class Namenode {
 
     /**
      * Get a report on the system's current data nodes.
+     * Note that ctx is currently ignored by the server.
      * 
      * @param ctx
      * @param type Type of data nodes to return
@@ -97,7 +98,7 @@ public class Namenode {
     public List<DatanodeInfo> getDatanodeReport(org.apache.hadoop.thriftfs.api.RequestContext ctx, DatanodeReportType type) throws org.apache.hadoop.thriftfs.api.IOException, TException;
 
     /**
-     * Get a health report of DFS
+     * Get a health report of DFS.  Note that ctx is ignored by the server.
      * 
      * @param ctx
      */
@@ -199,6 +200,15 @@ public class Namenode {
      */
     public ContentSummary getContentSummary(org.apache.hadoop.thriftfs.api.RequestContext ctx, String Path) throws org.apache.hadoop.thriftfs.api.IOException, TException;
 
+    /**
+     * Get ContentSummary objects for multiple directories simultaneously. The same warnings
+     * apply as for getContentSummary(...) above.
+     * 
+     * @param ctx
+     * @param paths
+     */
+    public List<ContentSummary> multiGetContentSummary(org.apache.hadoop.thriftfs.api.RequestContext ctx, List<String> paths) throws org.apache.hadoop.thriftfs.api.IOException, TException;
+
     /**
      * Set the quota for a directory.
      * 
@@ -915,6 +925,43 @@ public class Namenode {
       throw new TApplicationException(TApplicationException.MISSING_RESULT, "getContentSummary failed: unknown result");
     }
 
+    public List<ContentSummary> multiGetContentSummary(org.apache.hadoop.thriftfs.api.RequestContext ctx, List<String> paths) throws org.apache.hadoop.thriftfs.api.IOException, TException
+    {
+      send_multiGetContentSummary(ctx, paths);
+      return recv_multiGetContentSummary();
+    }
+
+    public void send_multiGetContentSummary(org.apache.hadoop.thriftfs.api.RequestContext ctx, List<String> paths) throws TException
+    {
+      oprot_.writeMessageBegin(new TMessage("multiGetContentSummary", TMessageType.CALL, seqid_));
+      multiGetContentSummary_args args = new multiGetContentSummary_args();
+      args.ctx = ctx;
+      args.paths = paths;
+      args.write(oprot_);
+      oprot_.writeMessageEnd();
+      oprot_.getTransport().flush();
+    }
+
+    public List<ContentSummary> recv_multiGetContentSummary() throws org.apache.hadoop.thriftfs.api.IOException, TException
+    {
+      TMessage msg = iprot_.readMessageBegin();
+      if (msg.type == TMessageType.EXCEPTION) {
+        TApplicationException x = TApplicationException.read(iprot_);
+        iprot_.readMessageEnd();
+        throw x;
+      }
+      multiGetContentSummary_result result = new multiGetContentSummary_result();
+      result.read(iprot_);
+      iprot_.readMessageEnd();
+      if (result.isSetSuccess()) {
+        return result.success;
+      }
+      if (result.err != null) {
+        throw result.err;
+      }
+      throw new TApplicationException(TApplicationException.MISSING_RESULT, "multiGetContentSummary failed: unknown result");
+    }
+
     public void setQuota(org.apache.hadoop.thriftfs.api.RequestContext ctx, String path, long namespaceQuota, long diskspaceQuota) throws org.apache.hadoop.thriftfs.api.IOException, TException
     {
       send_setQuota(ctx, path, namespaceQuota, diskspaceQuota);
@@ -1151,6 +1198,7 @@ public class Namenode {
       processMap_.put("reportBadBlocks", new reportBadBlocks());
       processMap_.put("stat", new stat());
       processMap_.put("getContentSummary", new getContentSummary());
+      processMap_.put("multiGetContentSummary", new multiGetContentSummary());
       processMap_.put("setQuota", new setQuota());
       processMap_.put("setReplication", new setReplication());
       processMap_.put("unlink", new unlink());
@@ -1659,6 +1707,34 @@ public class Namenode {
 
     }
 
+    private class multiGetContentSummary implements ProcessFunction {
+      public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException
+      {
+        multiGetContentSummary_args args = new multiGetContentSummary_args();
+        args.read(iprot);
+        iprot.readMessageEnd();
+        multiGetContentSummary_result result = new multiGetContentSummary_result();
+        try {
+          result.success = iface_.multiGetContentSummary(args.ctx, args.paths);
+        } catch (org.apache.hadoop.thriftfs.api.IOException err) {
+          result.err = err;
+        } catch (Throwable th) {
+          LOGGER.error("Internal error processing multiGetContentSummary", th);
+          TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR, "Internal error processing multiGetContentSummary");
+          oprot.writeMessageBegin(new TMessage("multiGetContentSummary", TMessageType.EXCEPTION, seqid));
+          x.write(oprot);
+          oprot.writeMessageEnd();
+          oprot.getTransport().flush();
+          return;
+        }
+        oprot.writeMessageBegin(new TMessage("multiGetContentSummary", TMessageType.REPLY, seqid));
+        result.write(oprot);
+        oprot.writeMessageEnd();
+        oprot.getTransport().flush();
+      }
+
+    }
+
     private class setQuota implements ProcessFunction {
       public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException
       {
@@ -13801,6 +13877,788 @@ public class Namenode {
 
   }
 
+  public static class multiGetContentSummary_args implements TBase<multiGetContentSummary_args._Fields>, java.io.Serializable, Cloneable   {
+    private static final TStruct STRUCT_DESC = new TStruct("multiGetContentSummary_args");
+
+    private static final TField CTX_FIELD_DESC = new TField("ctx", TType.STRUCT, (short)10);
+    private static final TField PATHS_FIELD_DESC = new TField("paths", TType.LIST, (short)1);
+
+    public org.apache.hadoop.thriftfs.api.RequestContext ctx;
+    public List<String> paths;
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements TFieldIdEnum {
+      CTX((short)10, "ctx"),
+      PATHS((short)1, "paths");
+
+      private static final Map<Integer, _Fields> byId = new HashMap<Integer, _Fields>();
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byId.put((int)field._thriftId, field);
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        return byId.get(fieldId);
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+
+    // isset id assignments
+
+    public static final Map<_Fields, FieldMetaData> metaDataMap = Collections.unmodifiableMap(new EnumMap<_Fields, FieldMetaData>(_Fields.class) {{
+      put(_Fields.CTX, new FieldMetaData("ctx", TFieldRequirementType.DEFAULT, 
+          new StructMetaData(TType.STRUCT, org.apache.hadoop.thriftfs.api.RequestContext.class)));
+      put(_Fields.PATHS, new FieldMetaData("paths", TFieldRequirementType.DEFAULT, 
+          new ListMetaData(TType.LIST, 
+              new FieldValueMetaData(TType.STRING))));
+    }});
+
+    static {
+      FieldMetaData.addStructMetaDataMap(multiGetContentSummary_args.class, metaDataMap);
+    }
+
+    public multiGetContentSummary_args() {
+    }
+
+    public multiGetContentSummary_args(
+      org.apache.hadoop.thriftfs.api.RequestContext ctx,
+      List<String> paths)
+    {
+      this();
+      this.ctx = ctx;
+      this.paths = paths;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public multiGetContentSummary_args(multiGetContentSummary_args other) {
+      if (other.isSetCtx()) {
+        this.ctx = new org.apache.hadoop.thriftfs.api.RequestContext(other.ctx);
+      }
+      if (other.isSetPaths()) {
+        List<String> __this__paths = new ArrayList<String>();
+        for (String other_element : other.paths) {
+          __this__paths.add(other_element);
+        }
+        this.paths = __this__paths;
+      }
+    }
+
+    public multiGetContentSummary_args deepCopy() {
+      return new multiGetContentSummary_args(this);
+    }
+
+    @Deprecated
+    public multiGetContentSummary_args clone() {
+      return new multiGetContentSummary_args(this);
+    }
+
+    public org.apache.hadoop.thriftfs.api.RequestContext getCtx() {
+      return this.ctx;
+    }
+
+    public multiGetContentSummary_args setCtx(org.apache.hadoop.thriftfs.api.RequestContext ctx) {
+      this.ctx = ctx;
+      return this;
+    }
+
+    public void unsetCtx() {
+      this.ctx = null;
+    }
+
+    /** Returns true if field ctx is set (has been asigned a value) and false otherwise */
+    public boolean isSetCtx() {
+      return this.ctx != null;
+    }
+
+    public void setCtxIsSet(boolean value) {
+      if (!value) {
+        this.ctx = null;
+      }
+    }
+
+    public int getPathsSize() {
+      return (this.paths == null) ? 0 : this.paths.size();
+    }
+
+    public java.util.Iterator<String> getPathsIterator() {
+      return (this.paths == null) ? null : this.paths.iterator();
+    }
+
+    public void addToPaths(String elem) {
+      if (this.paths == null) {
+        this.paths = new ArrayList<String>();
+      }
+      this.paths.add(elem);
+    }
+
+    public List<String> getPaths() {
+      return this.paths;
+    }
+
+    public multiGetContentSummary_args setPaths(List<String> paths) {
+      this.paths = paths;
+      return this;
+    }
+
+    public void unsetPaths() {
+      this.paths = null;
+    }
+
+    /** Returns true if field paths is set (has been asigned a value) and false otherwise */
+    public boolean isSetPaths() {
+      return this.paths != null;
+    }
+
+    public void setPathsIsSet(boolean value) {
+      if (!value) {
+        this.paths = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case CTX:
+        if (value == null) {
+          unsetCtx();
+        } else {
+          setCtx((org.apache.hadoop.thriftfs.api.RequestContext)value);
+        }
+        break;
+
+      case PATHS:
+        if (value == null) {
+          unsetPaths();
+        } else {
+          setPaths((List<String>)value);
+        }
+        break;
+
+      }
+    }
+
+    public void setFieldValue(int fieldID, Object value) {
+      setFieldValue(_Fields.findByThriftIdOrThrow(fieldID), value);
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case CTX:
+        return getCtx();
+
+      case PATHS:
+        return getPaths();
+
+      }
+      throw new IllegalStateException();
+    }
+
+    public Object getFieldValue(int fieldId) {
+      return getFieldValue(_Fields.findByThriftIdOrThrow(fieldId));
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      switch (field) {
+      case CTX:
+        return isSetCtx();
+      case PATHS:
+        return isSetPaths();
+      }
+      throw new IllegalStateException();
+    }
+
+    public boolean isSet(int fieldID) {
+      return isSet(_Fields.findByThriftIdOrThrow(fieldID));
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof multiGetContentSummary_args)
+        return this.equals((multiGetContentSummary_args)that);
+      return false;
+    }
+
+    public boolean equals(multiGetContentSummary_args that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_ctx = true && this.isSetCtx();
+      boolean that_present_ctx = true && that.isSetCtx();
+      if (this_present_ctx || that_present_ctx) {
+        if (!(this_present_ctx && that_present_ctx))
+          return false;
+        if (!this.ctx.equals(that.ctx))
+          return false;
+      }
+
+      boolean this_present_paths = true && this.isSetPaths();
+      boolean that_present_paths = true && that.isSetPaths();
+      if (this_present_paths || that_present_paths) {
+        if (!(this_present_paths && that_present_paths))
+          return false;
+        if (!this.paths.equals(that.paths))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public void read(TProtocol iprot) throws TException {
+      TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == TType.STOP) { 
+          break;
+        }
+        _Fields fieldId = _Fields.findByThriftId(field.id);
+        if (fieldId == null) {
+          TProtocolUtil.skip(iprot, field.type);
+        } else {
+          switch (fieldId) {
+            case CTX:
+              if (field.type == TType.STRUCT) {
+                this.ctx = new org.apache.hadoop.thriftfs.api.RequestContext();
+                this.ctx.read(iprot);
+              } else { 
+                TProtocolUtil.skip(iprot, field.type);
+              }
+              break;
+            case PATHS:
+              if (field.type == TType.LIST) {
+                {
+                  TList _list24 = iprot.readListBegin();
+                  this.paths = new ArrayList<String>(_list24.size);
+                  for (int _i25 = 0; _i25 < _list24.size; ++_i25)
+                  {
+                    String _elem26;
+                    _elem26 = iprot.readString();
+                    this.paths.add(_elem26);
+                  }
+                  iprot.readListEnd();
+                }
+              } else { 
+                TProtocolUtil.skip(iprot, field.type);
+              }
+              break;
+          }
+          iprot.readFieldEnd();
+        }
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(TProtocol oprot) throws TException {
+      validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (this.paths != null) {
+        oprot.writeFieldBegin(PATHS_FIELD_DESC);
+        {
+          oprot.writeListBegin(new TList(TType.STRING, this.paths.size()));
+          for (String _iter27 : this.paths)
+          {
+            oprot.writeString(_iter27);
+          }
+          oprot.writeListEnd();
+        }
+        oprot.writeFieldEnd();
+      }
+      if (this.ctx != null) {
+        oprot.writeFieldBegin(CTX_FIELD_DESC);
+        this.ctx.write(oprot);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("multiGetContentSummary_args(");
+      boolean first = true;
+
+      sb.append("ctx:");
+      if (this.ctx == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.ctx);
+      }
+      first = false;
+      if (!first) sb.append(", ");
+      sb.append("paths:");
+      if (this.paths == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.paths);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws TException {
+      // check for required fields
+    }
+
+  }
+
+  public static class multiGetContentSummary_result implements TBase<multiGetContentSummary_result._Fields>, java.io.Serializable, Cloneable, Comparable<multiGetContentSummary_result>   {
+    private static final TStruct STRUCT_DESC = new TStruct("multiGetContentSummary_result");
+
+    private static final TField SUCCESS_FIELD_DESC = new TField("success", TType.LIST, (short)0);
+    private static final TField ERR_FIELD_DESC = new TField("err", TType.STRUCT, (short)1);
+
+    public List<ContentSummary> success;
+    public org.apache.hadoop.thriftfs.api.IOException err;
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements TFieldIdEnum {
+      SUCCESS((short)0, "success"),
+      ERR((short)1, "err");
+
+      private static final Map<Integer, _Fields> byId = new HashMap<Integer, _Fields>();
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byId.put((int)field._thriftId, field);
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        return byId.get(fieldId);
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+
+    // isset id assignments
+
+    public static final Map<_Fields, FieldMetaData> metaDataMap = Collections.unmodifiableMap(new EnumMap<_Fields, FieldMetaData>(_Fields.class) {{
+      put(_Fields.SUCCESS, new FieldMetaData("success", TFieldRequirementType.DEFAULT, 
+          new ListMetaData(TType.LIST, 
+              new StructMetaData(TType.STRUCT, ContentSummary.class))));
+      put(_Fields.ERR, new FieldMetaData("err", TFieldRequirementType.DEFAULT, 
+          new FieldValueMetaData(TType.STRUCT)));
+    }});
+
+    static {
+      FieldMetaData.addStructMetaDataMap(multiGetContentSummary_result.class, metaDataMap);
+    }
+
+    public multiGetContentSummary_result() {
+    }
+
+    public multiGetContentSummary_result(
+      List<ContentSummary> success,
+      org.apache.hadoop.thriftfs.api.IOException err)
+    {
+      this();
+      this.success = success;
+      this.err = err;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public multiGetContentSummary_result(multiGetContentSummary_result other) {
+      if (other.isSetSuccess()) {
+        List<ContentSummary> __this__success = new ArrayList<ContentSummary>();
+        for (ContentSummary other_element : other.success) {
+          __this__success.add(new ContentSummary(other_element));
+        }
+        this.success = __this__success;
+      }
+      if (other.isSetErr()) {
+        this.err = new org.apache.hadoop.thriftfs.api.IOException(other.err);
+      }
+    }
+
+    public multiGetContentSummary_result deepCopy() {
+      return new multiGetContentSummary_result(this);
+    }
+
+    @Deprecated
+    public multiGetContentSummary_result clone() {
+      return new multiGetContentSummary_result(this);
+    }
+
+    public int getSuccessSize() {
+      return (this.success == null) ? 0 : this.success.size();
+    }
+
+    public java.util.Iterator<ContentSummary> getSuccessIterator() {
+      return (this.success == null) ? null : this.success.iterator();
+    }
+
+    public void addToSuccess(ContentSummary elem) {
+      if (this.success == null) {
+        this.success = new ArrayList<ContentSummary>();
+      }
+      this.success.add(elem);
+    }
+
+    public List<ContentSummary> getSuccess() {
+      return this.success;
+    }
+
+    public multiGetContentSummary_result setSuccess(List<ContentSummary> success) {
+      this.success = success;
+      return this;
+    }
+
+    public void unsetSuccess() {
+      this.success = null;
+    }
+
+    /** Returns true if field success is set (has been asigned a value) and false otherwise */
+    public boolean isSetSuccess() {
+      return this.success != null;
+    }
+
+    public void setSuccessIsSet(boolean value) {
+      if (!value) {
+        this.success = null;
+      }
+    }
+
+    public org.apache.hadoop.thriftfs.api.IOException getErr() {
+      return this.err;
+    }
+
+    public multiGetContentSummary_result setErr(org.apache.hadoop.thriftfs.api.IOException err) {
+      this.err = err;
+      return this;
+    }
+
+    public void unsetErr() {
+      this.err = null;
+    }
+
+    /** Returns true if field err is set (has been asigned a value) and false otherwise */
+    public boolean isSetErr() {
+      return this.err != null;
+    }
+
+    public void setErrIsSet(boolean value) {
+      if (!value) {
+        this.err = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case SUCCESS:
+        if (value == null) {
+          unsetSuccess();
+        } else {
+          setSuccess((List<ContentSummary>)value);
+        }
+        break;
+
+      case ERR:
+        if (value == null) {
+          unsetErr();
+        } else {
+          setErr((org.apache.hadoop.thriftfs.api.IOException)value);
+        }
+        break;
+
+      }
+    }
+
+    public void setFieldValue(int fieldID, Object value) {
+      setFieldValue(_Fields.findByThriftIdOrThrow(fieldID), value);
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case SUCCESS:
+        return getSuccess();
+
+      case ERR:
+        return getErr();
+
+      }
+      throw new IllegalStateException();
+    }
+
+    public Object getFieldValue(int fieldId) {
+      return getFieldValue(_Fields.findByThriftIdOrThrow(fieldId));
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      switch (field) {
+      case SUCCESS:
+        return isSetSuccess();
+      case ERR:
+        return isSetErr();
+      }
+      throw new IllegalStateException();
+    }
+
+    public boolean isSet(int fieldID) {
+      return isSet(_Fields.findByThriftIdOrThrow(fieldID));
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof multiGetContentSummary_result)
+        return this.equals((multiGetContentSummary_result)that);
+      return false;
+    }
+
+    public boolean equals(multiGetContentSummary_result that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_success = true && this.isSetSuccess();
+      boolean that_present_success = true && that.isSetSuccess();
+      if (this_present_success || that_present_success) {
+        if (!(this_present_success && that_present_success))
+          return false;
+        if (!this.success.equals(that.success))
+          return false;
+      }
+
+      boolean this_present_err = true && this.isSetErr();
+      boolean that_present_err = true && that.isSetErr();
+      if (this_present_err || that_present_err) {
+        if (!(this_present_err && that_present_err))
+          return false;
+        if (!this.err.equals(that.err))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public int compareTo(multiGetContentSummary_result other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+      multiGetContentSummary_result typedOther = (multiGetContentSummary_result)other;
+
+      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(isSetSuccess());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      lastComparison = TBaseHelper.compareTo(success, typedOther.success);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      lastComparison = Boolean.valueOf(isSetErr()).compareTo(isSetErr());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      lastComparison = TBaseHelper.compareTo(err, typedOther.err);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      return 0;
+    }
+
+    public void read(TProtocol iprot) throws TException {
+      TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == TType.STOP) { 
+          break;
+        }
+        _Fields fieldId = _Fields.findByThriftId(field.id);
+        if (fieldId == null) {
+          TProtocolUtil.skip(iprot, field.type);
+        } else {
+          switch (fieldId) {
+            case SUCCESS:
+              if (field.type == TType.LIST) {
+                {
+                  TList _list28 = iprot.readListBegin();
+                  this.success = new ArrayList<ContentSummary>(_list28.size);
+                  for (int _i29 = 0; _i29 < _list28.size; ++_i29)
+                  {
+                    ContentSummary _elem30;
+                    _elem30 = new ContentSummary();
+                    _elem30.read(iprot);
+                    this.success.add(_elem30);
+                  }
+                  iprot.readListEnd();
+                }
+              } else { 
+                TProtocolUtil.skip(iprot, field.type);
+              }
+              break;
+            case ERR:
+              if (field.type == TType.STRUCT) {
+                this.err = new org.apache.hadoop.thriftfs.api.IOException();
+                this.err.read(iprot);
+              } else { 
+                TProtocolUtil.skip(iprot, field.type);
+              }
+              break;
+          }
+          iprot.readFieldEnd();
+        }
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(TProtocol oprot) throws TException {
+      oprot.writeStructBegin(STRUCT_DESC);
+
+      if (this.isSetSuccess()) {
+        oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+        {
+          oprot.writeListBegin(new TList(TType.STRUCT, this.success.size()));
+          for (ContentSummary _iter31 : this.success)
+          {
+            _iter31.write(oprot);
+          }
+          oprot.writeListEnd();
+        }
+        oprot.writeFieldEnd();
+      } else if (this.isSetErr()) {
+        oprot.writeFieldBegin(ERR_FIELD_DESC);
+        this.err.write(oprot);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("multiGetContentSummary_result(");
+      boolean first = true;
+
+      sb.append("success:");
+      if (this.success == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.success);
+      }
+      first = false;
+      if (!first) sb.append(", ");
+      sb.append("err:");
+      if (this.err == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.err);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws TException {
+      // check for required fields
+    }
+
+  }
+
   public static class setQuota_args implements TBase<setQuota_args._Fields>, java.io.Serializable, Cloneable   {
     private static final TStruct STRUCT_DESC = new TStruct("setQuota_args");
 

+ 10 - 0
desktop/libs/hadoop/java/if/hdfs.thrift

@@ -191,6 +191,9 @@ struct ContentSummary {
   
   /** Quota consumed in disk (in bytes). */
   5: i64 spaceQuota,  
+
+  /** The path */
+  6: string path,
 }
 
 struct UpgradeStatusReport {
@@ -388,6 +391,13 @@ service Namenode extends common.HadoopServiceBase {
    */
   ContentSummary getContentSummary(10: common.RequestContext ctx,
                                    1:  string Path) throws (1: common.IOException err),
+
+  /**
+   * Get ContentSummary objects for multiple directories simultaneously. The same warnings
+   * apply as for getContentSummary(...) above.
+   */
+  list<ContentSummary> multiGetContentSummary(10: common.RequestContext ctx,
+                                              1: list<string> paths) throws (1: common.IOException err),
   
   /**
    * Set the quota for a directory.

+ 27 - 2
desktop/libs/hadoop/java/src/java/org/apache/hadoop/thriftfs/NamenodePlugin.java

@@ -418,8 +418,7 @@ public class NamenodePlugin
       assumeUserContext(ctx);
       LOG.debug("getContentSummary(" + path + "): Entering");
       try {
-        ContentSummary cs = ThriftUtils.toThrift(
-          namenode.getContentSummary(path));
+        ContentSummary cs = getContentSummary(path);
         LOG.debug("getContentSummary(" + path + "): Returning " + cs);
         return cs;
       } catch (Throwable t) {
@@ -428,6 +427,32 @@ public class NamenodePlugin
       }
     }
 
+    public List<ContentSummary> multiGetContentSummary(RequestContext ctx, List<String> paths)
+        throws IOException, TException {
+        assumeUserContext(ctx);
+        LOG.debug("multiGetContentSummary(" + paths + "): Entering");
+        List<ContentSummary> ret = new ArrayList<ContentSummary>();
+        try {
+            for (String path : paths) {
+                ret.add(getContentSummary(path));
+            }
+        } catch (Throwable t) {
+            LOG.info("multiGetContentSummary(" + paths + "): Failed", t);
+            throw ThriftUtils.toThrift(t);
+        }
+        LOG.debug("multiGetContentSummary(" + paths + "): Returning " + ret);
+        return ret;
+    }
+
+    private ContentSummary getContentSummary(String path) throws java.io.IOException {
+        try {
+            return ThriftUtils.toThrift(namenode.getContentSummary(path), path);
+        } catch (java.io.IOException e) {
+            LOG.error(e);
+            throw e;
+        }
+    }
+
     public boolean unlink(RequestContext ctx, String path, boolean recursive) throws IOException,
         TException {
       assumeUserContext(ctx);

+ 2 - 1
desktop/libs/hadoop/java/src/java/org/apache/hadoop/thriftfs/ThriftUtils.java

@@ -83,13 +83,14 @@ public class ThriftUtils {
                      b.getGenerationStamp(), block.getStartOffset(), nodes);
   }
 
-  public static ContentSummary toThrift(org.apache.hadoop.fs.ContentSummary cs) {
+  public static ContentSummary toThrift(org.apache.hadoop.fs.ContentSummary cs, String path) {
     ContentSummary tcs = new ContentSummary();
     tcs.fileCount = cs.getFileCount();
     tcs.directoryCount = cs.getDirectoryCount();
     tcs.quota = cs.getQuota();
     tcs.spaceConsumed = cs.getSpaceConsumed();
     tcs.spaceQuota = cs.getSpaceQuota();
+    tcs.path = path;
     return tcs;
   }
 

+ 4 - 0
desktop/libs/hadoop/src/hadoop/fs/hadoopfs.py

@@ -210,6 +210,10 @@ class HadoopFileSystem(object):
     stats = self.nn_client.ls(self.request_context, normpath(path))
     return [self._unpack_stat(s) for s in stats]
 
+  @_coerce_exceptions
+  def get_content_summaries(self, paths):
+    return self.nn_client.multiGetContentSummary(self.request_context, [normpath(path) for path in paths])
+
   @_coerce_exceptions
   def rename(self, old, new):
     success = self.nn_client.rename(