==========================================================================================
Verrückte Ideen
==========================================================================================
 - aufeinander aufbauende Events (Backend-spezifisch <- generisch, oder mehrere
   Einzelevents gebündelt in ein einzelnes abstraktes ["Crash", HLT mit
   abgeschalteten Interrupts])
   * lösbar als Callback-"Experimente", die selbst Events auslösen?
   * Synthese komplexerer Events
 - Backend-Schnittstelle (z.B. direkte Anbindung an Simulator vs.
   GDB-Schnittstelle zu Simulator vs. Anbindung an reale HW) von
   Backend-Architektur (welche Register gibt es, wie breit ist der
   Datenbus, welche Traps können ausgelöst werden, etc.) trennen


==========================================================================================
FailBochs-Bausteine TODO
==========================================================================================
Wer gerade an was arbeitet, steht in Klammern hinter dem TODO.

Bochs:
 - Bug: Nach save() ist momentan hinterher der Instruction-Pointer eins weiter,
   womit nicht unbedingt zu rechnen ist. (rh)
  -> Workaround?  save() ruft implizit restore() ...
 - bei BX_PANIC nicht einfach weitermachen, sondern dem Experiment
   signalisieren, dass der Simulator gepanict hat?

Abstraktionen:
 - Endianness?
 - Merkmalmodell von Implementierungsdetails trennen (hsc)
  -> automatische Konfigurierung anhand Experimentauswahl
  -> Annotierung von Experimentcode, automatisches Nachladen von Aspekten
 - (Allgemeine) Testfälle / Regression-Tests
  -> Modifikationen an FAIL* sind damit leichter zu verifizieren
 - Abstraktionen für Funktionsparameter und -rückgabewerte
 - API zum Übersetzen von Adressen (virtuell [-> linear] -> physikalisch)
  -> ggf. nur noch physikalische (oder virtuelle?) Adressen für diverse
     Listener?
 - SingleBitflipFaultspacePruning kapseln (hsc)

Events/Listener:
 - Umstrukturierung des Event-Managements, damit es performanter wird. Dazu
   werden Aspekte für die Performanz-Verbesserung pro zeitkritischem Typ
   eingewoben. Dabei soll auf eine "search"-Methode zurückgegriffen werden, mit
   der in den typspezifischen Containern gesucht werden kann. [...]
 - Listener-Callback-Funktionalität einführen: von spezifischem Listener
   ableiten, trigger() überschreiben
 - Listener alternativ beliebig lange aktiv lassen (statt sie jedes mal neu
   registrieren zu müssen, wenn einer gefeuert hat)
 - Bug? Wenn z.B. das Tracing-Plugin aktiv ist, ist nicht klar, ob ein
   bestimmtes Ereignis zuerst diesem, oder dem laufenden Experiment zugestellt
   wird; je nach Reihenfolge sieht der rausgeschriebene Trace anders aus
  -> explizites "stell mal alle übrigen Events zu, bevor es mit mir weitergeht"
     im SimulatorController?

Parallelisierung:
 - Momentan landen initial *alle* Parametersätze im Speicher.  Sobald das viel
   mehr werden, wird das eventuell eng.
   -> BoundedSynchronizedQueue basteln, Kampagne blockiert dann, wenn die voll ist
   -> eingehende Resultate nicht in der Kampagne "verarbeiten" (rausschreiben)
      -- sonst bekommen wir dasselbe Problem mit der Queue der Resultate;
      stattdessen z.B. die Idee der ExperimentDataStorage weiterverfolgen,
      Ergebnisse werden asynchron zur Kampagne weggeschrieben
      (oder: Zweiteilung der Kampagne vornehmen, "Verarbeitung" in eigenem
      Thread)
 - coolcampaign fährt momentan ziemlich Achterbahn bei RAM-Benutzung
   -> Grund analysieren, ggf. beheben (Ressourcenverwaltung? Threadpool?)
 - warum skalieren die Experimente/s nicht (ganz) linear mit der Anzahl der
   Cores auf einer Maschine?  Jobserver-Problem, oder lokal Contention auf dem
   Client (Kernel, Disk-IO)?
   -> mal Experimente ohne Kommunikation laufenlassen, Durchsatz messen
   -> mal mit mehreren Maschinen durchmessen
 - JobServer Statistiken ausgeben lassen, dafür keine Meldung mehr bei jedem Auftrag
   * Anzahl Hosts
   * Anzahl Clients (momentan ununterscheidbar ...)
   * Aufträge pro Sekunde
   * ETA bis Kampagne komplett
 - Client/Server-TCP-Verbindungen aufrechterhalten
 - die Möglichkeit schaffen, im Server mehr Informationen über einen Job
   vorzuhalten (und zu loggen), als man an den Client kommuniziert
   -> bei Fault-Space-Pruning hat man im Server Äquivalenzklassen, aus denen
      man nur einen einzelnen Parametersatz auswählt und dem Client zum
      Ausprobieren gibt; die Informationen über die Äquivalenzklasse müss(t)en
      nicht über die Leitung, werden aber am Schluss zur Auswertung gebraucht
 - Build-ID in control message tatsächlich generieren und verwenden!
   - einfacher, aber nicht in allen Fällen wirksam: Server generiert zur
     Laufzeit "Session-ID"; falls bei Client-/Server-Kommunikation diese nicht
     mit der vorherigen übereinstimmt, terminiert der Client automatisch
     * Problem 1: hilft nicht, wenn der Client gerade neu gestartet wurde
     * Problem 2: wenn das viele Clients tun, landen sehr viele unbearbeitete
       Jobs in der Aktiv-Queue auf dem Server
 - mehrere Jobs auf einmal übertragen -> weniger Kommunikationsvorgänge (rh)
   * adaptiv: clientseitig erst nur einen anfordern, Laufzeit messen, die
     folgenden Male immer so viele anfordern, dass (geschätzt) z.B. mindestens
     60s zwischen zwei Kommunikationsvorgängen liegen (mit oberem Limit für
     Anzahl Jobs)
   -> dann müsste man sich über die ganzen serverseitigen Engpässe gar keine
      Gedanken machen

Implementierungsdetails:
 - einheitliche Fehlerbehandlung
 - einheitliches Logging (Loglevels?), Ausgaben (z.B. im Bochs-Controller,
   siehe BochsController::save) vereinheitlichen, evtl. zusätzlich via
   (Non-)Verbose-Mode(s)
   -> "Ausgabesystem", "Logger"
 - einfache, Linux-spezifische Wallclock-Zeitmessung ähnlich boost::timer v2 (rh)
   * Start, Ende, einfache Stringkonvertierung/Ausgabe

Effizienz:
 - getrennte Queues?
 - Queue-Suche optimieren (Hashes, Sortierung, ...)?
 - boolean/Counter für Events (um Durchlaufen der Queue zu verhindern)?
 - Dynamic AspectC++ ausprobieren
 - Löschliste in EventManager via Hashing implementieren (o.Ä.)?

Buildsystem:
 - (mittelfristig) in cmake nur wirklich Build-spezifische Dinge konfigurieren
   (verwendeter Compiler, Installationsverzeichnis, ...), den Rest in einem
   brauchbaren Konfigurationswerkzeug mit Ausdrucksmöglichkeiten für
   Merkmalmodelle, Abhängigkeiten, Mehrfachauswahl etc. (kconfig?)
   * Bochs / T32 / Gem5 sind Alternativen, nicht beide anschaltbar
  -> Cmake-Combo-Box (ggf. noch an anderen Stellen einsetzbar)
     http://www.kitware.com/blog/home/post/82
 - Hinzufügen eines neuen Experiments konkreter dokumentieren (how-to-build.txt?)
 - "Aktivieren" von Aspekten muss anders implementiert werden:
   * Momentan ist es nicht möglich, dass mehrere Build-Verzeichnisse (mit
     Aspekten darin) nebeneinander existieren, da ag++ alle Unterverzeichnisse
     von fail/ nach Aspektheadern durchsucht.
  -> stattdessen (in Cmake) eine globale Liste von aktiven Aspektheadern
     pflegen und diese per ag++-Flag "-a" aktivieren.
  -> ggf. instantiate-foo-experiment.ah nicht mehr generieren (hässlicher, und
     dann unnötiger Hack)

Dokumentation:
 - Änderungen im Klassendiagramm nachziehen
 
Erledigt:
 - alle Events mit Zähler versehen, so dass sie erst bei Erreichen der 0 feuern
   * z.B. erst nach dem 5ten Mal Lesen von Adresse X auslösen
 - Bereiche von Instruction-Pointern
 - Wrapper für häufig auftretende Experimentmuster, z.B. einzelnes Event
   anlegen und dann genau darauf warten
 - Wildcards für beliebige Instruktions- bzw. Speicheradresse (ANY_ADDR, siehe Event.hpp),
   inkl. Anpassung des ausgelösten Events
 - Registerzugriff aus dem Experiment-Controller, RegisterBitflip vorbereitet
 - Auslösen von Reboot (rh)
 - Auslesen von Register- und Speicherzustand (Kontext Golden-Run-Vergleiche etc.)
 - Coroutinen-Bibliothek (oder getcontext/setcontext) statt Threads+Synchronisation?
 - Bitflips in Register
 - nach Eintreten eines Events wird das Event- (oder FI-)Objekt mit
   Detailinformationen befüllt
   -> insbesondere bei "Wildcards" (ANY_TRAP) will man ja im
      Experimentablauf wissen, was jetzt eigentlich passiert ist
 - Event-Aspekt zur Kommunikation mit dem Gastsystem fertig stellen (siehe events/GuestSysCom.ah)
 - Bochs-Spezifika von Bochs-unabhängigen Codeteilen trennen
   -> Simulator-Abstraktionsschicht
   -> Schnittstelle für Informationen über Plattformspezifika, z.B. Register + Bitbreiten
   -> Bochs-spezifische Aspekte leiten nur noch Kontrollfluss um,
      Implementierung von Ereignissen separat
 - (sofern möglich) Ereignisse von FI trennen
 - Scattering-Graphik, (Python-)Skript (ab)
 - ohne GUI bzw. gesetztem $DISPLAY lauffähig? (rh)
 - Save (rh):
   - Zielverzeichnis anlegen, falls nicht existent
   - Fehlermeldung, falls Zielverzeichnis nicht schreibbar
 - FI-Jobs gibt's nicht mehr, überall rauswerfen (ab)
 - Traps und Interrupts (alle, oder Match auf beliebige Teilmenge) 
   (Aspekte existieren bereits. Matchen auf beliebige Teilmenge der Traps ist noch nicht moeglich)
   (rh)
 - die schlimmsten Speicherlecks in Bochs eliminieren (rh)
 - Event-IDs als Identifikationsmittel für Events auf den zweiten Platz verweisen
   -> IDs gibt's weiterhin (getId()), aber z.B. waitAny() liefert einen Pointer (ab)
 - Brauchen wir eigentlich IDs als Handles für Events, oder genügt es nicht
   eigentlich, die Event-Objektadresse zu verwenden? (ab)
 - Event-Match-Schleife von Event-Feuer-Schleife trennen (ab):
   - erst alle Events, die aktuell matchen, sammeln (Code ggf. spezifisch für die Ereignisart)
   - dann sequentiell feuern (Code zentral in SimulatorController)
   -> keine Probleme mit nachträglich hinzukommenden Events
   - dann leider immer noch Probleme mit nachträglich entfernten Events
   -> siehe fail/experiments/coolchecksum/experiment.cc FIXME am Ende
   -> Lösung: Löschliste
   - ggf. zusammen mit Datenstruktur-Implementierungsdetails-TODO (s.u.) angehen
 - FailConfig.hpp in cmake-config einbinden (genauso behandeln wie experiments.hpp!)
   -> generierte Datei landet in Buildtree, wird nicht mehr eingecheckt
 - variant_config.h in cmake-config einbinden (genauso behandeln wie experiments.hpp!)
   -> generierte Datei landet in Buildtree, wird nicht mehr eingecheckt
 - EXP*-options nur einmal in config/, nicht in drei verschiedenen Dateien
   (config/CMakelists.txt, config/experiments.hpp.in,
   experiments/CMakeLists.txt)
 - zum Verpacken in ExperimentData-Nachrichten Register<->String-Konvertierung
   vereinfachen (ab)
 - Speicherzugriffe: bei Instruction Fetch?  INC $Adresse?  CALL?  PUSH?
   PUSHF?  Interrupt? (ab)
 - Timer (Bochs: basierend auf bx_pc_system.register_timer()) für "echte"
   Timeouts (die auch dann greifen, wenn die CPU z.B. in einem CLI/HLT steht) (ab)
 - Client-Timeouts untersuchen, Server-Implementierung tunen?  Retries im Client? (ab)
 - unbeantwortete Jobs am Ende einer Kampagne erneut vergeben (ab)
 - Namespace Confusion: aufräumen (ab)
 - Verzeichnisstruktur umstrukturieren und aufräumen (ab)
 - Determinismus: Wie kann für Mikroexperimente sichergestellt werden, dass
   externe Ereignisse (Timer, Eingang von Netzwerkpaketen, ...) reproduzierbar
   zum selben Zeitpunkt eintreffen? (rh)
   - Interrupts teilweise oder komplett sperren
   - optional: Interrupts auslösen
 - Traces: geeignet kapseln, in einer Sequenz von protobuf-Nachrichten statt
   einer großen rausschreiben/laden (rh)
 - einheitliches Namensschema für Backend-Beeinflussungen (Interrupt-Synthese,
   Interrupt-Unterdrückung, Speicher schreiben, Register schreiben, ...) finden
   -> "Fehlerinjektion" ist das ja nicht immer
 - Aktuelle Events sind viel mehr "Listener", die auf eine ganze Klasse von
   Ereignissen warten (semantische Ungenauigkeit)
    -> benenne Events um ("Listener")
    -> Erstelle neue Klassenhierarchie, die den "Informationsanteil" der "Events"
       repräsentiert. Diese kapseln dann die Informationen in den Events und
       werden zudem intern im FAIL*-Framework verwendet (genauer: kommuniziert).

==========================================================================================
Theorie TODO
==========================================================================================
 - Problem Fork von FI Tools -> Merging eklig.
   -> Liste mit konkreten Beispielen 
