Telegramm eines iPhone Kaufs

In guter alter Tradition, möchte ich hier noch einmal in kurzen Worten die Gegebenheiten am vorigen “iPhone 3G Freitag” beschreiben:

08:00: Der Wecker schellt. In froher Erwartung schwinge ich mich aus dem Bett und heize den Kaffeeautomaten an. In Anbetracht der letzten iPhone-Einführung in Deutschland gehe ich den Morgen gelassen an. Mein Mitstreiter des Tages hat vorsorglich ja zwei iPhöne reservieren lassen.
09:00: Nach Kaffee und Duschen fahre ich mit dem Auto zur U-Bahn und mit der U-Bahn weiter in die Stadt… Wer weiß, vielleicht gibt es doch Andrang und die Stadt ist dicht.
09:15: Nachricht vom Mitstreiter, bei ihm wird es wohl doch 09:30. Ich kämpfe mich (Müdigkeit) zum T-Punkt vor. Ich sehe eine _kleine_ Schlange von 5 Leuten, davon ist einer ein hyperaktiv-telefonierender und vor-der-Tür-parkender Audi A4 Fahrer, ein anderer trägt ein dezent S/W Apple-T-Shirt. Im Lauf der nächsten 10min wächst die Schlange um zwei weitere Kunden, die wild gestikulierend mit einer – scheinbar falschen – Telefonrechnung herumfuchteln. 
09:25:  Entwarnung. Ich entschließe mich dazu, einen Kaffee nachzutanken. Ich begebe mich zum nahen Stern-Bock und bestelle einen regular Cafe Mocá.
09:27: Sie sind heute schnell. Ich erhalte einen tall Cafe Mocá. War wohl ein Missverständnis. Ich beschließe, dass der Tag gut werden wird und steuere wieder das T an.
09:35:  Der Mitstreiter trifft ein. Lagebesprechung. Wir betrachten argwöhnisch den schon gefüllten T-Punkt. Beschließen was zu tun ist und legen uns eine Schlangen-ansteh-Strategie zurecht.
09:45:  Der T-Punkt ist nicht pber das normale Maß gefüllt, dennoch scheint der wohlige Geruch von Stress und Sonderaktion in er Luft zu liegen und Verkäuferinnen und Verkäufer hetzen mit gehetzten Blicken vom Lager zum Verkaufsraum. Wir entscheiden uns für eine Zwei-Schlangen-Strategie (okay für mehr fehlen uns eh die Leute :-D).
09:55:  Der große Moment. Wir haben unsere eigene Telekommunikationsfachkraft. Die gute Frau ist voll Echtzeitmultitasking-fähig und scheint mindestens über 10 Kerne zu verfügen.
10:00:  Wir ordern. Die Vorbestellungen scheinen – natürlich – nicht mehr auffindbar zu sein. Anscheinend hat jeder Verkäufer seine eigene Hitlist erstellt und mit nach Hause genommen. Dennoch erhalten wir zwei schwarze 16GB Modelle.
10:25: Ich bin an der Reihe. Ich erhalte (nach Aussage der threaded-Verkäuferin) das letzte iPhone des Ladens (ob das jetzt nur die 16GB Version betrifft steht noch im Raum). Die Verpackung ist aus unerfindlichen Gründen vor-geöffnet worden. Egal. Nach kurzer Sichtkontrolle greife ich zu. Ich muss doch keine 25 EUR Bereitstellung zahlen (Aktion! 🙂 ), allerdings kann ich JETZT meine alte Nummer nicht übernehmen (Aktion! 🙁 ). Wenn ich das wollte müsste ich nächste Woche Dienstag wiederkommen. Ich betrachte die sanft-glänzende Apple-Verpackung und erinnere mich daran als ich das letzte Mal wegen Klein-Foo in einen T-Punkt gehen wollte. Ich entschließe mich dazu, die logistische Herausforderung einer neuen-Nummer-Verteilung in meinem Social-Network in Kauf zu nehmen. 
10:45: Ich ordere eine Multi-SIM Karte mit dem Plan, den iPhone Tarif auch mit anderen Devices nutzen zu können. Ich werde gefühlte 100 Mal darauf aufmerksam gemacht, dass die zusätzliche SIM einmalig 30 EUR kostet. Bestellung fertig: 

    Ich erhalte: 

  • 1 EA iPhone (ohne DOCK!)
  • 2 EA SIM-Karten
  • 1 neue Nummer (Juhu es ist eine 0151er – ich habe heute erfahren, dass die aus dem alten C-Netz stammen)
11:00: I  Ich zahle. Und erhalte zusätzlich zwei Karten für das Fußballspiel Bayern gegen Bor. Dortmund am 23. Juli. Leider bin ich an dem Tag nicht in Deutschland, aber ich bin sicher, dass ich dafür Abnehmer finden werde. Ich entscheide mich gegen die durchsichtige Silikon-Schutzhülle. Ich möchte etwas dunkleres… Gibt es fürs alte iPhone (hehe wie schnell die Technik veraltet). Ich zahle nur das iPhone. DIe Multi-SIM scheint vergessen. Ich schaue in mein Shopping-Bag, sehe zwei Umschläge und verlasse schmunzelnd den Laden. ich beschließe das der Tag gut wird.
11:30: Wir lassen uns im Edwards nieder. In Erwartung von freiem WiFi, bestellen wir unsere Getränke und entpacken unsere iPhöne. Dummerweise scheint grade heute das WiFi ausgefallen zu sein (Verschwörung!!!!). Wir leeren unser Bestelltes und schlagen den Weg nach Hause ein.
12:15:  Wir erreichen Home, Sweet Home. Das WiFi ist vorhanden und stabil. Wir füllen den Tisch mit Apple-Devotionalien. Wir verbinden iPhone mit Macbook (pro), Macbook (pro) mit WiFi und starten iTunes.
12:30:  Nach einem – nervenden – iTunes-Update beginnt die Aktivierung des iPhones. Schnell die neue Nummer rausgesucht und mit iTunes Account abgeglichen.
12:45:  Ich erhalte meinen ersten Anruf auf meinen iPhone. Ein Herr Maier oder Müller. Wunder sich, dass ich ich bin. Komisch. Meine Nummer scheint noch nicht lange ungenutzt zu sein.
13:00:  Wir Updaten unsere iPhone-Firmware. Ich erkenne, dass mein iPhone mit meinen Kontakten kämpft. Ich schaue nach – nein keine großen Dateien. Nach gefühlten 30 min synchronisieren nun Email- und Browsereinstellungen. Done. Ich buche mein iPhone in mein heimatliche WiFi ein. Nettes Teil. Ich beschließe, dass der Tag gut ist.
14:00:  Wir entdecken den AppStore. Wir installieren uns zahlreiche (hmmm 10?) der kostenlosen Anwendungen. Remote ist cool. Auch LifeGame lässt den Programmierer in mir aufleben. Freudig entdecke ich den AIM-Client.
14:30:  Wir beschließen nun die Dev-Tools zu testen. Wir installieren “the latest iPhone-SDK”.
15:15: Der Hunger meldet sich. Wir gehen zu dem Chinesen gegenüber. Der schließt leider um 15h. Wir müssen hungrig aussehen. Aus Mitleid wird uns angeboten, dass wir uns etwas Bestellen können und es dann mitnehmen können. Netter Laden, toller Service. Wir bestellen beide das gleiche (schlechtes Gewissen ^^), geben Trinkgeld und verlassen das Lokal gen Heimat.
15:30: Wir essen. iPhone-Display ist “Fett”-proofed!
15:45:  Ich teste den HW-Modes der Dev-Tools. XCode-Organizer schlägt vor, die aktuelle Firmware aufs iPhone zu spielen. Ich stimme zu (noch ist der Tag gut)
16:00:  Mein iPhone ist wieder im Auslieferungszustand und möchte sich wieder neu aktivieren lassen. Ich starte iTunes und beginne den Vorgang. Ich erhalte wahlweise Fehler -9838 oder -4 (negativere Fehlernummer sind die schlechteren?). Ich fluche ein wenig. Stelle mich darauf ein, am morgigen Samstag mich in einen T-Punkt zu kämpfen. Ich lade noch einmal manuell per iTunes die Firmware aufs iPhone. Kein Erfolg. SIM-Lock weg und iTunes bockt? Ich schmeiße Google an. Finde den netten Thread auf FSCKLOG. Ich lese mich durch die 200 Kommentare und stelle fest, dass ich nicht alleine bin. Hatten wir morgens wohl sehr viel Glück und nun Pech.
17:30: -9838 … -4
17:30: -9838 … -4
18:00: -9838 … -4
18:15: -4 (Fehler -9838 scheint behoben – erkommt jedenfalls nicht mehr). Ich beschließe meine iPhone-Playlist zu füllen.
18:30: Aus Frust fahre ich Auto. Ich bringe meinen Mitstreiter zum abendlichen Workout.
19:00: Mache Dinge die mich ablenken. (Fotos scannen)
21:00: -4
21:15: -4
22:30: -4
23:15: Kein Fehler. “Kann iTunes Store nicht erreichen”.
23:30: Aktivierung geht. Der Tag findet ein gutes Ende. Ich kann mein iPhone wieder einrichten. Synchronisiere abermals Kontakte (30min), Musik, Bilder und Videos (20min).
00:00: Ich sehe mir noch ein paar der DEV-Videos an und schlafe ein.
Blogged with the Flock Browser

eingescannte Bilder konvertieren und Timestamp setzen

Da ich die letzten Tage gezwungenermaßen sehr viel Zeit hatte (warum kommt später) und ich irgendwie mal Grund in meine Kisten und Boxen bringen möchte, habe ich angefangen, meine (Papier-) Fotos einzuscannen und in iPhoto zu übertragen.

Die Frage stelle sich mir nun, wie ich aus 200 Tiff Dateien die das aktuelle Datum tragen (also das des Scans) ordentliche Digitalbilder hinkriege, sodass sie A) nicht zuviel Platz wegnehmen und B) nicht alle auf einen Tag datiert sind. Als Datum reicht mir erstmal nur der jeweilige Monat des Jahres.

Nachdem ich von freundlichen Mitmenschen (danke Willem, danke Christoph) mit geeigneten Shellscripten versorgt worden bin, war die Sache mit der Dateigröße vom Tisch der folgende Einzeiler macht das recht gut:

     for i in `ls`; do convert $i neues_verzeichnis/$i.png; done

Nicht vergessen: “neues_Verzeichnis” natürlich anpassen und das ganze (wenn man es denn in eine Datei packt) chmod +x setzen.
Aber das reichte mir ja nicht ^^

Und was mache ich, wenn ich gar nicht mehr anders kann? Ich nutze PHP…. gute, alte, unübersichtliche Scriptsprache.
Well… thats the Code:


    <?php
    if(count($argv) < 2) die(“Usage:\n php -f convert.php — -filetype -month -year\n php -f convert.php — -png -07 – 1997\n _MIND THE — !!_ \n”);
    $sdir = getcwd ();
    echo “Sourcefolder: “.$sdir.” …\n”;
    $tdir = $sdir.”/converted”;
    $ext = substr($argv[1], 1);
    $month = substr($argv[2], 1);
    $year = substr($argv[3], 1);
    echo “$ext-$month-$year\n”;
    $time = mktime(12, 0, 0, $month, 15, $year);
    echo $time.”\n”;
    @mkdir($tdir);
    if ($handle = @opendir($sdir)) {
        while (false !== ($file = readdir($handle)))
            if($file != “.” and $file != “..” and $file != “converted”){
            $filearray = explode(“.”, $file);
            array_pop($filearray);
            $newfile = $tdir.”/”.implode(“.”, $filearray).”.png”;
            echo “convert $sdir/$file $newfile\n”;
            system ( “convert $sdir/$file $newfile” );
            echo “set Date to: “.date(“d.m.y”, $time).”\n”;
            touch ($newfile, $time);
        }
    }
    ?>


Tut genau das was es soll…
Aufgerufen wird er mit

    php -f convert.php

Danach wird einem gesagt, was man an Parametern übergeben kann/soll/darf/muss.
Nun bleibt mir nur noch, mich mit meiner eigenen Vergangenheit in Form von Fotos konfrontiert zu sehen ^^.

Blogged with the Flock Browser

subversion problem: svn: Can’t move ‘xyz/.svn/tmp/entries’ to ‘xyz/.svn/entries’: Operation not permitted

svn: Can't move 'xyz/.svn/tmp/entries' to 'xyz/.svn/entries': Operation not permitted

Diese Fehler sprang mir grade entgegen, nachdem ich mal wieder ein

svn up

machen wollte.
Nach genauerer Betrachtung, stellte ich dann fest, dass

xyz/.svn/entries

nur Lesesrechte hat.
Ein

   sudo chmod 777 xyz/.svn/entries 

half leider auch nichts:

chmod: ./xyz/.svn/entries: Operation not permitted

Das fand ich dann schon ziemlich dreist irgendwie :-D.
Letztendlich half mir ein:

 
cp xyz/.svn/entries xyz/.svn/entries2
sudo rm xyz/.svn/entries
cp xyz/.svn/entries2 xyz/.svn/entries
sudo chmod 777  xyz/.svn/entries

Was zwar auf dem ersten Blick ein wenig aufwendig erscheint, aber in Form eines bash-scriptes angenehm die Arbeit übernimmt.
Allerdings weiß ich jetzt immer noch nicht WARUM dieser Fehler kommt.
Letztendlich habe ich mich ja daran gewöhnt, dass subversion meint, . hätte ein Lock….
Wenn mir da jemand mal erklären könnte, ob ich da was falsch mache oder wie… das fände ich mal toll :-).

update macos ipmitool

During my experiences with IPMI i figured out, that there is an issue with the build in ipmitool for MacOs.
If you want to use the IPMI 2.0 protocol (needed for Serial over Lan (SOL) ), you have to add an “-I lanplus” to the ipmitool command.
The problem is, that there is no such parameter in the original MacOs version.

So you have to recompile your own version:

Go to
http://ipmitool.sourceforge.net and download the source code.
You have to make sure, that you already have installed the common build enviroment (xCode).

You have to find out where the original version of ipmitool is:

    # whereis ipmitool
    # /usr/bin/ipmitool

So after you extracted the ipmitool source you have to configure it with the right path:
    # ./configure –prefix=/usr/

This tells the compiler, that binary should be placed in /usr/bin/ and the libs should be go to /usr/lib/

You finish with:
    # make
    # sudo make install

After that you will find your parameter in the help message:

    # ipmitool -h
    pmitool version 1.8.9
   
    usage: ipmitool [options…] <command>
   
           -h             This help
           -V             Show version information
           -v             Verbose (can use multiple times)
           -c             Display output in comma separated format
           -d N           Specify a /dev/ipmiN device to use (default=0)
           -I intf        Interface to use
           -H hostname    Remote host name for LAN interface
           -p port        Remote RMCP port [default=623]
           -U username    Remote session username
           -f file        Read remote session password from file
           -S sdr         Use local file for remote SDR cache
           -a             Prompt for remote password
           -e char        Set SOL escape character
           -C ciphersuite Cipher suite to be used by lanplus interface
           -k key         Use Kg key for IPMIv2 authentication
           -L level       Remote session privilege level [default=ADMINISTRATOR]
                          Append a ‘+’ to use name/privilege lookup in RAKP1
           -A authtype    Force use of auth type NONE, PASSWORD, MD2, MD5 or OEM
           -P password    Remote session password
           -E             Read password from IPMI_PASSWORD environment variable
           -m address     Set local IPMB address
           -b channel     Set destination channel for bridged request
           -l lun         Set destination lun for raw commands
           -t address     Bridge request to remote target address
           -o oemtype     Setup for OEM (use ‘list’ to see available OEM types)
           -O seloem      Use file for OEM SEL event descriptions
   
    Interfaces:
        lan           IPMI v1.5 LAN Interface [default]
        lanplus       IPMI v2.0 RMCP+ LAN Interface
   
    Commands:
        raw           Send a RAW IPMI request and print response
        i2c           Send an I2C Master Write-Read command and print response
        spd           Print SPD info from remote I2C device
        lan           Configure LAN Channels
        chassis       Get chassis status and set power state
        power         Shortcut to chassis power commands
        event         Send pre-defined events to MC
        mc            Management Controller status and global enables
        sdr           Print Sensor Data Repository entries and readings
        sensor        Print detailed sensor information
        fru           Print built-in FRU and scan SDR for FRU locators
        sel           Print System Event Log (SEL)
        pef           Configure Platform Event Filtering (PEF)
        sol           Configure and connect IPMIv2.0 Serial-over-LAN
        tsol          Configure and connect with Tyan IPMIv1.5 Serial-over-LAN
        isol          Configure IPMIv1.5 Serial-over-LAN
        user          Configure Management Controller users
        channel       Configure Management Controller channels
        session       Print session information
        sunoem        OEM Commands for Sun servers
        kontronoem    OEM Commands for Kontron devices
        picmg         Run a PICMG/ATCA extended cmd
        fwum          Update IPMC using Kontron OEM Firmware Update Manager
        firewall      Configure Firmware Firewall
        exec          Run list of commands from file
        set           Set runtime variable for shell and exec
        hpm           Update HPM components using PICMG HPM.1 file

Blogged with the Flock Browser

my very first (ehm… useful ?!?!) ruby script.

So concerning my first try of a web based zfs managment interface i will restart the project with some new conditions:

  • 1. i will switch from the former language PHP to the – like everywhere told – dev-friendly language ruby.
  • 2. i will first concentrate on just the basic functions.
  • 3. i have to use the system build in security realms (so either PAM or an equal interface)
  • 4. i will use dynamic JS-Functions to enhance the GUI. But the system should also work with simple browser (e.g. lynx/links)
  • 5. i will offer a RESTful interface. So it should be very easy for 3rd party apps to connect to them and use alle the functionality.

The Beginning ^^:
So my first task is to bring an overview of all system-disks (other devices are not necessary at the moment) into my ruby context.
So basic system command is:

root@sunny:~# format < /dev/null
Searching for disks…

The device does not support mode page 3 or page 4,
or the reported geometry info is invalid.
WARNING: Disk geometry is based on capacity data.

The current rpm value 0 is invalid, adjusting it to 3600
done

c3t0d0: configured with capacity of 18.61GB

AVAILABLE DISK SELECTIONS:
0. c0d0 <DEFAULT cyl 3734 alt 2 hd 255 sec 63>
/pci@0,0/pci-ide@11,1/ide@0/cmdk@0,0
1. c3t0d0 <ST92011A–3.04 cyl 2430 alt 2 hd 255 sec 63>
/pci@0,0/pci925,1234@11,3/storage@2/disk@0,0
Specify disk (enter its number):

Beside of the interesting warning, this will do the job. The format command will normally lead to a prompt. To avoid this, you just pipe the output to /dev/null.

The really valuable stuff is in the upper part of the output.
After consulting the ruby API about strings and arrays i ended up with the following (dirty) lines of code:


#!ruby
#!/usr/local/bin/ruby -rubygems

s = %x{format < /dev/null}
sa = s.split(“\n”)
counter = 0
dsk = false
puts “Array: “+sa.length().to_s()
sa.map do |i|
if i.strip().length() > 0
print counter.to_s()+” ”
if counter == (sa.length()-1)
dsk = false
end
if dsk == true
puts “DSK: “+i.strip()+”\n”
else
puts i.strip()+”\n”
end
if i.eql?(“AVAILABLE DISK SELECTIONS:”)
dsk = true
end

end
counter += 1
end

I found a really nice post about the ruby command line interface. That post gave me a good start in experimenting with the produced string output. You just always remember the irb to test parts of your code. Of course there is _A_Lot_ of debugging code. But the end-result is correct. Of course there should no hard-coded string in there. A by the way: it was a little bit inconvenient to quarrel again with the integer<->string conversion after some relaxing and luxurious years coding Java ^^. Okay so no implicit casting in ruby (?). Oh wait a minute – no typed language, so no casting?.

Oh yes… i don’t want to hide the output:

root@sunny:~$ ruby cmd.rb

The device does not support mode page 3 or page 4,
or the reported geometry info is invalid.
WARNING: Disk geometry is based on capacity data.

The current rpm value 0 is invalid, adjusting it to 3600
Array: 12
0 Searching for disks…
1 done
3 c3t0d0: configured with capacity of 18.61GB
6 AVAILABLE DISK SELECTIONS:
7 DSK: 0. c0d0 <DEFAULT cyl 3734 alt 2 hd 255 sec 63>
8 DSK: /pci@0,0/pci-ide@11,1/ide@0/cmdk@0,0
9 DSK: 1. c3t0d0 <ST92011A–3.04 cyl 2430 alt 2 hd 255 sec 63>
10 DSK: /pci@0,0/pci925,1234@11,3/storage@2/disk@0,0
11 Specify disk (enter its number):


So i guess i found my disks. At the end, i can just iterate about the even number of entries :-).
Okay ruby-gurus. How can i optimize my code. I am beginner level and “slurred” during years, coding Java and anciently PHP.
I am sure there is a lot of potential to cleanup this mess ^^.

Blogged with the Flock Browser

very first test with ruby camping :-)


I tried The Camping Short, Short Example for the ruby camping framework.

#!ruby
 #!/usr/local/bin/ruby -rubygems
 require 'camping'

 Camping.goes :HomePage

 module HomePage::Controllers

   # The root slash shows the `index' view.
   class Index < R '/'
     def get
       render :index
     end
   end

   # Any other page name gets sent to the view
   # of the same name.
   #
   #   /index -> Views#index
   #   /sample -> Views#sample
   #
   class Page < R '/(\w+)'
     def get(page_name)
       render page_name
     end
   end

 end

 module HomePage::Views

   # If you have a `layout' method like this, it
   # will wrap the HTML in the other methods.  The
   # `self << yield' is where the HTML is inserted.
   def layout
     html do
       title { 'My HomePage' }
       body { self << yield }
     end
   end

   # The `index' view.  Inside your views, you express
   # the HTML in Ruby.  See http://code.whytheluckystiff.net/markaby/.
   def index
     p 'Hi my name is Charles.'
     p 'Here are some links:'
     ul do
      li { a 'Google', :href => 'http://google.com' }
      li { a 'A sample page', :href => '/sample' }
     end
   end

   # The `sample' view.
   def sample
     p 'A sample page'
   end
 end


It seems to be very easy to create the separat pages.

The example above generates one entry page. (the index method in Views) and one additional page (sample method).
As far as i should know it from rails, it uses the same MVC pattern and theres is a similar syntax. Just the Views are in native ruby without mixing up with html.
But maybe that will appear later on.
The next step is to see howto connect ruby with some inner sys-functions of nexenta ^^.

Blogged with the Flock Browser

Installing ruby camping


Just a short one:

After succeeding in installing ruby gems, i finally was able to install the ruby micro-framework camping.
So ruby should just be used as a small administration web interface. In my eyes a rails aproach seems to be like breaking a fly on the wheel.

Just easy as this:

  root@sunny:~# gem install camping –source http://code.whytheluckystiff.net
    …
    Installing ri documentation for markaby-0.5…
    Installing ri documentation for camping-1.5.180…
    Installing RDoc documentation for activesupport-1.4.2…
    Installing RDoc documentation for builder-2.1.1…
    Installing RDoc documentation for markaby-0.5…
    Installing RDoc documentation for camping-1.5.180…

Smooth and easy. Ready to rumble ;-).

Blogged with the Flock Browser

Install Gems (Ruby with zlib) on Nexenta (GnuSolaris) 1.01

Next in the row is the installation of the ruby gems package.
So it should be easy… just following the instructions.
So…..

root@sunny:~# wget http://rubyforge.org/frs/download.php/38647/rubygems-1.2.0.zip
root@sunny:~# unzip rubygems-1.2.0.zip
root@sunny:~# cd rubygems-1.2.0
root@sunny:~# ruby setup.rb config
./lib/rubygems/spec_fetcher.rb:1:in `require’: no such file to load — zlib (LoadError)
from ./lib/rubygems/spec_fetcher.rb:1
from ./lib/rubygems/source_index.rb:10:in `require’
from ./lib/rubygems/source_index.rb:10
from ./lib/rubygems.rb:767:in `require’
from ./lib/rubygems.rb:767
from setup.rb:22:in `require’
from setup.rb:22

Welcom to error world ;-).
Okay…. should be easy to solve:

root@sunny:~# apt-get install libzlib-ruby zlib1g-dev

or for 64bit Plattforms:

root@sunny:~# apt-get install libzlib-ruby lib64z1-dev

But still the same Error!
Finally i found something in the Weblog of Lucas Chan.
Hm its about readhat/centos…. okay why not.
Just go to the ruby sources:

root@sunny:~# cd /usr/local/src/ruby-1.8.6-p110/
root@sunny:~# cd ext/zlib
root@sunny:~# ruby ruby extconf.rb –with-zlib-include=/usr/include –with-zlib-lib=/usr/lib
checking for deflateReset() in -lz… yes
checking for zlib.h… yes
checking for kind of operating system… Unix
creating Makefile

root@sunny:~# make
root@sunny:~# make install

and finally:

root@sunny:~# cd /usr/local/src/rubygems-1.2.0/
root@sunny:~# ruby setup.rb config
….
== Thanks

Keep those gems coming!

— Jim & Chad & Eric (for the RubyGems team)

Again: something learned!

Blogged with the Flock Browser

Multicast – genauer Nachgeschaut

Da das ja heute bei der Tafelrunde eher etwas zusammengesucht war, habe ich mich noch mal hingesetzt und mir die Dinge an-/eingelesen.
Ich werde einfach mal versuchen die Fragen, die da aufkamen wiederzugeben und dann mit passenden Texten beantworten:

  1. Was ist Multicast?
    Multicast ist eine Nachrichtenübertragung von einem Punkt zu einer Gruppe von Empfängern (auch Mehrpunktverbindung genannt).
    Daneben gibt es noch weitere Arten von Übertragungen:

    • Unicast: eine Punkt-zu-Punkt-Verbindung (klassische Client<->Server Verbindung)
    • Broadcast- und die Anycast-Übertragung (“ich bin da – wer noch?” – ping an x.x.x.255)
    • Geocast, ein besonderer Multicast, der räumlich begrenzt ist.
  2. Was sind die Vorteile von Multicast gegenüber Unicast?
    Es sind gleichzeitige Nachrichten an mehrere Teilnehmer möglich, ohne dass sich die Bandbreite des Senders verändert (für den Sender ist es als würde man eine Nachricht an einen Empfänger senden).
    Handelt es sich um paketorientierte Datenübertragung, findet die Vervielfältigung der Pakete an jedem Verteiler (Switch, Router) auf der Route statt.
  3. Wie geht das nun genau?
    Multicast ist die übliche Bezeichnung für IP-Multicast, das es ermöglicht, in IP-Netzwerken effizient Daten an viele Empfänger zur gleichen Zeit zu senden. Das passiert mit einer speziellen Multicast-Adresse. In IPv4 ist hierfür der Adress-Bereich 224.0.0.0 bis 239.255.255.255 (Klasse D), in IPv6 jede mit FF00::/8 beginnende Adresse reserviert.
    Bei der Übertragung über Ethernet werden die IPv4- bzw. IPv6-Multicastadressen auf bestimmte Pseudo-MAC-Adressen abgebildet, um bereits durch die Netzwerkkarte eine Filterung nach relevantem Traffic zu ermöglichen.
  4. Okaaaaay…. Wer macht sowas? Ist sowas nützlich?
    Ja ist es. Bekannte Anwendungen sind:

    • Audio- und Videoübertragungen (Protokolle wie RTP)
    • Verwendung beim Clustering und beim Routing nach dem Routing Information Protocol (RIP) Version 2.
    • ist für ein funktionierendes AppleTalk-Netzwerk notwendig.
    • Als Service Location Protocol und Multicast DNS wird als Teilimplementierung von Zeroconf Multicast (Rendezvous – inzwischen Bonjour) betrieben
      • automatische Zuweisung von IP-Adressen ohne DHCP-Server
      • übersetzen von Hostnamen in IP-Adressen ohne DNS-Server
      • automatisches Finden von Diensten im lokalen Netzwerk ohne einen zentralen Directory-Server
    • In Windows wird es im Simple Service Discovery Protocol benutzt
    • Weitere Multicast-Protokolle
      • Internet Relay Chat (IRC) bildet Netzwerke, welche einen einfachen TCP-basierten Multicast-Baum realisieren – wer hätte das gedacht ^^
      • Es wird überlegt in Jabber Multicast nach zurüsten.
  5. Und das geht jetzt auch über das Internet oder wie jetzt?
    Jein… also:
    Multicast-Pakete werden von den meisten Routern im Internet nicht verarbeitet. Deswegen werden multicastfähige Teilnetze über Tunnel zu Multicast Backbones (MBones) verbunden.
    Um Multicast-Pakete zwischen mehreren Netzen zu koordinieren, werden spezielle Multicast-Routing-Protokolle verwendet.
  6. Ahja… sehr schön – kann da nix passieren / durcheinander kommen?
    Es existieren bei der Verwendung bestimmter Adressbereiche einiger Switches Probleme bei der Weiterleitung von Multicastnachrichten.
    Die Adressen von 224.0.0.0 bis 224.255.255.255 sind für Routingprotokolle reserviert und für diese Adressen sendet der Router keine IP-Multicast-Datagramme. Die Adressen von 239.0.0.0 bis 239.255.255.255 sind für scoping reserviert, eine Weiterleitung innerhalb dieses Adressbereichs ist ebenfalls Switch abhängig. Adressen im Bereich 225.x.x.x bis 238.x.x.x sind frei verfügbar.
  7. Nachwort:
    Multicasting wird wieder populär, weil IPTV darauf basiert.
    Für verteilte Chat-Netzwerke wurde mittlerweile allgemein eingesehen, dass sie nicht mittels IP-Multicast realisiert werden können.
    Der Einsatz weiterer Multicast-Protokolle ist daher unumgänglich.  Na da haben wirs!

Schamlos kopiert von http://de.wikipedia.org/wiki/Multicast – teiweise gekürtzt und ein wenig angepasst.
Die Formulierungen sind auf die frühe Stunde zurück zu führen.
Anschließend zur Entspannung noch ein wenig Java – ein einfacher Chat-Server:
Zuerst der “Server” – Der ja eigentlich auch Teil jedes Clients ist:

public class NameServer{
        // the multicast group address sent to new members
        private static final String GROUP_HOST = "228.5.6.7";  
        private static final int PORT = 1234;      // for this server
        private static final int BUFSIZE = 1024;   // max size of a message
        private DatagramSocket serverSock;
   
        // holds the names of the current members of the multicast group
        private ArrayList groupMembers; 
        try {  // try to create a socket for the server
          serverSock = new DatagramSocket(PORT);
        }catch(SocketException se){
            System.out.println(se);
            System.exit(1);
        }
        groupMembers = new ArrayList();
        waitForPackets();
       
        // das ist dann hier wieder die typische Server-While-Schleifen-Methode
        private void waitForPackets(){
            DatagramPacket receivePacket;
            byte data[];
            System.out.println("Ready for client messages");
            try {
              while (true) {
                data = new byte[BUFSIZE];  // set up an empty packet
                receivePacket = new DatagramPacket(data, data.length);
                serverSock.receive( receivePacket );  // wait for a packet
       
                // extract client address, port, message
                InetAddress clientAddr = receivePacket.getAddress();
                int clientPort = receivePacket.getPort();
                String clientMsg = new String( receivePacket.getData(), 0, receivePacket.getLength() ).trim();
                processClient(clientMsg, clientAddr, clientPort);
              }
            }catch(IOException ioe){ 
                System.out.println(ioe); 
            }
        }
        ...
    }

Und hier dann noch mal der “Client”-Anteil:
   

public class MultiChat {
   
      // timeout used when waiting in receive()
      private static final int TIME_OUT = 5000;   // 5 secs
     
      // max size of a message
      private static final int PACKET_SIZE = 1024;
      // NameServer address and port constants
      private static final String SERVER_HOST = "localhost";
      private static final int SERVER_PORT = 1234; 
      /* The multicast port. The multicast group address is
      obtained from the NameServer object. */
      private static final int GROUP_PORT = 5555; 
      // for communication with the NameServer
      private DatagramSocket clientSock;
      private InetAddress serverAddr; 
      // for communication with the multicast group
      private MulticastSocket groupSock;
      private InetAddress groupAddr;  
      public MultiChat(String nm){
         /* Attempt to register name and get multicast group
         address from the NameServer */
         makeClientSock();
         waitForPackets();
      } // end of MultiChat();
     
      private void makeClientSock(){
        try {   // try to create the client's socket
          clientSock = new DatagramSocket();
          clientSock.setSoTimeout(TIME_OUT);  // include a time-out
        }catch( SocketException se ) {
          se.printStackTrace();
          System.exit(1);
        } 
        try {  // NameServer address string --> IP no.
          serverAddr = InetAddress.getByName(SERVER_HOST);
        }catch( UnknownHostException uhe) {
          uhe.printStackTrace();
          System.exit(1);
        }
      }  // end of makeClientSock()
     
      private void waitForPackets(){
        DatagramPacket packet;
        byte data[];
        try {
          while (true) {
           data = new byte[PACKET_SIZE];    // set up an empty packet
            packet = new DatagramPacket(data, data.length);
            groupSock.receive(packet);  // wait for a packet
            processPacket(packet);
          }
        }catch(IOException ioe){ 
            System.out.println(ioe); 
            }
      }  // end of waitForPackets() 
    }

Wie man ziemlich gut erkennen kann, ist es auch nicht wesentlich anders, als wenn man sich direkt Sockets erstellt. Gefunden habe ich das Ganze in dem Buch “Killer Game Programming in Java” – heißt wirklich so – hin und wieder finden sich da wirklich interessante Dinge besprochen (Link: hier!).
So das wars.
Die Tage wollte ich noch mal bissel was zu OSGi schreiben – so denn das schöne Buch ankommt.
Und aus – leider aktuellem Anlass – zu IPMI und wieso es eigentlich schon fast unverschämt ist, dass ein _mitgelieferetes_ Linux-Tool fehlerhaft ist und deswegen vom Hersteller empfohlen wird, extra dafür ein Windows aufzusetzen. Nichts gegen Windows, aber wieso liefert man ein fehlerhaftes Tool dann mit?
P.S.: Schreibt mal wieder 😉