code: boolean doMerge(String[] srcDataDirs, Collection<File> dstDataDirs, 
        int namespaceId, NamespaceInfo nsInfo, StartupOption startOpt) 
      throws IOException {
      HashMap<File, File> dirsToMerge = new HashMap<File, File>();
      int i = 0;
      for (Iterator<File> it = dstDataDirs.iterator(); it.hasNext(); i++) {
        File dstDataDir = it.next();
        if (dstDataDir.exists()) {
          continue;
        }
        File srcDataDir = NameSpaceSliceStorage.getNsRoot(
            namespaceId, new File(srcDataDirs[i], STORAGE_DIR_CURRENT));
        if (!srcDataDir.exists() || !srcDataDir.isDirectory()) {
          LOG.info("Source data directory " +
              srcDataDir + " doesn't exist.");
          continue;
        }
        dirsToMerge.put(srcDataDir, dstDataDir);
      }
      if (dirsToMerge.size() == 0)
        //No merge is needed
        return false;
      
      if (dirsToMerge.size() != dstDataDirs.size()) {
        // Last merge succeeds partially
        throw new IOException("Merge fail: not all directories are merged successfully.");
      }
      
      MergeThread[] mergeThreads = new MergeThread[dirsToMerge.size()];
      // start to merge
      i = 0;
      for (Map.Entry<File, File> entry: dirsToMerge.entrySet()) {
        MergeThread thread = new MergeThread(entry.getKey(), entry.getValue(), nsInfo);
        thread.start();
        mergeThreads[i] = thread;
        i++;
      }
      // wait for merge to be done
      for (MergeThread thread : mergeThreads) {
        try {
          thread.join();
        } catch (InterruptedException e) {
          throw (InterruptedIOException)new InterruptedIOException().initCause(e);
        }
      }
      // check for errors
      for (MergeThread thread : mergeThreads) {
        if (thread.error != null)
          throw new IOException(thread.error);
      }
      return true;
    }
docs: merge the data directory from srcDataDirs to dstDataDirs
  @return true if merge succeeds; false if no merge happens