Native Zugriffe auf’s Hadoop Distributed File System (HDFS) mit .NET

HDFS Zugriffe mit .NETNeben der, bei Apache Hadoop mitgelieferten und in C geschriebenen, HDFS Klassenbibliothek "C API libhdfs", liefert Microsoft bei der Windows Azure HDInsight Preview auch eine C++ Variante mit.
Mit Hilfe dieser Klassenbibliothek, kann man somit auch aus .NET auf das Hadoop Distributed File System zugreifen…

Mit der vor kurzen bekannt gegebenen "Microsoft HDInsight für Windows Server"-Preview, wurde auch das Microsoft .NET SDK For Hadoop (in der Version v0.0.4) veröffentlicht.

Ein kurzer Blick auf die HdfsFile Klasse zeigt allerdings, dass dieses noch ein wenig in der Kinderschuhen steckt:

/// <summary>
/// Writes all bytes.
/// </summary>
/// <param name="hdfsPath">The HDFS path.</param>
/// <param name="bytes">The bytes.</param>
public static void WriteAllBytes(string hdfsPath, byte[] bytes)
{
  string tempPath = System.IO.Path.GetTempFileName();
  File.WriteAllBytes(tempPath, bytes);

  ProcessUtil.RunHadoopCommand_ThrowOnError(
    EnvironmentUtils.PathToHadoopExe,
    string.Format(
      "fs -moveFromLocal "{0}" "{1}"", 
      tempPath, hdfsPath), 
    false);
}

 

Jede Dateioperation wird lokal durchgeführt und mit dem Hadoop Kommandozeilentool ins bzw. vom HDFS transferiert.

Die "Windows HDFS Managed library (WinHdfsManaged)" hingegen setzt auf der, bei Hadoop mitgelieferten, HDFS Klassenbibliothek auf.

Der Quellcode, sowie eine kompilierte Version dieser Klassenbibliothek, liegt auf dem Headnode-Server des Windows Azure HDInsight Clusters (C:AppsdistcontribWinLibHdfs).

Da nicht jeder einen Zugriff auf die Windows Azure HDInsight Preview hat, habe ich die kompilierte Version der aktuelle WinHdfsManaged-Klassenbibliothek diesem Blog Post angehängt.

 

Beispiele zur Verwendung

Um mit der WinHdfsManaged-Klassenbibliothek Dateisystemoperationen durchführen zu können, muss man zuerst eine Verbindung zum Namenode-Server herstellen.

Hierzu verwendet man die Connect-Methode der HdfsFileSystem-Klasse:

using (var hdfsSystem = HdfsFileSystem.Connect("127.0.0.1", 8020))
{
  // ...
}

 

Anschließend kann beispielsweise die ListDirectory-Methode aufrufen, um die Verzeichnisse und Dateien eines angegebenen Pfades anzeigen zu lassen…

using (var entries = fileSystem.ListDirectory("/"))
{
  if (entries.Entries != null)
    foreach (var entry in entries.Entries)
    {
      Console.WriteLine("{0}t{1}t{2:#,0}",
        entry.Name, entry.Kind, entry.Size);    
    }
}

 

Konsolenausgabe des Beispiels

hdfs://127.0.0.1:8020/WordCount.js  File       806
hdfs://127.0.0.1:8020/hdfs          Directory  0
hdfs://127.0.0.1:8020/mapred        Directory  0
hdfs://127.0.0.1:8020/tmp           Directory  0
hdfs://127.0.0.1:8020/user          Directory  0

 

… oder mittels GetPathInfo-Methode einzelne Elemente.

using (var entry = fileSystem.GetPathInfo("/WordCount.js"))
{
  if (entry != null)
    Console.WriteLine("{0}t{1}t{2:#,0}",
      entry.Name, entry.Kind, entry.Size);
}

 

Dateien können auf verschiedene Weisen gelesen bzw. geschrieben werden:

Auslesen einer Textdatei

using (var fileHandle = fileSystem.OpenFileForRead("/WordCount.js"))
{
    string line;
    while ((line = fileHandle.ReadLine())!=null)
    {
        Console.WriteLine(line);
    }
}

 

Kopieren einer HDFS Datei nach Lokal (mit einem Stream-Objekt)

using (var hdfsStream = fileSystem.OpenFileStream("/WordCount.js", 
  HdfsFileAccess.Read))
{
  using (var fileStream = new FileStream("C:\WordCount.js", 
    FileMode.Create, FileAccess.Write))
  {
    hdfsStream.CopyTo(fileStream);
  }
}

 

Kopieren einer HDFS Datei nach Lokal (mit einem Byte-Array)

var buffer = new byte[512];
using (var fileHandle = fileSystem.OpenFileStream("/WordCount.js",
  HdfsFileAccess.Read, buffer.Length))
{
  using (var fileStream = new FileStream("C:\WordCount.js", 
    FileMode.Create, FileAccess.Write))
  {
    int lengthRead;
    while ((lengthRead = fileHandle.Read(buffer, 0, buffer.Length)) > 0)
    {
      fileStream.Write(buffer, 0, lengthRead);
    }
  }
}

 

Schreiben einer HDFS Datei (Byteweise)

var data = File.ReadAllBytes("C:\WordCount.js");
using (var file = fileSystem.OpenFileStream("/WordCount.js",
  HdfsFileAccess.Write, 512))
{
  file.Write(data, 0, data.Length);
  file.WriteByte((byte)10);
  file.Flush();
}

 

Auch das Verändern von Dateieigenschaften lässt sich mit der WinHdfsManaged-Klassenbibliothek durchführen.

Besitzer und Dateizeiten festlegen

fileSystem.Chown("/WordCount.js","hadoop","supergroup");
var modifiedTime = DateTime.Now.AddDays(-10);
var accessedTime = DateTime.Now.AddDays(-1);
fileSystem.SetTimes("/WordCount.js", modifiedTime, accessedTime);

 

HDFS Explorer

Inspiriert von dieser Klassenbibliothek, habe ich angefangen einen HDFS Explorer für Windows zu entwicklen:

HDFS Explorer für Windows

Den aktuellen Stand dieser Entwicklung, stelle ich auf GitHub zur Verfügung:

https://github.com/SaschaDittmann/HdfsExplorer

 


Check Also

Time Machine Backups nach Microsoft Azure

Seit einigen Jahren verwende ich eine Apple Time Capsule, um meine Time Machine Backups an einem zentralen Ort speichern zu können. Bislang hatte das für mich auch vollkommen ausgereicht. Seitdem ich jedoch immer mehr unterwegs bin, habe ich nach einer Lösung gesucht, die ich auch von unterwegs nutzen kann. In diesem Blog Post zeige ich deshalb, wie man Time Machine Backups nach Microsoft Azure machen kann.