13. November 2011

Server Migration

Heute stand wieder mal eine Server-Migration an. Die Weblins wurden vom Ein-Server-Testbetrieb zum aktuellen Produktiv-Cluster migriert. Das war meine bisher schönste Migration:

- Server installieren,
- Konfigurationsdaten anpassen,
- Daten migrieren,
- Integrationstests checken,
- DNS umschalten,
- fertig.

Zugegeben, langsam bekomme ich Übung. Angefangen hat alles mit einem Entwicklungsserver. Dann kam das erste Produktiv-System aus 2 Hetzner-Servern. Darauf folgte ziemlich schnell das erste echte Rechenzentrum aus 10 Servern, genannt: der Proton-Cluster. Der wurde dann ausgebaut bis zu 60 Hosts. Vor 2 Monaten habe ich alles auf einem Server installiert als Testbetrieb mit einem simulierten Cluster (genannt Delta). Zwischendurch gab es noch eine Installation des gesamten Systems auf einer VMware. Heute dann die bisher letzte Installation (genannt Atlas) auf mehreren Servern, die sich die ca. 8 Rollen teilen.

Weblin ist ein komplexes System. Viele Subsysteme, zusätzlich zur Website auch noch ein Client und das Instant Message-System. Trotzdem ist es gut handhabbar, läuft stabil und ist flexibel, wie die unterschiedlichen Setups zeigen. Wäre es nicht so gut in Schuss, dann hätte ich es nicht wieder zum Laufen bekommen.

An Weblin Client und Portal haben viele Leute gearbeitet. Bei denen möchte ich mich hier für mich und im Namen der User bedanken: Entwickler im T-Team und iTeam, Research-Team und Praktikanten, Operating und Code-Review, Design und Content, Partner-Integration und Community-Management. Und nicht zuletzt die, die in letzter Zeit mit Rat (=Consulting) und Tat (=Twincoding) geholfen haben.

Ein paar meiner "Learnings":
- Viele gut ausgeprägte Server-Rollen helfen dabei groß (und klein) zu skalieren.
- Konfiguration zentralisieren und das dann durchhalten, wenn viele Rollen und Subsysteme dazukommen.
- Konsequentes Durchziehen einer verteilten Architektur hilft, auch wenn es manchmal mehr Arbeit macht.
- Ausführliche Integrationstests helfen Konfigurationsprobleme aufzuspüren.
- Refactoring hält jung.
- Technische Lösungen nicht ausreizen. Immer noch eine Optimierung in petto haben.
- Ich kann programmieren, deshalb funktionieren für mich eigene Lösungen, z.B. beim Backup (scp, rsync, tar) und beim Setup (svn und Shellskripte). Und das ist auch gut so.

Jetzt sind wir richtig online.

Weblin is back.

Und das ist erst der Anfang.

_happy_migrating()

5. November 2011

Throttling Bandwidth with Linux Tools

As a semi-professional admin I do backups of production systems all the time. This means various "tar", "scp", "rsync" and even "lftp" operations depending on what is to be backup-ed.

The problem: Backup interferes with normal operation

Backup is running at the same time as the normal operation of the production system and the system is already quite busy. Copy and transfer tools take as many resources as they can get from CPU, DMA and network. This usually interferes with the normal server operations and can even bring down the server (thank you DMA).

The solution: Throttling

Many of the tools have a throttling option, which can limit the bandwidth in network transfers and file system operations.

scp:
  • Option -l limits the used bandwidth, specified in Kbit/s. 
  • Example for max 5 MByte/sec: scp -l 40000 myfile $user@$host:
rsync:
  • Option --bwlimit limits I/O bandwidth in KBytes per second. 
  • Example for max 5 MByte/sec: rsync --bwlimit 5000 myfile destfolder 
lftp:
  • Setting "net:limit-rate" limits transfer rate on data connection in bytes per second. 
  • Example for max. 5 MByte/sec: echo "set net:limit-rate 5000000; put myfile" | lftp -u $user,$password $host
Anything else, e.g. tar, use the cstream command:
  • cstream can limit throughput of pipes with option -t in bytes per second.
  • Example for max 5 MByte/sec: tar cf - myfolder | cstream -t -5000k > myfolder.tar
  • Use "-5000k" instead of "5000k" to never exceed the max. Otherwise cstream saves throughput it could not use for later, which may be more bursty.
happy_throttling()

1. Oktober 2011

KLab geht an die Börse

Die Firma KLab ist in Tokio erfolgreich an die Börse gegangen. Die Aktien wurden für 1700 Yen ausgegeben. Der Handel begann dann mit 3970 und 3 Tage später stehen sie bei 3500. Also kein schlechter Start. Das ist der erste Börsengang einer Social-Network / Casual-Game Firma in Japan. Vielleicht sogar weltweit. Der Buzz sagt: "Zynga of Japan". KLab ist eine Nummer kleiner als Zynga, aber ziemlich erfolgreich mit Social Games und virtuellen Gütern.


Das tolle daran: seit einiger Zeit arbeite ich mit KLab an einem Projekt wo es um Avatare auf allen Webseiten geht. Das Projekt wird in der Investoreninformation genannt ("Cheers") als eine der 5 Umsatz- und Wachstumssäulen der Firma.

Irgendwann kam der Anruf: "Wir wollen sowas wie Weblin. Du hast das schon mal gemacht. Zeig uns wie das geht". Und das haben wir dann gemacht: eine Plattform für Social Gaming auf allen Webseiten.

Wichtiges Projekt im Börsenprospekt einer Firma mit US$ 200 Mio. Marktkapitalisierung. Coole Sache das.

_happy_trading()

17. September 2011

Im VMware Player vom ISO Image installieren

Für Noob-Admins wie mich: Debian in VMware Player vom ISO-Image installieren

Eigentlich soll man mit dem VMware Player keine Syteme installieren (können). Dafür gibt es die Workstation und die ist ihr Geld auch wert. Aber wenn man mal ein System probieren will, bevor man die Workstation kauft, kann man das mit etwas Handarbeit auch im Player machen.

Ich habe eine bootfähige CD als ISO-Image (in meinem Fall "C:\debian-6.0.2.1-i386-netinst.iso") und will von diesem Image ein neues Linux installieren:

1. Dupliziere eine bestehende VM oder lade eine VMware Appliance runter. Die VM kommt mit einer Konfigurationsdatei mit der Endung .vmx, mit einer virtuellen Platte mit der Endung .vmdk und anderen Dateien.

2. Im .vmx setze oder ändere die 4 Werte:
ide1:0.autodetect = "TRUE"
ide1:0.deviceType = "cdrom-image"
ide1:0.fileName = "C:\debian-6.0.2.1-i386-netinst.iso"
ide1:0.present = "TRUE"
3. Boote die VM durch Doppelklick auf die .vmx Datei

4. Beim Bootvorgang, bevor das Auswahlmenü erscheint und das Betriebssystem bootet, drücke F2 für BIOS-Setup SCHNELL.

5. Im BIOS-Setup die bootbaren Devices herum schieben bis die CDROM vor (über) der Festplatte steht. F10: Save and Exit

6. Jetzt sollte die VM automatisch nochmal booten und den Installer des ISO-Images anzeigen.

7. Nach der Installation ordentlich runterfahren

8. Das ISO-Image aus der .vmx Datei löschen:
ide1:0.fileName = ""
ide1:0.present = "FALSE"
happy_booting()

31. August 2011

Make Money with Virtual Goods

My session at Barcamp Hannover 2011:

28. August 2011

Galaxy Tab wiederbeleben - ein Wunder

Heute mal ein (weniger tiefschürfender, aber doch bewegender) Microblog:


Nach einem ersten ganzen Tag mit dem neuen Galaxy Tab 10.1 bleibt es plötzlich dunkel. Power-Button drücken, Power Button lange drücken, Power Button gaaanz laaange drüüücken, gut zureden, nichts hilft. Dunkelheit auf dem Schirm, trotz Stunden am Ladestrom. Schreck.

Aber keine Panik: Google hilft (Bing hätte vielleicht auch geholfen, aber hat ja keiner gefragt). In der Verzweiflung also gegoogelt: "galaxy tab remains dark" und finde ... warte ... es kommt gleich ... einen Blogbeitrag: Solution for Samsung Galaxy Tab unable to turn on problem

Da heißt es: Den Bildschirm betatschen und GLEICHZEITIG den Power Button pressen. Mit dem wertvollen Hinweis: nur Geduld, kann lange dauern, weiter pressen und beten.

Ich presse und presse und presse und nach gefühlten 2 Minuten lebt er wieder.

Ein Wunder.
Allah ist groß. Und der heilige Geist. Und Google. Und Voyager8 (der Blogger). Danke an alle Beteiligten. Hammer. Echt.

happy_pressing()

14. August 2011

Zweitgeist Kündigung aufgehoben


Das Hamburger Landgericht hat die Kündigung bei Zweitgeist aufgehoben.

Tja, die Mühlen der Justiz mahlen langsam. Es hat 2 Jahre gedauert. Aber jetzt ist offiziell klargestellt: die Kündigung war unwirksam.

Was für eine Kündigung? Februar 2009 wurde ich als Geschäftsführer bei der von Christine und mir gegründeten Firma Zweitgeist fristlos gekündigt. Die Kündigung war Teil des Versuchs einiger Investoren, Zweitgeist an den Rand des Konkurses zu führen, um die Firma dann zu übernehmen.

Was heißt hier Firma übernehmen? Einige Investoren haben ein lächerlich niedriges Angebot gemacht, um den Gründern ihre Anteile abzukaufen. Damit man auf dem Papier die Firma so niedrig bewerten konnte, musste sie sehr schlecht aussehen. Das ist nicht leicht bei 3 Millionen Usern und 400.000 neuen Usern pro Monat und wenn man anfängt wirklich Geld zu verdienen. Deshalb mussten alle Mitarbeiter entlassen werden. Eine Firma ohne Mitarbeiter sieht nämlich wirklich schlecht aus.

Jedenfalls sind bei diesem "Spielchen" 25 Arbeitsplätze verloren gegangen. Eure Arbeitsplätze, sozusagen Kollateralschaden, weil jemand eine stark wachsende Internetfirma übernehmen wollte. Aber das kümmert Investoren nicht wirklich. Da zählt nur der mögliche Gewinn beim Verkauf. Und da gab es eben einen Investor, der sich ausgerechnet hat, dass er seinen Anteil vervierfachen kann. Später mehr dazu.

Jedenfalls hat das Gericht klargestellt, dass der erste Akt, die Kündigung, ungültig war.

happy_pokering()

PS: Dass mir jetzt keiner mit Winner-Stories/Loser-Stories kommt. Natürlich haben alle nur verloren. Die anderen hoffen aber, dass nicht bekannt wird, was für einen Mist sie gebaut haben. Aber es ist das wahre Leben, mein Leben und euer Leben, eure Arbeitsplätze. Es ist wahr, deshalb gehört es geschrieben und nicht verheimlicht. Heimlich ist jetzt aus.

4. August 2011

Adwords Test gesponsort von Google

Google hat mir vor einiger Zeit einen 100 € Adwords Gutschein geschickt. Anscheinend gräbt Google inzwischen auch Registergerichte durch nach neuen Firmen. Mir solls recht sein. Besser als noch ein Büromaterial-Katalog.

Das - dachte ich mir - ist doch eine gute Gelegenheit, mal kostenlos mit Adwords zu experimentieren. Die Kampagne von Google wendet sich an alle möglichen IT-Firmen. Also - dachte ich mir - muss man nicht unbedingt SEO/Adwords Experte sein, um das Angebot zu nutzen. Adwords - dachte ich mir - wird schon so einfach sein, dass ich es auch verstehe. Schliesslich - dachte ich mir - wollen sie ja, dass die kostenlose Adwords Kampagne so gut gefällt, dass man noch etwas mehr investiert. Falsch gedacht.

Adwords ist nicht für Dummies und nicht für Handbuch-Ignorierer, wie mich. Die Kampage ist zwar einfach aufgesetzt, funktioniert aber leider nicht. Ich bekomme keine Klicks. Die Ads werden gar nicht angezeigt, weil angeblich die Keyword-Relevanz zu schlecht ist.

Am Inhalt kann es nicht liegen. Der Inhalt besteht aus Massen an selbstgeschriebenen Text zu einem bestimmten Thema. Die Seiten sind reichhaltig, fokussiert, originär: www.galactic-developments.de. Daran kann es nicht liegen. Die Keywords stammen aus dem Text und jedes Keyword linkt auf die Seite aus der es stammt. Trotzdem werden die Keywords nicht angezeigt. Selbst wenn ich wollte, könnte ich nichts investieren, um die Website zu pushen, denn Google will mein Geld nicht.

Mögliche Schwachstellen meiner Kampagne:

  • Die Website hat keine META-Keywords.
  • Die Landing Pages haben nicht das Keyword im Title.
  • Die Kampagne hat nur ein Ad. Man könnte für jeses Keyword ein Ad machen.
  • Die Keywords kommen nicht im Ad-Text vor.
  • Die Website ist nicht SEO-optimiert.
  • Ich habe nichts zu verkaufen. Adwords ist für Shops gemacht, die immer direkt auf ein Produkt linken.
_happy_advertising()

14. Juni 2011

An HTML based Chat Window with WebKit, jQuery, and tricks

Over the weekend I was working on the OVW chat window. The chat window is very similar to the avatar display and also very different. The similarities are:

  • both are display modules
  • both use WebKit
Because they are both display modules, I could take the avatar display module code and strip away the avatar part to keep only nicknames. The chat window needs only nicknames. Later there will be images and more features. But for the start we need only text. The chat module has the same structure as the avatar module. It subscribes to a small number of virtual presence model events and then turns around and paints the display in HTML.


See the ui-layout-* CSS-classes? They are used by jQuery UI Layout. There is a bit of configuration necessary, but only a bit: http://code.google.com/p/ovw/source/browse/trunk/Apollo/bin/Win32/Debug/modules/Chat/Chat.html?r=255#153

As always, styling is very simple. Need bold nicknames? Here they are:
#ChatOut .cNickname { font-weight:bold; }
On the other hand, chat window and avatar display are very different:
  • chat is a dialog where the Chat.html code is in an IFRAME
  • avatar display paints directly, has no dialog frame
Calling the avatar display I can simply call a JavaScript function in WebKit. But in case of a Dialog with IFRAME, things are a bit more complicated. The IFRAME is a HTML window inside the HTML window. The WebView module has only a handle to the outer HTML/JavaScript. There is no direct access to the JavaScript of the inner HTML. I can call a JavaScript function in WebKit, but the function is executed in the context of the dialog wrapper. This is OK, if I want to control the dialog functions. But talking to the inner HTML is more difficult.

I am sure there are way to get to an embedded IFRAME from C++. But I did not want to get too deep into enumerating WebKit objects from C++. I needed a way to call JavaScript in the embedded IFRAME from the parent frame. Luckily we are in the same security domain, so calling JavaScript across frames is no problem. My solution is to call a function in the Dialog, which calls a function in the IFRAME, which evals the code I want to execute in the IFRAME.
function ContentEval(sCode)

{
return document.getElementById('Content').contentWindow.EvalJS(sCode);
}
Not very nice. A bit dirty, but it works. Also not very fast. Anyway, there are not many messages which take this route. Just adding participants and chat lines. I am confident, that we find a better way to do this later.

_happy_wrapping()

UPDATE: a week later, I have direct access to embedded frames. I am searching the frame by it's DOM-ID, then call the function inside the frame. I do GetFrameByPath to find the frame, because the frame may be inside another frame. Frames inside frames will be identified by a "/" separated list of DOM-IDs. That's my so called frame-path: http://code.google.com/p/ovw/source/browse/trunk/Apollo/bin/Win32/Debug/modules/Chat/Chat.html?r=414#200

The GetFrameByPath function is a mess of COM auto-pointers and QueryInterface. The ugly face of C++. Thank FSM someone invented better ways.

7. Juni 2011

More OVW Progress

Another week of evenings and weekend worth of progress on the next weblin generation (OVW). I am now working on browser tracking, support for multiple tabs and the multiple views for the same scene.


1. Firefox Add-on

Unfortunately, the rather simple weblin way of tracking browsers is not sufficient anymore. We want tabs (more about tabs and windows at the OVW blog).

Reliable information about visible tabs is only available inside the browser. So I need real browser addons. I started with Firefox some time ago. The addon keeps track of all tabs, when they open/close, become visible and when they navigate. It sends all the information over a local TCP connection to the client (using a simple remote procedure call protocol). This sounds complicated and it is, because the socket implementation in Firefox has its quirks. I could tell stories. But the beauty of a TCP connection is, that if the browser crashes or disappears, then the client will notice when the TCP connection goes down. It will then leave all rooms automatically, even if the browser addon does not say goodbye.

2. Tracking Browser Coordinates

Unfortunately, I don't get a real window handle (HWND) inside the browser. I need a native component to get a HWND for the tab. Why HWND? because I want to track the coordinates of the tab: resize and move events. I could add a native DLL to the addon, but then the addon is not cross-platform. Since I have a native part anyway (the client), I rather make the platform dependent processing in the client.

I implemented a BrowserInfo-module which finds the tab's HWND in the window list and does GetWindowRect() to get coordinates. The module also arranges the window stacking order with SetWindowPos() so that the avatar display is always directly on top of it's browser. That's good old Win32 coding. While most of the code is cross-platform, this part must be adapted to other operating systems, i.e. MacOS.

3. Model View Controller

I am very happy with the Model-View-Controller architecture. The "view" is only responsible for showing avatars. It can be closed and opened and re-creates everything from the model. The view uses the WebKit and JavaScript heavily.

The virtual presence module manages entering and leaving chat rooms, participants and chat lines. This is the "model". The view gets events from the model when participants enter/leave/chat. The view can always query the model. The model has only data structures. The view creates visible avatars.

And best of all: there can be multiple views for the same model. This means, that 2 browser windows can show the same scene.

_happy_modeling()

1. Juni 2011

Open Virtual World Progress

The Open Virtual World project makes significant progress. I am now using WebKit for all user interface components. WebKit is the HTML rendering engine that drives Google Chrome, Safari, and many mobile browsers, because it is easy to integrate and has a good open source license. WebKit is a C++ library and it has a brand new transparency feature. WebKit with transparency is perfect to paint avatars over browser windows.


I can use all the cool Web technologies: CSS, jQuery, canvas. I could even make make my user interface with Flash, SVG, 3D CSS Transforms, WebGL/3D. A CSS style on a text element is much faster to implement than with old graphics libraries. And it is portable to other platforms. Development almost feels like rapid prototyping. The way we are used to program Web frontends. It is a Web frontend, but for a native application. A true cross platform GUI.

This is a comparison of OVW avatars (left) and weblin avatars (right). Weblin avatars are painted to the screen by old school InvalidateRect, WM_PAINT, BitBlt techniques. OVW avatars are rendered by HTML and JavaScript.


Javascript means, that I can use jQuery, which makes effects very easy. Say, I move an avatar with the mouse and let it go. The Weblin avatar slowly slides down to the browser border. In weblin this was animated with a WM_TIMER, and painting the avatar at different positions until it reached the bottom. Then stop the timer. Now, with jQuery I just write one line of JavaScript like:
$(this).animate( { bottom: '0px' }, 800 );
Voilà, the avatar slides down.

There is more at the Open Virtual World blog:
I use Webkit also for windows and dialogs. There are no native windows. Everything is a transparent Win32 window without window border, but with a WebKit inside. All you see is programmed in HTML. Need a semi transparent shadow around your window? Just make a
and use a CSS "box-shadow".


WebKit rox.

Code is at code.google.com.

_happy_sliding()

20. Mai 2011

Technologie und idiotische Investoren

Gerade komme ich wieder mal von einem Barcamp/Conference/Unconference zurück. Da gab es wieder allerlei interessante Vorträge über Technologien und Arbeitsmethoden. Dabei haben wir (ehemalige Mitarbeiter von Weblin) festgestellt, dass das was wir vor 3-5 Jahren gemacht haben, jetzt für die Masse der Entwickler interessant ist. Wir haben damals Probleme erkannt und gelöst, die immer noch aktuell sind und inzwischen wenigstens von den meisten anderen Teams auch angegangen werden.


Bei Weblin hatten wir ab 2006:
und vieles mehr. Frag' doch mal heute - zu Zeiten von NoSQL - wer for 4 Jahren schon "Avoid SQL" gesagt hat.

Das waren schon damals alles bekannte Technologien - die aber nur 3 % der Startups verwendet haben. Heute völlig normal, keine Kunst. Die Kunst ist es das Richtige zu tun, wenn es noch nicht alle machen. Mit der Auflösung von Weblin wurden eine Menge Entwickler rausgeschickt, die die Technologien in ihre neuen Teams getragen haben und jetzt damit viel Geld verdienen.

So gut waren wir.

Technologie zählt. Alle Firmen, die Erfolg haben, haben super Teams im Hintergrund. Werft das Technik-Team weg und ihr habt nichts. Facebook, Zynga, Bigpoint kaufen Firmen nur, um an die Technik-Teams zu kommen. Für alle, die es noch nicht gemerkt haben: die Zeiten ändern sich.

_happy_ranting()

8. März 2011

Simple Dependency Injection

Dependency injection (DI) is very useful for isolated tests. In short:

Assumed you have a user table in the database. Assumed, that the user table is accessed through a class UserDatabase. Your application wants to cache users for quicker access. This means, that there is at least a list of users in memory. Usually you would wrap this list into a class UserManager. The typical code of UserManager will instantiate a UserDatabase, like:

class UserManager {
UserDatabase DB = new UserDatabase();
UserManager() {}
public UserId CreateUser() {
return DB.CreateUser();
}
...
}

If you want to test UserManager.CreateUser(), then the method needs a UserDatabase instance which will access the real database. This is not what you want, because it is not isolated. You want to test UserManager without activating UserDatabase. It rather would be cool if the UserManager would use a dummy database class which just simulates the behaviour of UserDatabase without actually writing to the real database.

So, we want to equip the UserManager for the test with a MockDatabase, but for the real operation it should use the real UserDatabase. We want to decide which database class the UserManager will be using under which circumstances. Means: we make the proper database and hand it to the UserManager. We inject it. Example:
class UserManager {
UserDatabase DB;
UserManager() { // real constructor
DB = new UserDatabase();
}
UserManager(UserDatabase db) { // test constructor
DB = db;
}
public UserId CreateUser() {
return DB.CreateUser();
}
...
}

The test code will create a new MockDatabase() and use UserManager(UserDatabase db) to inject it. The real code will use the default constructor, which makes its own normal UserDatabase. Not pretty, but possible. If there are more dependencies, then things get nasty with large contructors which are only used for tests and have different code from the real constructor. Not pretty.

There are better ways. For example DI frameworks, which provide sophisticated methods for injecting dependencies without bloating constructors. They use extensive configuration, if you like. I used StructureMap. It works, but I do not like, that I have to learn it. I spend a few hours reading, learning, trying, and even a few hours on it's unexpected limitations. Now I can use StructureMap, but I do not recommend it, if you do not already know it.

Dependency injection can be simpler. Here is my take: we want, that UserManager uses either MockDatabase or a UserDatabase. Why not just tell the UserManager to Use() either database:
class UserManager {
UserDatabase DB { get; set; }
UserManager Use(UserDatabase db) { DB = db; return this; }
public UserId CreateUser() {
return DB.CreateUser();
}
...
}

The test code will then look like:
var um = new UserManager().Use(new MockDatabase());

The production code will be very similar:
var um = new UserManager().Use(new UserDatabase());

The return this; part in Use() takes care, that the configuration can be written in a single line. If there are multiple dependencies, then I can do:
var um = new UserManager()
.Use(new MockDatabase())
.Use(new DummyWebService())
.Use(new TestController());

...because all the different Use() Methods have different parameters types and automatically know what to do. That's it. Use() is my DI framework.

And here comes my favorite single line of dependency injected configuration for a unit test. An ItemCore which uses a RezMockConnection and an ItemRepository which itself uses a MemoryItemStorage.Factory:
var rep = new ItemCore().Use(new ItemRepository().Use(MemoryItemStorage.Factory)).Use(new RezMockConnection()).Repository;


_happy_using()

27. Februar 2011

A Busy Spaceport in Earth Orbit

This is not Science Fiction:


There is a big space station in earth orbit. It spans 2 soccer fields. It has the weight and pressurized volume of a Boeing 747.

The station has a current population of 12 people.

There are 6 (!) spacecraft docked:
  • 2 russian soyuz crew vehicles
  • 1 russian progress transporter
  • a japanese HTV transporter
  • a european ATV transporter
  • an american space shuttle

2 x Soyuz
TMA-20 & TMA-01M
Russia
Progress
M-09M
Russia
HTV-II
Kounotori 2
Japan
ATV-2
Johannes Kepler
Europe
Space Shuttle
Discovery
USA










Never again will there be so many spacecraft including a shuttle docked. This is mostly due to the shuttle's retirement. Only two more shuttles will visit the ISS. Other craft will replace the shuttle.

With the Space Shuttle retiring and no improved reusable craft following, it looks like there has not been much progress in the last 30 years. But the completed ISS with 6 craft attached and 12 people is a much larger and developed space operation, than during the single-module days of Skylab and Salyut. A different order of magnitude:

Skylab
SalyutISS






_happy_undocking()

2. Februar 2011

2 1/2 Zi. Wohnung in Freiburg zu vermieten ab 1.4.2011

Anzeige:


2 1/2 Zimmer 41 qm ab 1.4.
1. OG, 2 1/2 Zi, EBK, Bad, Flur, Wohnzimmer, Schlafzimmer, Keller, Aufzug, Bauj. 1995, Tennenbacherstr. 50, 79106 Freiburg, Nähe Institutsviertel, Straßenbahn Haltestelle vor dem Haus, 420,- € KM, 160,- € NK, Kaution 3 x KM, keine Provision, wolf.heiner@gmail.com, Tel. 0171 / 2848461




2. Januar 2011

OAuth for TwiX

I finally added OAuth to TwiX, the Twitter-XMPP gateway.

Since August 2010 Twitter requires OAuth for API access. This is extremely stupid for background daemons like TwiX which do not have a user interface and especially no browser based UI.

TwiX is my C# playground. So, I needed an OAuth library for C#. TwiX runs on mono and .NET. I am running my instance of TwiX on a Linux server. Luckily almost all .NET libraries run without modification on mono.

A quick research returned several OAuth libraries, some are for ASP.NET, which I do not use, because TwiX is a faceless server daemon, not a Web application. I zeroed in on Shannon Whitley's implementation which comes with a handy sample project.

This example project has
- an OAuth core implementation
- a Twitter OAuth adapter
- a sample desktop app with embedded browser
= cool thing

I used the 2 OAuth classes in TwiX and converted the sample desktop app into a Twitter OAuth token generator tool (see screen shot). 1 hour of work, thanks Shannon.

This is a general Twitter token generator. It is not just for TwiX. The OAuthTwitterDesktopTool generates a twitter token and token secret for every Twitter app, if you know the app's consumer key and consumer secret. The OAuthTwitterDesktopTool is part of the TwiX distribution.

You can find TwiX with OAuth and the token generator on the TwiX homepage.

_happy_authorizing()