Hacking just for Fun: Raid5 in Java

I was just curious how easy it might be to write a RAID5 compatible Outputstream in Java? Just a few Lines. For sure it is not the most elegante solution. Especially if you see the nice possibility to integrate one Outputstream within another… so maybe two Raid5s into one Raid0 Stream? (would be RAID50) then. Reading is missing ;-).

/**
 * Raid5Stream
 * 31.03.2012
 * @author Philipp Haussleiter
 *
 */
package de.javastream.jraid;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Raid5Stream extends OutputStream {

    public final static int PARITY_MARKER = 1;
    public final static int DATA_MARKER = 0;
    private File disks[];
    private FileOutputStream streams[];
    private int mode = 0;
    private final static int MAX_MODE = 2;
    private int[] buffer = new int[2];

    public Raid5Stream(File disks[]) throws IOException {
        super();
        if (disks.length != 3) {
            throw new RuntimeException("we need a disk count of x times 3");
        }
        int i = 0;
        this.disks = new File[disks.length];
        this.streams = new FileOutputStream[disks.length];
        for (File f : disks) {
            if (!f.exists() && !f.createNewFile()) {
                throw new RuntimeException(f.getAbsolutePath() + " does not exists and cannot be created!");
            } else {
                System.out.println("using " + f.getAbsolutePath() + "\n");
                this.disks[i] = f;
                this.streams[i] = new FileOutputStream(f);
            }
            i++;
        }
        writerMarker();
    }

    private void writerMarker() throws IOException {
        for (int i = 0; i < this.streams.length; i++) {
            if (i % 3 == 0) {
                this.streams[i].write(PARITY_MARKER);
            } else {
                this.streams[i].write(DATA_MARKER);
            }
        }
    }

    @Override
    public void write(int i) throws IOException {
        switch (mode) {
            case MAX_MODE:
                this.streams[mode].write(buffer[0] ^ buffer[1]);
                mode = 0;
            default:
                this.buffer[mode] = i;
                this.streams[mode].write(i);
                mode++;
        }
    }
}

Using it is easy as:

...
public class App {

    public static void main(String[] args) throws IOException {
        File raid5_disk1 = new File("raid5.disk1");
        File raid5_disk2 = new File("raid5.disk2");
        File raid5_disk3 = new File("raid5.disk3");
        long count = 0;
        Raid5Stream raid5Stream = new Raid5Stream(new File[]{raid5_disk1, raid5_disk2, raid5_disk3});
        FileInputStream in = new FileInputStream("/dev/random");
        BufferedInputStream bis = new BufferedInputStream(in);
        BufferedOutputStream raid5bos = new BufferedOutputStream(raid5Stream);
        while(count < 1024*1024*2){
            raid5bos.write(bis.read());
            count++;
        }
        raid5bos.close();
        bis.close();
    }
}

Good sources for more reading are the Wikipedia Articles about RAID and XOR.

SVG – the lost son of formats

I was on the Chemnitz Linux Days last weekend. Besides great other talks a saw “Free your slides – Vortragsfolien im Browser anzeigen” from Sirko Kemter. He talked about a tiny tool called jessyink for creating Slides out of inkscape SVGs. I did a small SVG-Demo some months ago using RaphaelJS and a draft about this project exists since then. So instead of trying to complete this draft and published it, i decided to ask what area of SVG might be of interest here. Basic SVG elements? Animation? It might need some time, but i re-discovered what a great format SVG is and really want to create some posts for that.

 

Run local/remote terminal commands with java using ssh

Sometimes you need to use some CLI-Tools before you want to create or search for a native JNI Binding.
So there is a common way, using the Java Process-Class. But then you might meet two problems i had to face in the past during several problems:

  1. There are (a really small) number of CLI-Tools, that giving no constant output over the STD-OUT (the standard output the Process-Class uses for output)
  2. There is no “elegant” way to implement a process call into your project.

To solve this Problem I created a basic HelperClass, that calls the System over SSH (with the Convenience to work remote and the side-effect to always get STD-compatible output).
I am primarely using it for a fun project SAM i started some months ago to try to create a Management-Tool for Unices and Windows with a very low client-side footprint.

The first Class is used to capsulate the basic SSH Calls:

 
// some imports... 
 public class SystemHelper {
    private Runtime r;
    private String sshPrefix = "";

    // call with $user and 127.0.0.1 to run local command.     
    public SystemHelper(String user, String ip) {
        r = Runtime.getRuntime();
        sshPrefix = " ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no " + user + "@" + ip;
    }

    public void runCommand(String command, ProcessParser pp) {
        try {
            Logger.info("running: " + this.sshPrefix + " " + command);
            Process p = r.exec(this.sshPrefix + " " + command);
            InputStream in = p.getInputStream();
            BufferedInputStream buf = new BufferedInputStream(in);
            InputStreamReader inread = new InputStreamReader(buf);
            BufferedReader bufferedreader = new BufferedReader(inread);
            pp.parse(bufferedreader);
            try {
                if (p.waitFor() != 0) {
                    Logger.info("exit value = " + p.exitValue());
                }
            } catch (InterruptedException e) {
                System.err.println(e);
            } finally {
                // Close the InputStream                 
                bufferedreader.close();
                inread.close();
                buf.close();
                in.close();
            }
        } catch (IOException ex) {
            Logger.error(ex.getLocalizedMessage());
        }
    }
}

ProcessParser is an interface that defines the methode parse, accepting a BufferedReader for parsing the output of the Process. Unfortunately there is no timeout ATM to kill a hanging SSH-Call.

 public interface ProcessParser { 
     public void parse(BufferedReader bufferedreader); 
 } 

The most basic (Output-)Parser looks like this:

 
    public String getPublicSSHKey() {
        SimpeOutputPP so = new SimpeOutputPP();
        String command = "cat ~/.ssh/id_rsa.pub";
        runCommand(command, so);
        if (!so.getOutput().isEmpty()) {
            return so.getOutput().get(0);
        }
        return "";
    }

This returns just the public SSH-Key of the current user. I implemented some more parsers for the output of apt (dpkg), rpm and pacman. You can find them in the github project here.