Neben 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:
Den aktuellen Stand dieser Entwicklung, stelle ich auf GitHub zur Verfügung:
https://github.com/SaschaDittmann/HdfsExplorer
Weitere Informationen