Older blog entries for dan (starting at number 177)

Meet the new laptop ...

… same as the old laptop. Seriously. The only time you will see the word ‘fast’ in the same sentence as Sandisk U100 is in articles recycled from the press release they sent out at launch. And maybe now here, in the sentence “I threw away my Sandisk U100 and replaced it with something fast”.

I mean, it has to be said, there may have been something wrong with my particular drive -

  $ dd if=/dev/zero bs=1M count=1000 of=/home/dan/zeros.bin 
  1048576000 bytes (1.0 GB) copied, 230.009 s, 4.6 MB/s 

though I’m not the only one so … maybe not. ANYWAY. Point being, I replaced it with a Plextor M5M and it’s fixed all the odd stalls and hangs and stutters that I used to experience on this machine. Which is lovely, because reformatting it with ext4 a few months ago so completely didn’t.

A summary of the upgrade process

  1. remove 11 or so screws from the bottom of the case. Use a decent screwdriver, because if your machine is like mine, the screws are (1) made of cheese; (2) held in with threadlock
  2. remove the bottom of the case
  3. look for the bit that looks like an msata ssd. Pictures of msata ssds are available on the internet
  4. remove the foam pad stuck to it
  5. unplug and remove it
  6. plug the new one in
  7. reassembly is the reverse of disassembly

In summary, not hard. And I can confirm that my puppet manifest worked pretty much perfectly for reinstalling it. With the exception of a couple of dependencies I forgot to declare, but nothing that running puppet twice didn’t fix.

Syndicated 2013-10-21 18:26:19 from diary at Telent Netowrks

Clojure on company time / my first cljs

From: Daniel Barlow <dan@telent.net>
To: london-clojurians <london-clojurians@googlegroups.com>

A few weeks ago I foolishly volunteered to give a "this is what I remember
about functional programming" lunchtime talk for our company-internal
"Level Up" informal training sessions: the material being a combination of
what I learned at university many years ago and since have largely
forgotten[*], with the slightly more practical stuff I've since picked up
working with CL and Clojure.

So the presentation was yesterday, and seemed to be well received inasmuch
as at least nobody walked out: I spent 25 minutes blethering with some
slides, and then we did 4clojure problems for the rest of the hour.

*  I wrote some presentation software for the occasion:
https://github.com/telent/schuko which is also my first use of cljs outside
of a dojo setting.  Shows up that I really need to investigate some more
functional patterns for DOM/event-driven CLJS systems, because what I've
done there really doesn't feel Lispy.  Feedback welcome

* The markdown source for the slides
Instructions are in the README for how to convert this into HTML

I make no particular claim to correctness, completeness, or purity of
thought, and the bits about normal-order evaluation probably don't make a
lot of sense because they're written in Clojure syntax yet don't work in
Clojure because it (usually, by default) has strict evaluation - but I cast
this out to the wider world (that's you guys) in case you find it useful
anyway in your own evangelising


[*] Bless you, Bird & Wadler

Syndicated 2013-10-18 09:18:34 from diary at Telent Netowrks

iwl if you will

I don’t pretend to understand much about wifi, but – historically, at least – I observe that the phrase “wireless net working” is often, like “military intelligence” or “road works ahead”, most charitably described as oxymoronic.

The ingredients:

  • a linux box with an “Intel Corporation Centrino Advanced-N 6230” network controller
  • the iwlwifi module
  • a dual-frequency (2.4GHz and 5GHz) smallish “Enterprise” network based on Ciso Meraki

The symptoms: sometimes it doesn’t work. Sometimes it works for a couple of minutes and then stops.

The hypothesis: iwlwifi or the hardware it’s talking to doesn’t like talking on 5GHz channels

The fix (first attempt):

:; cat /etc/modprobe.d/iwlwifi.conf 
options iwlwifi 5ghz_disable=1

The problem with this fix: it makes no difference. It turns out 5ghz_disable has no effect any longer

The fix (second attempt): add the line

to the relevant network clause in /etc/wpa_supplicant.conf. And be grateful you’re not using dbus

The result: it seems to be working so far.

In other news, Schuko is hacky-but-probably-functional Showoff-style Markdown→HTML presentation software, in Clojure(script). It generates a static HTML file which you can host anywhere, and uses client-side Javascript and CSS for navigation and page flipping transitions.

Syndicated 2013-10-01 08:40:40 from diary at Telent Netowrks

Fully loaded leiningen

Taking the time to figure out how to use ones tools is more often a good thing to do than it is a thing I actually do. In this case, the thing I have now figured out is how to get all of a multi-file Clojure project loaded into Clojure without visiting each file and doing C-c C-l on it

user> (require 'winnow.core)

That’s right. require on a namespace will actually load the file that defines it – and the files defining the namespaces it depends on. ns or in-ns just create it in an empty state.

Syndicated 2013-06-29 22:04:59 from diary at Telent Netowrks

NetworkManager No More

Finally fed up with it randomly stalling and hanging for tens of seconds at a time, I decided yesterday to reinstall my laptop using ext4 instead of btrfs[*]. This time around I’ve done it all with Puppet, so I can tell you about my other recent change – connecting to protected WPA wireless networks without the “assistance” of NetworkManager.

It turns out to be amazingly simple if you’re reasonably acquainted with editing text files: you need a stanza in /etc/wpa_supplicant.conf for each network you want to connect to (and optionally, each network you want to tell it about that it should not connect to)

        ssid="My SSID"
        #psk="not a passphrase"
        id_str "default"
        ssid="My other SSID"
        #psk="not a passphrase"
        id_str "default"
        ssid="Some annoying captive portal"
        id_str "ignore"

and then you need to put stuff in /etc/network/interfaces to tell it to use wpa-roam

iface wlan0 inet manual
  wpa-driver wext
  wpa-roam /etc/wpa_supplicant.conf

and then some more stuff to correspond to each id_str you’ve used in wpa_supplicant.conf

iface default inet dhcp
iface ignore inet manual

My setup is not exactly what you see in this commit because I’m not quite stupid enough to put real keys into Github – but it’s otherwise pretty close. And for the rest of the repository, see here

[*] it remains to be seen if it makes any difference at all, but it was probably about due for a good decrufting anyway

Syndicated 2013-06-29 21:43:08 from diary at Telent Netowrks

Stranded Strava ride

This morning, due to some unlikely-ever-to-be diagnosed bug perhaps involving poor network connectivity in our office basement, the Android Strava app started denying all knowledge of my ride into work.

It turned out not to be quite as lost as I feared it would be, but the process of getting it uploaded was still kind of complicated. You will need root on your android, plus a real computer (or a Mac will do at a pinch, if that’s all you have available) with the android stuff installed, sqlite3 and gpsbabel.

  • copy the strava database onto the computer. Do this in two steps because adb pull doesn’t have the permissions to read the directory where the database lives
    $ adb shell
    shell@android:/ $ su
    shell@android:/ # cp /data/data/com.strava/databases/strava.db /sdcard/tmp-strava
    shell@android:/data/data/com.strava/databases # exit
    shell@android:/ $ exit
    $ adb pull  /sdcard/tmp-strava
    4566 KB/s (1277952 bytes in 0.273s)
  • use sqlite3 to get the data points out. This involved a bit of digging around
    sqlite> .tables
    CLUB_ACTIVITY           comments                related_activites
    activities              facebook_athletes       segment_leaderboards
    android_metadata        followers               segments
    athletes                followings              streams
    challenge_leaderboards  heartrates              waypoints
    challenge_participants  kudos                   zones
    challenges              notifications
    sqlite> .headers on
    sqlite> select max(timestamp) from waypoints;
    sqlite> select * from waypoints where timestamp=1370851561000;
    sqlite> .mode csv
    sqlite> .output /tmp/track.csv
    sqlite> select date(timestamp/1000.0,‘unixepoch’) as date,time(timestamp/1000.0,‘unixepoch’) as time,latiude as lat,longitude as lon,altitude as alt from waypoints where ride_id=‘c558df30-01ae-43ab-99c6-9b4649b8d596’;
    sqlite3> ^D
    Yes, you read that right, there really is a column called latiude in that table. Note that the ride_id of my missing ride is not necessarily the same as your missing ride: in this case I looked at the timestamp of the most recent waypoint logged and it corresponded to the time I finished my ride, but you might have to dig further.
  • now we have a CSV file, we need only turn it into a format that Strava will recognize, and upload it with the Strava upload button. According to the docs, this GPSBabel invocation should transform a list of waypoints in CSV form into a track in GPX form – according to empirical observation, it merely gives a list of waypoints in GPX format. But Strava seems to accept that as a valid upload anyway
    $ gpsbabel  -i unicsv -f /tmp/track.csv -o tcx -x transform,trk=wpt -t   -F /tmp/track.tcx
  • And here it is – though, you might argue, hardly worth the effort of recovering it. Somewhere in the process it seems to have lost track of my local time conventions too, but UTC is the one true timezone, so no big deal.

Syndicated 2013-06-10 12:50:29 from diary at Telent Netowrks

Way(land) back when

It’s been a little while since I made progress on psadan ($dayjob and daddy duty), but from looking at the commit log I see it’s even longer since I wrote about any of it. So:

I wrote a macro. with-sync does what he name suggests: it executes its body, then sends a sync message to the wl_display, then waits for the callback. This is the standard Wayland way to make sure that stuff has finished happening before doing more stuff. The actual macro implementation was pretty similar to writing macros in CL except that the quasiquote escape is ~ not , – and that this is a Lisp-1, so declaring a local variable called promise turns out to be a bad idea when you also want to call the function (promise)

We refactored the handle-message and listen functions to return the new state of the agent that runs them, instead of keeping the globals in an atom inside it. Bcause we only update globals through the agent, this saves us from having to keep them in an atom, which felt kind of ugly.

And finally: psadan now parses the wl_drm protocol as well as the regular one – that bit was easy, it’s just another file of XML to parse. This is however where I got bogged down quite comprehensively in how we actually use the stuff though: there are a lot of bits. I’m hoping that JOGL , possibly in conjunction with its Pbuffer support, is (a) relevant, (b) sufficient, but even then there’s titting around with ioctls to be done which is not readily doable in the JVM.

Syndicated 2013-04-02 20:49:06 from diary at Telent Netowrks

In mysterious way(land)s

Why are our bind messages to wl_registry erroring out?

15:19 &lt; daniels> yeah, wl_registry_bind is a special case - i think it's the 
                 one non-autogenerated marshaller we have
15:32 &lt; daniels> actually no, sorry, i'm lying through my teeth
15:32 &lt; daniels> it's no longer autogenerated
15:32 &lt; daniels> but the parser expands new_id to interface + version + id
15:33 &lt; daniels> it used to be hand-written, but is now autogenerated
15:33 &lt; daniels> http://cgit.freedesktop.org/wayland/wayland/tree/src/scanner.c#n614
16:28 &lt; jekstrand> dan_b: It is a somewhat-special case.  Basically, every time 
                   there's a new_id that does not have any type information 
                   specified, two aditional pieces of information (interface 
                   name and version) get added.
16:29 &lt; jekstrand> dan_b: That really should be documented, but it's not.  I 
                   had to grep through the scanner.c file to find it all.

Armed with this additional info the fix was fairly straightforward: I augmented the XML parsing/protocol generation to stick an additional pair of arguments into each message that contains a new_id and no interface.

Thanks to both daniels and jekstrand on irc for clearing it up.

Syndicated 2013-03-21 13:29:35 from diary at Telent Netowrks

The long way(land) round

The latest round of psadan hacking was motivated by two goals

  • that it would be good to actually remember the globals we’re receiving when we send get_registry to the magic registry object
  • that if we’re going to ask for a callback when all the globals are notified, we should wait for it before continuing.

We went down a couple or three dead ends on our way to this goal, but eventually we settled on creating an agent responsible for listening to the connection (I called it channel, in the absence of any better ideas) and dispatching (using a handle-message multimethod) to some code appropriate for each kind of message we’re receiving.


  • multimethods the clojure way are pretty versatile: you can dispatch on pretty much any property – or derived property – of the function argument, not just on type. In our case that’s the interface name and the message (event) name:
     (defmulti handle-message 
       (fn [conn m] 
         [(:name (:interface m)) (:message m)]))
     (defmethod handle-message [:wl_registry :global] [conn m]
       (let [[name interface version] (:args m)]
         (conn/register-global conn name interface version)))
     (defmethod handle-message [:wl_callback :done] [conn m]
       (let [object (conn/get-object  conn (:object-id m))
    	 promise (:promise object)]
         (when promise
           (deliver promise m))))
     (defmethod handle-message :default [conn m]
       (println [“unknown message” (:name (:interface m)) (:message m)]))
  • we handle the “tell me when you’re done” requirement with a promise. The get-globals code adds an unfulfilled promise to the callback object it creates, then once it has sent out its messages it derefs the promise , causing it to wait until something delivers the promise. That something is the handle-message implementation for wl_callback, for which, see above.
  • we were trying to map handle-message onto each of the messages parsed out of the buffer, but not doing anything with the result. Given that map is lazy, this meant our handle-message code was for the most part not being called. Surrounding the map form with a dorun fixed this.
  • you send work to an agent with (send fn ...) or (send-off fn ...) which invoke the fn with the current state of the agent, not with the agent itself. Which is fine but offers no facility for the agent to send work to itself – happily, the global/magic/special variable *agent*, which evaluates to the currently running agent if any is, works nicely for this purpose
    (defn listen [conn]
      (let [buf (conn/read-buffer conn)
            messages (buf/parse-messages buf conn :events)]
        (dorun (map #(handle-message conn %) messages)))
      (send-off agent listen)
    (send-off channel listen)
  • the ‘name’ field in a global is (confusingly) a number, and (more confusingly still) not an object id. Object number 3 in our client is a wl_callback object, whereas the global named 3 is .. well, let’s check …
    psadan.core> (def channel (chan/open-channel “/home/dan/private/wayland-0”))
    psadan.core> (chan/get-registry channel)
    ;; [debug output elided]
    {:object-id 3, :bytes 12, :interface {:index 2, :name :wl_callback, :requests (), :events ({:index 0, :name :done, :summary nil, :args ({:name “serial”, :type :uint, :interface nil})}), :enums ()}, :message :done, :args (-115)}
    psadan.core> (get @(:globals @channel) 3)
    {:interface :screenshooter, :version 1}

Next up? At some point we need to decide whether sending messages should be done by the channel or whether it’s OK to carry on doing that directly in whatever thread we happen to be in. But what would be much more fun is to see if we can actually render a window…

Syndicated 2013-03-18 21:07:47 from diary at Telent Netowrks

Finding a Way(land)

In the next round we shall be sending it the messages we have so lovingly composed from whole cloth and see if it reacts the same way as it did when the same bytes were sent from weston-info

And the answer is … yes, pretty much. We had to fix up our string parsing to make sense of the replies, but watch:

psadan.core> (def connection (conn/open-connection "/home/dan/private/wayland-0"))
psadan.core> (defn test-send-message []
  (let [registry
         {:id 2 :interface (proto/find-interface-by-name :wl_registry)})
         {:id 3 :interface (proto/find-interface-by-name :wl_callback)})
    (conn/write-buffer connection
                       (buf/pack-message connection (:display connection)
                                         :requests :get_registry [registry]))
    (conn/write-buffer connection
                       (buf/pack-message connection (:display connection)
                                         :requests :sync [done-cb]))

psadan.core> (test-send-message)
{:id 2, :interface {:index 1, :name :wl_registry, :requests ({:index 0, :name :bind, :summary "bind an object to the display", :args ({:name "name", :type :uint, :interface nil} {:name "id", :type :new_id, :interface nil})}), :events ({:index 0, :name :global, :summary "announce global object", :args ({:name "name", :type :uint, :interface nil} {:name "interface", :type :string, :interface nil} {:name "version", :type :uint, :interface nil})} {:index 1, :name :global_remove, :summary "announce removal of global object", :args ({:name "name", :type :uint, :interface nil})}), :enums ()}}
psadan.core> (def received (read-buffer connection))
psadan.core> (pprint (map (fn [x] [(:object-id x) (:message x) (:args x)]) (buf/parse-messages received connection :events)))
([2 :global (1 "wl_display" 1)]
 [2 :global (2 "wl_compositor" 2)]
 [2 :global (3 "screenshooter" 1)]
 [2 :global (4 "text_cursor_position" 1)]
 [2 :global (5 "text_model_factory" 1)]
 [2 :global (6 "wl_data_device_manager" 1)]
 [2 :global (7 "wl_shm" 1)]
 [2 :global (8 "wl_seat" 1)]
 [2 :global (9 "input_method" 1)]
 [2 :global (10 "wl_output" 1)]
 [2 :global (11 "wl_drm" 1)]
 [2 :global (12 "wl_shell" 1)]
 [2 :global (13 "desktop_shell" 1)]
 [2 :global (14 "screensaver" 1)]
 [2 :global (15 "input_panel" 1)]
 [2 :global (16 "workspace_manager" 1)]
 [3 :done (58)]
 [1 :delete_id (3)])

My interpretation of what’s happening here is that we’re sending to the server a ‘tell object 2 about all your global objects’ message, followed by a ‘tell object 3 done when you’re finished doing stuff’ message, and as you can see from the output, the reply is a bunch of ids for global objects sent to object 2, a done event sent to object 3, and then a delete_id event for object 3 sent to object 1. I’m actually not sure why that last one triggers, as I don’t think I asked it to. Perhaps it’s just tidying up for me.

I’m also handwaving – if not actually handdrowning – a litle bit, because really … are these :global messages sent to object 2 or from object 2? For the moment, I am using the two directions interchangeably, which is probably not a recipe for an easier future life, but in the meantime I can continue to tread water.

It’s instructive, or at least reassuring, to compare this stuff with what weston-info says:

interface: 'wl_display', version: 1, name: 1
interface: 'wl_compositor', version: 2, name: 2
interface: 'screenshooter', version: 1, name: 3
interface: 'text_cursor_position', version: 1, name: 4
interface: 'text_model_factory', version: 1, name: 5
interface: 'wl_data_device_manager', version: 1, name: 6
interface: 'wl_shm', version: 1, name: 7
	formats: XRGB8888 ARGB8888
interface: 'wl_seat', version: 1, name: 8
	capabilities: pointer keyboard
interface: 'input_method', version: 1, name: 9
interface: 'wl_output', version: 1, name: 10
	x: 0, y: 0,
	physical_width: 1024 mm, physical_height: 640 mm,
	make: 'xwayland', model: 'none',
	subpixel_orientation: unknown, output_tranform: normal,
		width: 1024 px, height: 640 px, refresh: 60 Hz,
		flags: current preferred
interface: 'wl_drm', version: 1, name: 11
interface: 'wl_shell', version: 1, name: 12
interface: 'desktop_shell', version: 1, name: 13
interface: 'screensaver', version: 1, name: 14
interface: 'input_panel', version: 1, name: 15
interface: 'workspace_manager', version: 1, name: 16

Top Wayland tip for today: it appears to be the case that you can make the C library clients log protocol exchanges to stderr by putting WAYLAND_DEBUG=client in the environment. When doing that it’s clear to see that weston-info is making a couple of additional requests that we’re not. We could add them, but I think the more pressing concern is to make it do something with the events we’re getting already – if it’s sending us details of global objects that we might need to know about, we should at a minimum be storing those details somewhere instead of throwing them away …

Syndicated 2013-03-14 13:32:01 from diary at Telent Netowrks

168 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!