aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--articles/2010-02-06_debian_auf_dem_sheevaplug.md44
-rw-r--r--articles/2011-03-31_sheevaplug_ueberwachung.md112
-rw-r--r--articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md114
-rw-r--r--articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md5
-rw-r--r--articles/2011-11-08_informationen_umformen_mit_xsl.md196
-rw-r--r--articles/2012-01-25_erfahrungen_mit_openslides.md45
-rw-r--r--articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md19
-rw-r--r--articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md70
-rw-r--r--articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md24
-rw-r--r--articles/2013-10-06_notizen_zu_cpp_und_unicode.md82
-rw-r--r--articles/2013-11-03_mapping_binary_structures_as_tuples_using_template_metaprogramming.md279
-rw-r--r--articles/2014-01-05_disabling_methods_in_implicitly_instantiated_class_template_specializations_in_cpp.md67
-rw-r--r--articles/2014-07-11_mapping_arrays_using_tuples_in_cpp11.md84
13 files changed, 625 insertions, 516 deletions
diff --git a/articles/2010-02-06_debian_auf_dem_sheevaplug.md b/articles/2010-02-06_debian_auf_dem_sheevaplug.md
index df98769..23b0a17 100644
--- a/articles/2010-02-06_debian_auf_dem_sheevaplug.md
+++ b/articles/2010-02-06_debian_auf_dem_sheevaplug.md
@@ -4,36 +4,54 @@ Auf dem herkömmlichen [Weg](http://www.cyrius.com/debian/kirkwood/sheevaplug/)
Als erstes laden wir uns den normalen SheevaInstaller herunter mit dem man Ubuntu 9.04 auf dem Sheeva installieren kann ([klick](http://www.plugcomputer.org/index.php/us/resources/downloads?func=select&id=5)). Nach dem wir den Tarball heruntergeladen haben sollte man ihn entpacken. Als nächstes laden wir ein Debian Lenny / Squeeze Prebuild von [hier](http://www.mediafire.com/sheeva-with-debian) herunter. Nun ersetzen wir die „rootfs.tar.gz“ mit der neuen Debian „rootfs.tar.gz“. Bevor wir jedoch mit der Installation beginnen müssen wir die neue „rootfs.tar.gz“ mit „tar“ entpacken. Dazu führen wir auf der Konsole
- mkdir rootfs
- cd rootfs
- tar xfvz rootfs.tar.gz
+~~~
+mkdir rootfs
+cd rootfs
+tar xfvz rootfs.tar.gz
+~~~
+{: .language-sh}
aus. In dem Ordner führen wir nun ein
- mknod -m 660 dev/ttyS0 c 4 64
+~~~
+mknod -m 660 dev/ttyS0 c 4 64
+~~~
+{: .language-sh}
aus. Mit diesem Befehl wird die fehlende serielle Konsole erstellt. Jetzt verpacken wir das Archiv wieder mit
- tar cfvz ../rootfs.tar.gz *
+~~~
+tar cfvz ../rootfs.tar.gz *
+~~~
+{: .language-sh}
Den gesamten Inhalt des Ordners /install im SheevaInstaller-Verzeichniss müssen wir jetzt auf einen mit FAT formatierten USB-Stick kopieren. Diesen stecken wir schon einmal in den USB-Port des Sheevas. Als nächstes verbinden wir den SheevaPlug mit einem Mini-USB Kabel mit unserem Computer und führen das Script „runme.php“ aus. Wenn alles klappt wird nun ein neuer Boot-Loader und das rootfs auf den Plug kopiert. Dannach ist unser Debian einsatzbereit.
Sollte der Plug den USB-Stick nicht erkennen und somit auch das rootfs nicht kopieren können hilft es einen anderen USB-Stick zu verwenden. Beispielsweise wurde mein SanDisk U3 Stick trotz gelöschtem U3 nicht erkannt. Mit einem anderen Stick funktionierte es jedoch tadelos. Auch sollte der Stick partitioniert sein. Der Bootloader des SheevaPlugs kann nicht gut mit direkt auf dem Stick enthalten Dateisystemen umgehen. Wenn die MiniUSB Verbindung beim Ausführen des runme-Scripts nicht funktionieren sollte hilft oft ein
- rmmod ftdi_sio
+~~~
+rmmod ftdi_sio
+~~~
+{: .language-sh}
und
- modprobe ftdi_sio vendor=0x9e88 product=0x9e8f
+~~~
+modprobe ftdi_sio vendor=0x9e88 product=0x9e8f
+~~~
+{: .language-sh}
(beides als root). Ebenfalls sollte kein zweites Serielles-Gerät am Computer angeschlossen sein.
Bei neueren Plugs kann man bei Problemen bei der Installation die Datei „uboot/openocd/config/interface/sheevaplug.cfg“ im SheevaInstaller-Ordner nach
- interface ft2232
- ft2232_layout sheevaplug
- ft2232_vid_pid 0×0403 0×6010
- #ft2232_vid_pid 0x9e88 0x9e8f
- #ft2232_device_desc “SheevaPlug JTAGKey FT2232D B”
- jtag_khz 2000
+~~~
+interface ft2232
+ft2232_layout sheevaplug
+ft2232_vid_pid 0×0403 0×6010
+#ft2232_vid_pid 0x9e88 0x9e8f
+#ft2232_device_desc “SheevaPlug JTAGKey FT2232D B”
+jtag_khz 2000
+~~~
+{: .language-sh}
umändern.
Wenn Debian jetzt auf dem SheevaPlug läuft und man sich über SSH einloggen konnte (pwd: nosoup4u), sollte man als erstes ein Update machen.
diff --git a/articles/2011-03-31_sheevaplug_ueberwachung.md b/articles/2011-03-31_sheevaplug_ueberwachung.md
index 74dfa88..0cbea1c 100644
--- a/articles/2011-03-31_sheevaplug_ueberwachung.md
+++ b/articles/2011-03-31_sheevaplug_ueberwachung.md
@@ -9,7 +9,10 @@ Den Systemmonitor Conky lasse ich mit dem Befehl `ssh -X -vv -Y -p 22 adrian@ast
Zusätzlich loggt der SheevaPlug regelmäßig die aktuellen Systemdaten wie CPU-Auslastung, Netzwerkverkehr und belegten Arbeitsspeicher und generiert sie zu Graphen die mir dann jede Nacht per eMail zugesand werden.
Zum Loggen der Daten verwende ich dstat das mit folgendem, von einem Cron-Job gestarteten Befehl aufgerufen wird:
- dstat -tcmn 2 1 | tail -1 >> /var/log/systat.log
+~~~
+dstat -tcmn 2 1 | tail -1 >> /var/log/systat.log
+~~~
+{: .language-sh}
Die Argumente -tcmn geben hierbei die zu loggenden Systemdaten und deren Reihenfolge an – heraus kommen Zeilen wie diese:
@@ -17,61 +20,70 @@ Die Argumente -tcmn geben hierbei die zu loggenden Systemdaten und deren Reihenf
Um 0 Uhr wird dann die Log-Datei von einem Cron-Job mit diesem Script wegkopiert, Graphen werden von gnuplot generiert und dann mit einem kleinen Python-Programm versendet.
- #!/bin/sh
- mv /var/log/systat.log /root/sys_graph/stat.dat
- cd /root/sys_graph/
- ./generate_cpu.plot
- ./generate_memory.plot
- ./generate_network.plot
- ./send_report.py
+~~~
+#!/bin/sh
+mv /var/log/systat.log /root/sys_graph/stat.dat
+cd /root/sys_graph/
+./generate_cpu.plot
+./generate_memory.plot
+./generate_network.plot
+./send_report.py
+~~~
+{: .language-sh}
Hier das gnuplot-Script zur Erzeugung des CPU-Graphen als Beispiel:
- #!/usr/bin/gnuplot
- set terminal png
- set output "cpu.png"
- set title "CPU usage"
- set xlabel "time"
- set ylabel "percent"
- set xdata time
- set timefmt "%d-%m %H:%M:%S"
- set format x "%H:%M"
- plot "stat.dat" using 1:4 title "system" with lines, \
- "stat.dat" using 1:3 title "user" with lines, \
- "stat.dat" using 1:5 title "idle" with lines
+~~~
+#!/usr/bin/gnuplot
+set terminal png
+set output "cpu.png"
+set title "CPU usage"
+set xlabel "time"
+set ylabel "percent"
+set xdata time
+set timefmt "%d-%m %H:%M:%S"
+set format x "%H:%M"
+plot "stat.dat" using 1:4 title "system" with lines, \
+"stat.dat" using 1:3 title "user" with lines, \
+"stat.dat" using 1:5 title "idle" with lines
+~~~
+{: .language-sh}
… und hier noch das Python-Programm zum Versenden per Mail:
- #!/usr/bin/python2
- import smtplib
- from time import *
- from email.mime.image import MIMEImage
- from email.mime.multipart import MIMEMultipart
-
- lt = localtime()
-
- # Mail-Header
- msg = MIMEMultipart()
- msg['Subject'] = strftime('Leistungsreport – %d%m%Y', lt)
- msg['From'] = 'reports@asterix'
- msg['To'] = 'mail@mail.mail'
-
- msg.preamble = strftime('Leistungsreport – %d%m%Y', lt)
-
- # Attachments
- fileArray = ['cpu.png','memory.png','network.png']
- for file in fileArray:
- fp = open(file, ‘rb’)
- img = MIMEImage(fp.read())
- fp.close()
- msg.attach(img)
-
- # Login in SMTP-Server
- s = smtplib.SMTP('smtpmail.t-online.de')
- s.login('mail@mail.mail', '#####')
-
- s.sendmail('mail@mail.mail', 'mail@mail.mail', msg.as_string())
- s.quit()
+~~~
+#!/usr/bin/python2
+import smtplib
+from time import *
+from email.mime.image import MIMEImage
+from email.mime.multipart import MIMEMultipart
+
+lt = localtime()
+
+# Mail-Header
+msg = MIMEMultipart()
+msg['Subject'] = strftime('Leistungsreport – %d%m%Y', lt)
+msg['From'] = 'reports@asterix'
+msg['To'] = 'mail@mail.mail'
+
+msg.preamble = strftime('Leistungsreport – %d%m%Y', lt)
+
+# Attachments
+fileArray = ['cpu.png','memory.png','network.png']
+for file in fileArray:
+ fp = open(file, ‘rb’)
+ img = MIMEImage(fp.read())
+ fp.close()
+ msg.attach(img)
+
+# Login in SMTP-Server
+s = smtplib.SMTP('smtpmail.t-online.de')
+s.login('mail@mail.mail', '#####')
+
+s.sendmail('mail@mail.mail', 'mail@mail.mail', msg.as_string())
+s.quit()
+~~~
+{: .language-python}
Als Endergebniss erhalte ich dann täglich solche Grafiken per Mail:
diff --git a/articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md b/articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md
index 8687ba1..83202a3 100644
--- a/articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md
+++ b/articles/2011-06-14_darstellen_von_gps_daten_mit_gnuplot.md
@@ -4,43 +4,53 @@ Bei meiner letzten Wanderung in den Schweizer Alpen habe ich spaßeshalber das N
Die Daten der Messpunkte sind im XML als `trkpt`-Tags gespeichert. Enthalten sind jeweils der Längen- und Breitengrad, die Uhrzeit, der Modus (3d / 2d), die Höhe über Null und die Anzahl der zur Positionsbestimmung genutzten Satelliten. Aussehen tut das ganze dann z.B. so:
- <trkpt lat="47.320591" lon="9.329439">
- <time>2011-06-12T07:57:39Z</time>
- <fix>3d</fix>
- <ele>870</ele>
- <sat>6</sat>
- </trkpt>
+~~~
+<trkpt lat="47.320591" lon="9.329439">
+ <time>2011-06-12T07:57:39Z</time>
+ <fix>3d</fix>
+ <ele>870</ele>
+ <sat>6</sat>
+</trkpt>
+~~~
+{: .language-xml}
Diese Daten lassen sich nun sehr einfach Verarbeiten – ich habe das Python `xml.dom.minidom` Modul verwendet. Um die Positionen einfacher verwenden zu können, werden sie mit dieser Funktion in Listenform gebracht:
- def getPositions(xml):
- doc = minidom.parse(xml)
- node = doc.documentElement
- rawTrkPt = doc.getElementsByTagName("trkpt")
- positions = []
- for TrkPt in rawTrkPt:
- pos = {}
- pos["lat"] = TrkPt.getAttribute("lat")
- pos["lon"] = TrkPt.getAttribute("lon")
- pos["ele"] = int(TrkPt.getElementsByTagName("ele")[0].childNodes[0].nodeValue)
- positions.append(pos)
- return positions
+~~~
+def getPositions(xml):
+ doc = minidom.parse(xml)
+ node = doc.documentElement
+ rawTrkPt = doc.getElementsByTagName("trkpt")
+ positions = []
+ for TrkPt in rawTrkPt:
+ pos = {}
+ pos["lat"] = TrkPt.getAttribute("lat")
+ pos["lon"] = TrkPt.getAttribute("lon")
+ pos["ele"] = int(TrkPt.getElementsByTagName("ele")[0].childNodes[0].nodeValue)
+ positions.append(pos)
+ return positions
+~~~
+{: .language-python}
Aus dieser Liste kann ich jetzt schon einige Kennzahlen ziehen:
- def printStats(gpxPositions):
- highEle = gpxPositions[0]["ele"]
- lowEle = gpxPositions[0]["ele"]
- for pos in gpxPositions:
- if pos["ele"] > highEle:
- highEle = pos["ele"]
- if pos["ele"] < lowEle:
- lowEle = pos["ele"]
- eleDiv = highEle - lowEle
- print "Measure points: " + str(len(gpxPositions))
- print "Lowest elevation: " + str(lowEle)
- print "Highest elevation: " + str(highEle)
- print "Height difference: " + str(eleDiv)
+~~~
+def printStats(gpxPositions):
+ highEle = gpxPositions[0]["ele"]
+ lowEle = gpxPositions[0]["ele"]
+ for pos in gpxPositions:
+ if pos["ele"] > highEle:
+ highEle = pos["ele"]
+ if pos["ele"] < lowEle:
+ lowEle = pos["ele"]
+ eleDiv = highEle - lowEle
+ print "Measure points: " + str(len(gpxPositions))
+ print "Lowest elevation: " + str(lowEle)
+ print "Highest elevation: " + str(highEle)
+ print "Height difference: " + str(eleDiv)
+~~~
+{: .language-python}
+
Die Kennzahlen für meine Testdaten wären:
@@ -51,10 +61,13 @@ Die Kennzahlen für meine Testdaten wären:
Da die Daten ja, wie schon im Titel angekündigt, mit gnuplot dargestellt werden sollen werden sie mit dieser Funktion in für gnuplot lesbares CSV gebracht:
- def printCsv(gpxPositions):
- separator = ';'
- for pos in gpxPositions:
- print pos["lat"] + separator + pos["lon"] + separator + str(pos["ele"])
+~~~
+def printCsv(gpxPositions):
+ separator = ';'
+ for pos in gpxPositions:
+ print pos["lat"] + separator + pos["lon"] + separator + str(pos["ele"])
+~~~
+{: .language-python}
### Plotten mit gnuplot
@@ -62,20 +75,23 @@ Da die Daten ja, wie schon im Titel angekündigt, mit gnuplot dargestellt werden
Eine solche, dreidimensionale Ausgabe der GPS Daten zu erzeugen ist mit der `splot`-Funktion sehr einfach.
- #!/usr/bin/gnuplot
- set terminal png size 1280,1024
- set output "output.png"
- set multiplot
- set yrange [9.365:9.31]
- set xrange [47.325:47.28]
- set zrange [800:1700]
- set view 28,272,1,1
- set ticslevel 0
- set grid
- set datafile separator ';'
- splot "/home/adrian/projects/gpxplot/wanderung_120611.csv" with impulses lt 3 lw 1
- splot "/home/adrian/projects/gpxplot/wanderung_120611.csv" with lines lw 2
- unset multiplot
+~~~
+#!/usr/bin/gnuplot
+set terminal png size 1280,1024
+set output "output.png"
+set multiplot
+set yrange [9.365:9.31]
+set xrange [47.325:47.28]
+set zrange [800:1700]
+set view 28,272,1,1
+set ticslevel 0
+set grid
+set datafile separator ';'
+splot "/home/adrian/projects/gpxplot/wanderung_120611.csv" with impulses lt 3 lw 1
+splot "/home/adrian/projects/gpxplot/wanderung_120611.csv" with lines lw 2
+unset multiplot
+~~~
+{: .language-sh}
Mit `set terminal png size 1280,1024` und `set output "output.png"` werden zuerst das Ausgabemedium, die Größe und der Dateiname der Ausgabe definiert. Dannach aktiviert `set multiplot` den gnuplot-Modus, bei dem mehrere Plots in einer Ausgabe angezeigt werden können. Dieses Verhalten brauchen wir hier, um sowohl die Strecke selbst als rote Line, als auch die zur Verdeutlichung verwendeten blauen Linien gleichzeitig anzuzeigen.
Mit `set [y,x,z]range` werden die Außengrenzen des zu plottenden Bereichs gesetzt. Dies ließe sich natürlich auch über ein Script automatisch erledigen. Als Nächstes wird mit `set view 28,272,1,1` die Blickrichtung und Skalierung definiert. `set ticslevel 0` sorgt dafür, dass die Z-Achse direkt auf der Grundebene beginnt. Um ein Gitter auf der Grundfläche anzuzeigen, gibt es `set grid`.
diff --git a/articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md b/articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md
index 65fc7e7..f59b709 100644
--- a/articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md
+++ b/articles/2011-10-16_kurztipp_n900_retten_ohne_neu_zu_flashen.md
@@ -7,6 +7,9 @@ Erst sah es so aus, als würde ich nicht darum herum kommen das Betriebsystem ne
Dabei handelt es sich um ein kleines Linux welches mithilfe des normalen [Flashers](http://tablets-dev.nokia.com/maemo-dev-env-downloads.php) direkt in den RAM des N900 kopiert und dort gebootet werden kann. Vom rescueOS aus kann man dann das Root-Dateisystem problemlos einbinden und Probleme beheben. Zum Starten reicht das [initrd Image](http://n900.quitesimple.org/rescueOS/rescueOS-1.0.img) und folgender Befehl:
- flasher-3.5 -k 2.6.37 -n initrd.img -l -b"rootdelay root=/dev/ram0"
+~~~
+flasher-3.5 -k 2.6.37 -n initrd.img -l -b"rootdelay root=/dev/ram0"
+~~~
+{: .language-sh}
Nähere Informationen zur Verwendung und den Funktionen finden sich in der rescueOS [Dokumentation](http://n900.quitesimple.org/rescueOS/documentation.txt).
diff --git a/articles/2011-11-08_informationen_umformen_mit_xsl.md b/articles/2011-11-08_informationen_umformen_mit_xsl.md
index 40777d0..47f9973 100644
--- a/articles/2011-11-08_informationen_umformen_mit_xsl.md
+++ b/articles/2011-11-08_informationen_umformen_mit_xsl.md
@@ -8,49 +8,57 @@ Schlussendlich habe ich dann eine [XSLT](http://de.wikipedia.org/wiki/XSLT) gesc
Mit XSL lassen sich XML Dateien in andere Formen bringen. Da Mediawiki mehr oder weniger valides XHTML ausgibt, kann man, nachdem das XHTML mit [Tidy](http://tidy.sourceforge.net) ein wenig aufgeräumt wurde, sehr einfach die [Terminliste](http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine) extrahieren und gleichzeitig in RSS umformen:
- <xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:x="http://www.w3.org/1999/xhtml"
- exclude-result-prefixes="x">
-
- <xsl:import href="date-time.xsl"/>
-
- <xsl:output method="xml"
- doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
- doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
- omit-xml-declaration="yes"
- encoding="UTF-8"
- indent="yes" />
-
- <xsl:template match="/">
- <rss version="2.0">
- <channel>
- <title>Termine des KV Konstanz</title>
- <link>http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine</link>
- <description>Termine des KV Konstanz</description>
- <xsl:apply-templates/>
- </channel>
- </rss>
- </xsl:template>
-
- <xsl:template match="x:div[@id='pkn_main']/x:table">
- <xsl:for-each select="x:tr">
- <xsl:choose>
- <xsl:when test="position() > 1">
- <item>
- <title><xsl:value-of select="x:td[3]"/> am <xsl:call-template name="format-date">
- <xsl:with-param name="date" select="x:td[1]/x:span/."/>
- <xsl:with-param name="format" select="'d.n.Y'"/></xsl:call-template> um <xsl:value-of select="x:td[2]"/> Uhr</title>
- <link>http://wiki.piratenpartei.de<xsl:value-of select="x:td[3]/x:a/@href"/></link>
- </item>
- </xsl:when>
- </xsl:choose>
- </xsl:for-each>
- </xsl:template>
-
- <xsl:template match="text()"/>
-
- </xsl:stylesheet>
+~~~
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:x="http://www.w3.org/1999/xhtml"
+ exclude-result-prefixes="x">
+
+<xsl:import href="date-time.xsl"/>
+
+<xsl:output method="xml"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+ omit-xml-declaration="yes"
+ encoding="UTF-8"
+ indent="no" />
+
+<xsl:template match="/">
+ <rss version="2.0">
+ <channel>
+ <title>Termine des KV Konstanz</title>
+ <link>http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine</link>
+ <description>Termine des KV Konstanz</description>
+ <xsl:apply-templates/>
+ </channel>
+ </rss>
+</xsl:template>
+
+<xsl:template match="x:div[@id='pkn_main']/x:table/x:tr[position() &gt; 1]">
+ <item>
+ <title>
+ <xsl:value-of select="x:td[3]"/>
+ <xsl:text> am </xsl:text>
+ <xsl:call-template name="format-date">
+ <xsl:with-param name="date" select="x:td[1]/x:span/."/>
+ <xsl:with-param name="format" select="'d.n.Y'"/>
+ </xsl:call-template>
+ <xsl:text> um </xsl:text>
+ <xsl:value-of select="x:td[2]"/>
+ <xsl:text> Uhr</xsl:text>
+ </title>
+ <link>
+ <xsl:text>http://wiki.piratenpartei.de</xsl:text>
+ <xsl:value-of select="x:td[3]/x:a/@href"/>
+ </link>
+ </item>
+</xsl:template>
+
+<xsl:template match="text()"/>
+
+</xsl:stylesheet>
+~~~
+{: .language-xsl}
Der Kern dieses XSL ist nicht mehr als ein Template welches auf den [XPATH](http://de.wikipedia.org/wiki/XPATH) zum Finden der Terminliste reagiert. Die For-Each-Schleife iteriert dann durch die Termine und formt diese entsprechend in RSS um.
Der einzige Knackpunkt kommt daher, dass XHTML kein normales XML ist und somit seinen eigenen Namespace hat. Diesen sollte man im Element `xsl:stylesheet` korrekt angeben, sonst funktioniert nichts. Auch muss im XPATH Ausdruck dann vor jedem Element ein `x:` eingefügt werden um dem XSL Prozessor den Namespace für das jeweilige Element mitzuteilen.
@@ -64,66 +72,72 @@ Zum Anpassen des Datums verwende ich - wie auch in diesem Blog - die [date-time.
Mit der eben beschriebenen XSLT lässt sich jetzt in drei Schritten das fertige RSS generieren:
- #!/bin/sh
- wget -O termine_wiki.html "http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine"
- tidy -asxml -asxhtml -O termine_tidy.html termine_wiki.html
- xsltproc --output termine_kvkn.rss --novalid termine_kvkn.xsl termine_tidy.html
+~~~
+#!/bin/sh
+wget -O termine_wiki.html "http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine"
+tidy -asxml -asxhtml -O termine_tidy.html termine_wiki.html
+xsltproc --output termine_kvkn.rss --novalid termine_kvkn.xsl termine_tidy.html
+~~~
+{: .language-sh}
In PHP ist das ganze dann zusammen mit sehr einfachem Caching auch direkt auf einem Webserver einsetzbar:
- define('CACHE_TIME', 6);
- define('CACHE_FILE', 'rss.cache');
+~~~
+define('CACHE_TIME', 6);
+define('CACHE_FILE', 'rss.cache');
- header("Content-Type: application/rss+xml");
+header("Content-Type: application/rss+xml");
- if ( file_exists(CACHE_FILE) )
- {
- if ( !filemtime(CACHE_FILE) < time() - CACHE_TIME * 3600 ) {
- readfile(CACHE_FILE);
- }
- else {
- if ( !generate_rss() ) {
- readfile(CACHE_FILE);
- }
- }
+if ( file_exists(CACHE_FILE) )
+{
+ if ( !filemtime(CACHE_FILE) < time() - CACHE_TIME * 3600 ) {
+ readfile(CACHE_FILE);
}
else {
- ob_start();
-
- generate_rss();
-
- ob_end_flush();
-
- $cache_file = fopen(CACHE_FILE, 'w');
- fwrite($cache_file, ob_get_contents());
- fclose($cache_file);
+ if ( !generate_rss() ) {
+ readfile(CACHE_FILE);
+ }
}
-
- function generate_rss()
+}
+else {
+ ob_start();
+
+ generate_rss();
+
+ ob_end_flush();
+
+ $cache_file = fopen(CACHE_FILE, 'w');
+ fwrite($cache_file, ob_get_contents());
+ fclose($cache_file);
+}
+
+function generate_rss()
+{
+ $event_page = file_get_contents('http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine');
+
+ if ($event_page != false)
{
- $event_page = file_get_contents('http://wiki.piratenpartei.de/BW:Kreisverband_Konstanz/Termine');
-
- if ($event_page != false)
- {
- $config = array('output-xhtml' => true, 'output-xml' => true);
+ $config = array('output-xhtml' => true, 'output-xml' => true);
- $tidy = new tidy();
+ $tidy = new tidy();
- $xml = new DomDocument();
- $xml->loadXML( $tidy->repairString($event_page, $config) );
+ $xml = new DomDocument();
+ $xml->loadXML( $tidy->repairString($event_page, $config) );
- $xsl = new DomDocument();
- $xsl->load('termine_kvkn.xsl');
+ $xsl = new DomDocument();
+ $xsl->load('termine_kvkn.xsl');
- $xslt = new XsltProcessor();
- $xslt->importStylesheet($xsl);
+ $xslt = new XsltProcessor();
+ $xslt->importStylesheet($xsl);
- $rss = $xslt->transformToXML($xml);
- echo $rss;
-
- return true;
- }
- else {
- return false;
- }
+ $rss = $xslt->transformToXML($xml);
+ echo $rss;
+
+ return true;
+ }
+ else {
+ return false;
}
+}
+~~~
+{: .language-php}
diff --git a/articles/2012-01-25_erfahrungen_mit_openslides.md b/articles/2012-01-25_erfahrungen_mit_openslides.md
index 3d7c534..a3fde3a 100644
--- a/articles/2012-01-25_erfahrungen_mit_openslides.md
+++ b/articles/2012-01-25_erfahrungen_mit_openslides.md
@@ -20,27 +20,30 @@ Theoretisch ermöglicht es diese Software also - bei entsprechender Authentifizi
Der einzige Punkt der mich wirklich störte war die fehlende Anzeige von Wahlergebnissen der Teilnehmer die eine Wahl verloren hatten. Die jeweilige Stimmenzahl war im Frontend erst sichtbar nachdem der entsprechende Kandidat als Sieger markiert worden war.
Doch auch dieses Problem ließ sich - OpenSource sei Dank - schnell über manuelles Eingreifen im Quelltext korrigieren:
- --- /home/adrian/Downloads/original_views.py
- +++ /opt/hg.openslides.org/openslides/agenda/views.py
- @@ -132,14 +132,11 @@
- for poll in assignment.poll_set.all():
- if poll.published:
- if candidate in poll.options_values:
- - if assignment.is_elected(candidate):
- - option = Option.objects.filter(poll=poll).filter(user=candidate)[0]
- - if poll.optiondecision:
- - tmplist[1].append([option.yes, option.no, option.undesided])
- - else:
- - tmplist[1].append(option.yes)
- + option = Option.objects.filter(poll=poll).filter(user=candidate)[0]
- + if poll.optiondecision:
- + tmplist[1].append([option.yes, option.no, option.undesided])
- else:
- - tmplist[1].append("")
- + tmplist[1].append(option.yes)
- else:
- tmplist[1].append("-")
- votes.append(tmplist)
+~~~
+--- /home/adrian/Downloads/original_views.py
++++ /opt/hg.openslides.org/openslides/agenda/views.py
+@@ -132,14 +132,11 @@
+ for poll in assignment.poll_set.all():
+ if poll.published:
+ if candidate in poll.options_values:
+- if assignment.is_elected(candidate):
+- option = Option.objects.filter(poll=poll).filter(user=candidate)[0]
+- if poll.optiondecision:
+- tmplist[1].append([option.yes, option.no, option.undesided])
+- else:
+- tmplist[1].append(option.yes)
++ option = Option.objects.filter(poll=poll).filter(user=candidate)[0]
++ if poll.optiondecision:
++ tmplist[1].append([option.yes, option.no, option.undesided])
+ else:
+- tmplist[1].append("")
++ tmplist[1].append(option.yes)
+ else:
+ tmplist[1].append("-")
+ votes.append(tmplist)
+~~~
+{: .language-diff}
OpenSlides ist wirklich ein tolles Stück Software und ich kann nur jedem der vor der Aufgabe steht eine Versammlung zu organisieren, sei es die eines Vereins oder wie in meinem Fall die einer Partei, empfehlen sich es einmal näher anzusehen.
Weitere Angaben zur Installation und Konfiguration finden sich auf der [Webpräsenz](http://openslides.org/de/index.html) und im [Quell-Archiv](http://openslides.org/download/openslides-1.1.tar.gz).
diff --git a/articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md b/articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md
index b714997..ebe48e5 100644
--- a/articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md
+++ b/articles/2012-08-29_erfahrungen_mit_einer_ssd_unter_linux.md
@@ -21,14 +21,17 @@ nötig sein sollte ist das umso besser. Die 16 GiB SD-Karte des SheevaPlugs läu
Hier meine derzeitige `/etc/fstab`:
- #
- # /etc/fstab: static file system information
- #
- # <file system> <dir> <type> <options> <dump> <pass>
- tmpfs /tmp tmpfs nodev,nosuid 0 0
-
- /dev/sda1 swap swap defaults,noatime,discard 0 0
- /dev/sda2 / ext4 defaults,noatime,discard,data=ordered 0 0
+~~~
+#
+# /etc/fstab: static file system information
+#
+# <file system> <dir> <type> <options> <dump> <pass>
+tmpfs /tmp tmpfs nodev,nosuid 0 0
+
+/dev/sda1 swap swap defaults,noatime,discard 0 0
+/dev/sda2 / ext4 defaults,noatime,discard,data=ordered 0 0
+~~~
+{: .language-sh}
### Verschlüsselung?
diff --git a/articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md b/articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md
index 42cc891..ae7c783 100644
--- a/articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md
+++ b/articles/2012-11-20_virtualisierung_mit_kvm_und_virtuelle_netzwerke_mit_vde.md
@@ -25,8 +25,11 @@ des Gast-Systems werden auf die gleiche Weise gesetzt. Aus diesem Grund gehe ich
Hier als Beispiel mein derzeitiger Standardaufruf von KVM, der für alle VMs gleich ist. Dynamisch ist allein das zu verwendende Speicher-Gerät - in meinem Fall verschiedene Image-Dateien.
- #!/bin/sh
- qemu-kvm -cpu host -hda $1 -m 1024 -daemonize -vnc none -usb -net nic -net vde
+~~~
+#!/bin/sh
+qemu-kvm -cpu host -hda $1 -m 1024 -daemonize -vnc none -usb -net nic -net vde
+~~~
+{: .language-sh}
Dieser verwendet das als erster Parameter übergebene Gerät als Festplatte und setzt neben den nötigen Netzwerk-Einstellungen die VM mittels `-daemonize` in den Hintergrund. Falls benötigt, kann
als Wert des Parameters `-vnc` auch eine von einem Doppelpunkt angeführte Zahl übergeben werden um die Grafik-Ausgabe der VM an einen VNC-Server anzubinden (z.B. `-vnc :1` für `127.0.0.1:1`). Diese
@@ -38,19 +41,22 @@ Funktion verwende ich nicht, da ich ausschließlich über das interne Netzwerk d
Meine Konfiguration hält sich dabei im wesentlichen an den [Vorschlag](https://wiki.archlinux.org/index.php/QEMU#Networking_with_VDE2) im englischen Arch-Wiki, welchen ich in ein einfaches Script verpackt habe:
- #!/bin/sh
- case "$1" in
- start)
- tunctl -t tap0
- vde_switch -tap tap0 -daemon -pidfile .switch.pid -mod 660 -group kvm
- ifconfig tap0 192.168.100.254 netmask 255.255.255.0
- ;;
- stop)
- kill -9 `cat .switch.pid`
- rm .switch.pid
- tunctl -d tap0
- ;;
- esac
+~~~
+#!/bin/sh
+case "$1" in
+ start)
+ tunctl -t tap0
+ vde_switch -tap tap0 -daemon -pidfile .switch.pid -mod 660 -group kvm
+ ifconfig tap0 192.168.100.254 netmask 255.255.255.0
+ ;;
+ stop)
+ kill -9 `cat .switch.pid`
+ rm .switch.pid
+ tunctl -d tap0
+ ;;
+esac
+~~~
+{: .language-sh}
Dieses Script erzeugt ein virtuelles Interface `tap0` und verbindet ein neues, als Daemon im Hintergrund laufendes, virtuelles Switch mit diesem. Als nächstes wird dann noch eine statische IP
Konfiguration für das virtuelle Interface definiert. Durch diese können alle mit `-net nic -net vde` Parametern gestarteten KVM Gäste über die IP `192.168.100.254` auf den Host zugreifen.
@@ -65,17 +71,20 @@ In den Gast-Systemen selbst muss zusätzlich eine statische IP Konfiguration vor
Um das interne virtuelle LAN bei Bedarf mit der Außenwelt zu verbinden gibt es ebenfalls ein kleines Script welches die nötige Route erzeugt bzw. löscht:
- #!/bin/sh
- case "$1" in
- start)
- echo "1" > /proc/sys/net/ipv4/ip_forward
- iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o $2 -j MASQUERADE
- ;;
- stop)
- iptables -t nat -X
- echo "0" > /proc/sys/net/ipv4/ip_forward
- ;;
- esac
+~~~
+#!/bin/sh
+case "$1" in
+ start)
+ echo "1" > /proc/sys/net/ipv4/ip_forward
+ iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o $2 -j MASQUERADE
+ ;;
+ stop)
+ iptables -t nat -X
+ echo "0" > /proc/sys/net/ipv4/ip_forward
+ ;;
+esac
+~~~
+{: .language-sh}
Anpassbar ist hierbei das Interface, um z.B. daheim `eth0` und unterwegs wahlweise `wlan0` oder `usb0` verwenden zu können.
@@ -84,12 +93,12 @@ Anpassbar ist hierbei das Interface, um z.B. daheim `eth0` und unterwegs wahlwei
Nach einer Kernel Aktualisierung im ArchLinux Gast-System, kam es beim Neustart plötzlich zu dieser etwas erschreckenden Meldung:
KVM: entry failed, hardware error 0x80000021
-
+
If you're running a guest on an Intel machine without unrestricted mode
support, the failure can be most likely due to the guest entering an invalid
state for Intel VT. For example, the guest maybe running in big real mode
which is not supported on less recent Intel processors.
-
+
EAX=00000000 EBX=0020fa5c ECX=00000000 EDX=fffff000
ESI=f6d29014 EDI=00000001 EBP=f6461fa0 ESP=f6461f60
EIP=c0128443 EFL=00010246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
@@ -111,7 +120,10 @@ Nach einer Kernel Aktualisierung im ArchLinux Gast-System, kam es beim Neustart
Dies sah für mich im ersten Moment wie ein klarer Hardware-Fehler aus, alle Informationen die sich über meine bevorzugte Suchmaschine finden ließen, waren jedoch für andere Situationen und ältere Kernel Versionen als `3.6.6-1`. Nach Tests mit verschiedenen Parametern für die zuständigen Kernel-Module, funktionierte es schließlich nach Laden des Moduls mit folgendem Befehl wieder einwandfrei:
- modprobe kvm_intel emulate_invalid_guest_state=0
+~~~
+modprobe kvm_intel emulate_invalid_guest_state=0
+~~~
+{: .language-sh}
Um den `emulate_invalid_guest_state` Parameter dauerhaft zu setzen reicht ein Eintrag in `/etc/modprobe.d`.
diff --git a/articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md b/articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md
index 1cb8480..ae04631 100644
--- a/articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md
+++ b/articles/2013-04-27_declaring_functions_local_to_a_translation_unit_in_cpp.md
@@ -2,21 +2,27 @@
In a current project of mine I defined the following function marked with the inline hint without declaring it in a header file:
- inline bool checkStorageSection(const void* keyBuffer) {
- return (StorageSection::Edge == readNumber<uint8_t>(
- reinterpret_cast<const uint8_t*>(keyBuffer)+0
- ));
- }
+~~~
+inline bool checkStorageSection(const void* keyBuffer) {
+ return (StorageSection::Edge == readNumber<uint8_t>(
+ reinterpret_cast<const uint8_t*>(keyBuffer)+0
+ ));
+}
+~~~
+{: .language-cpp}
This function was not defined in one but in multiple translation units - each instance with the same signature but a slightly different comparison contained in the function body. I expected these functions to be local to their respective translation unit and in the best case to be inlined into their calling member methods.
While debugging another issue that seemed to be unrelated to these functions I noticed a strange behaviour: The calls in the member methods that should have linked to their respective local function definition all linked to the same definition in a different translation unit (the one displayed above). A quick check in GDB using the _x_-command to display the function addresses confirmed this suspicion:
- // Function address in translation unit A
- 0x804e718 <GraphDB::checkStorageSection(void const*)>: 0x83e58955
+~~~
+// Function address in translation unit A
+0x804e718 <GraphDB::checkStorageSection(void const*)>: 0x83e58955
- // Function address in translation unit B
- 0x804e718 <GraphDB::checkStorageSection(void const*)>: 0x83e58955
+// Function address in translation unit B
+0x804e718 <GraphDB::checkStorageSection(void const*)>: 0x83e58955
+~~~
+{: .language-gdb}
The address _0x804e718_ was the address of the function definition in translation unit "A" in both cases. At first I suspected that the cause was probably that both definitions were located in the same namespace, but excluding them from the enclosing namespace declaration did not fix the problem.
diff --git a/articles/2013-10-06_notizen_zu_cpp_und_unicode.md b/articles/2013-10-06_notizen_zu_cpp_und_unicode.md
index 6685687..fbc6d63 100644
--- a/articles/2013-10-06_notizen_zu_cpp_und_unicode.md
+++ b/articles/2013-10-06_notizen_zu_cpp_und_unicode.md
@@ -11,7 +11