C ist die Implementierungssprache unserer Wahl

Einfachheit (Reduktion von Fehler, höhere Zuverlässigkeit) und Performance (Reduktion von Server- und Stromkosten). Wenn I/O nicht mehr die Geschwindigkeitsbremse darstellt, tritt die Qualität der Performance der Anwendung in den Vordergrund.

bis zu   1/100   des Stromverbrauches und   1/100   der notwendigen Serverleistung.
 Es ist kaum zu glauben, lassen Sie es sich zeigen 

Entgegen vieler Aussagen ist es in C einfachm robuste und fehlerfreie Programme zu erstellen. Der Aufwand ist nicht viel mehr als der von High-Level Sprachen (Haskell ausgenommen). Wir haben einen C-Guide erstellt, um die versprochene Qualität und Performance einhalten zu können. Um ein Maximum an Geschwindigkeit und Einfachheit zu erhalten entwickeln wir meistens in C. Auf Kundenwunsch ist C++ natürlich kein Problem.

Sehen Sie folgendes Beispiel: Es werden von allen Kunden und allen Rechnungen die Rechnungsposten nach Artikelnummer sortiert und ausgegeben.

static int rechnung_cmp_artikel_nr(rech_posten_t *rp1, rech_posten_t *rp2) {
   return strcmp(rp1->artikel->artikel_nr, rp2->artikel->artikel_nr);
}

static void rechnungsposten_print_all(void) {
   push(0); // Marker für Result-Stack
   // R ist der Root der noSQL Datenbank
   // von allen Kunden alle Rechnungen alle Rechnungsposten auf Result-Stack
   kunde_t *k=R->kunden;
   each(k) {
      rechnung_t *r=k->rechnungen;
      each(r) {
         n_collect(r->posten);
      }
   }
   sort(rechnung_cmp_artikel_nr);

   rech_posten_t *rp;
   while(rp=pop()) { // alle Rechnungsposten vom Result-Stack abholen
      rech_posten_print(rp);
   }
}
each(k) ist ein Makro und wird aufgelöst zu:
	for(;k;k=k->next)

Linked List

Die verwendeten Datenstrukturen sind extrem einfach. In der noSQL Datenbank (im obigen Beispiel zu sehen) werden alle Objekte in verketteten Listen abgelegt. Hier verwenden wir eine einfache Linked-List mit einem Pointer auf das Attribut das den Listen-Anfang hält. Damit können folgende Operationen sehr einfach umgesetzt werden: rechnung_move(rechnung_t *rechnung, rechnung_t **new_owner), rechnung_delete(rechnung_t *rechnung) und rechnung_new(rechnung_t **owner);
Anmerkung: Diese Funktionen werden aus dem Datenbank-Schema generiert
typedef struct kunde_t { // Datenbank Objekt
	struct kunde_t *next;
	struct kunde_t **owner; // Backlink to start attribute: &R->kunden
	struct rechnung_t *rechnungen;
	char *name;
} kunde_t;
typedef struct rechnung_t { // Datenbank Objekt
	struct rechnung_t *next;
	struct rechnung_t **owner; // Backlink to &kunde->rechnungen
} rechnung_t;

Array: Result-Stack (verschachtelbar)

Zum Aufsammeln (select) und Sortieren (qsort) von Elementen kommt ein statisches Array zum Einsatz. Mit push(0) wird ein neuer "Stack-Anfang" eingerichtet. Die 0 dient als Ende-Kennung, ähnlich wie das 0-Byte bei C-Strings.
  rechnung_t *r=kunde->rechnungen;
  push(0); // Start stack
  for(;r;r=r->next) {
    if(r->...) push(r); // Bilde Ergebnismenge
  }
  sort(rechnung_cmp_artikel_nr);
  while(r=pop()) { // Hole Ergebnismenge sortiert ab
    rechnung_print(r);
  }

Hash-Array

Hash Strukturen werden nicht permanent gehalten sondern nach Bedarf dynamisch angelegt.
  hash_t *rechnung_hash=hash_new(10000); // Hash-Array ist dynamisch und nicht auf 10000 beschränkt
  rechnung_t *r=kunde->rechnungen;
  for(;r;r=r->next) {
    if(r->...) hash_add_key(rechnung_hash, r->artikel_nummer, r); // Bilde Ergebnismenge
  }
  push(0);
  hash_collect_key(rechnung_hash);
  char *artikel_nummer;
  while(artikel_nummer=pop()) { // Hole Ergebnismenge sortiert ab
	 push(0); verschachtelter Result-Stack
	 hash_collect_values(rechnung_hash, artikel_nummer);
    ...
  }
  hash_delete(rechnung_hash);

Temporäre Strings

Über die Funktion str(char *fmt, ...) wird ähnlich wie snprintf() Text in einen temporären Speicher geschrieben. Man muss sich nicht mehr um die Anforderung oder Freigabe des Speichers kümmern und es werden ganz einfache (einfach=weniger Fehler) Konstruktionen möglich wie:
  //db_strset setzt ein dynamisches Stringfeld in der Datenbank
  db_strset(&kunde->name, str("%s,%s", vorname, famname));
  db_strset(&kunde->plz, str("%05d,%s", plz, ort));