Posts for Wednesday, July 6, 2011

PDFTK - Generate Issues

So, I've been working on this PDF project for awhile, and I think it might be beneficial for me to add some notes which were somewhat elusive on the net.

The FDF file which is generated by PDFTK generate is encoded in UTF-16 character set - and is very hard to work with.   I found this script which solves the problem, and allows the FDF file to still function.



I doubt it will work if the field names contain anything other than ASCII.

$ cat Project2.fdf | sed -e's/\x00//g' | sed -e's/\xFE\xFF//g' | less

(change "less" to "> "filename.txt", and it'll output the new fdf file nicely)

That's about it.

Posts for Monday, July 4, 2011

Free Software and law related links 27.VI.2011 - 3.VII.2011

A new week and we're back on track.

Yet again, I would like to thank Natalia for the great help with gathering of these articles and links.

Amongst the things I would like to point out for you this week is an interesting find by the 451 Group that lately many companies are omitting "open source" as the term to describe their business (see Free Software Business section). Why this is so they might (try to) explain in the near future.

As there really seems not a week can pass without software patent disputes, I would like you to check out the newest happenings in the Oracle vs. Google case and who won the bid of Nortel's massive patent portfolio (both in Software Patents section). While you're at it, I would warmly suggest that you also read Bessen's Generation of Software Patents.

ACTA and it's successor TPPA were also present this week as you can see below in the Copyright and Other Legal Act Reforms section.

If you've ever wondered how the law in another country handles Free Software and related issues, look no further. The great experts who are doing the IFOSSLR journal, have written (and are continuing to write!) the IFOSSLB book — this should be a handy reference to anyone who has to do with legal aspects of Free Software (Free Software Licensing section).

Free Software Licensing

As you probably have already known, the same people who thought of the IFOSSLR have also published the IFOSSLB — an e-book that gives a clear yet thorough analysis of Free Software legal matters by different legal systems, written and maintained by local experts, and by inviting everyone to assist in improving or expanding the content.

Free Software Business

Interesting post about how in the past year many companies have stopped using the term "open source" to identify themselves with it.

Rumour has it a first serious Android-based OS is getting started in China.

Software Patents


Groklaw: SCO v. Novell: Oral Argument at the Appeals Court

Interesting balanced compilation of literature on software patents.

Groklaw reports more information on the Oracle vs. Google patent case re Java-like code in Android. In short, the number of patent claims has been narrowed down, as well as (a lower) cap on damages is being negotiated. Glyn Moody analyses these recent events with the help of the above-mentioned Bessen's paper.

The bid for Nortel's vast patent portfolio (including new wireless technology) has been won by a group consisting of Apple, EMC, Ericsson, Microsoft, RIM and Sony. Reuters offers a nice review of how the bidding went. A joint hearing of U.S. and Canadian courts will be held on 11th of July which will either approve or disapprove the winning bid.

In the messy patent battle between Apple and Samsung, Samsung decides to drop one of its countersuits


New Zealand OS Society: No Opposition to Software Patent Exclusion from NZ Software Companies

Open Standards


H-online: The rise and fall and rise of HTML

Government and Free Software Policies


Mark Mcguire: NZ Government adopts Creative Commons licences


OSOR: OSOR forge now hosts nearly 2500 projects for public administrations


OSOR: CH: Geneva abandoning its open source email and office strategy


OSOR: NL: Half of all public administrations have open source strategy

After quite some FUD lately, it's refreshing to hear again positive press about its endavour. I'm quite confident you already know this, but just in case it bares repeating, that Munich is not just switching to Free Software and Open Standards, but at the *same* time cleaning its basement of all unneeded cruft, legacy solutions, updating the infrastructure and unifying it. Now, *that*'s a lot to chew on, and from what I hear, they're doing just fine.


OSOR: PT: Consensus among political parties on open source and open standards in the Public Administration


OSOR: Swiss MP wants administrations to dispel misconceptions open source


EY, Switzerland: Publication 'Open source software in mission-critical applications' [German]:

Copyright and Other Legal Act Reforms


Creative Commons: The Open Society Foundations encourage grantees to use CC licenses


TechDirt: Did Mexico Pull Out Of ACTA For Real? For Now, Yes, But Maybe Not For Long


Knowledge Ecology International: Notes from the Seventh Round of TPPA Negotiations in Vietnam

Other interesting links

After Wolfram with its Alpha and now the Chinese Baidu search engine is partnering up with Microsoft's Bing.

In the latest edition of EDRi-gram, there's interesting things evolving in the Scandinavian region: on one hand the Netherlands have become the first EU country to launch net neutrality, on the other though it is reported that anonymous internet usage may not be possible anymore in Denmark. Amongst other news there's a new draft law for data retention in Romania and the EU-US PNR agreement has been found incompatible with human rights


Christian Engström, MEP: The net blocking slope starts to get slippery


Neelie Kroes, EC: I propose a “Compact for the Internet”

hook out → first week as FSFE Legal Coordinator :]

Posts for Saturday, July 2, 2011

Reading news the way I like it

I have been using Tiny Tiny RSS (or TT-RSS) (www-apps/tt-rss in Gentoo) as my news aggregator since the end of 2008. It is a web application (written in PHP) that provides a great news aggregator UI. Since it’s a web application, you can use it from anywhere with just a browser, and thus have all your feeds in the same state (read/starred/…), anywhere you are. Think of it as Google Reader, but without Google knowing exactly what news articles you’re interested in, since you can run TT-RSS on your own server / web host.
So, TT-RSS alone was great already, but the UI is more suitable for when you have a mouse and a big browser window, than for using it from your phone.

Recently I discovered the Android App TT-RSS Reader which solves exactly that problem. It connects to your TT-RSS instance via an API, and brings all your feeds, with all their states just as on the web interface, to your Android device. The interface is specifically designed for touch screens, so it’s much easier to navigate through your feeds and articles than via the web interface. Furthermore, it can cache articles and images, which you can trigger while on WiFi before leaving the house, and then read everything on the way in Offline mode, to save mobile traffic, which is expensive and/or slow for some. When you’re back on WiFi, you switch back to Online mode, and TT-RSS Reader synchronises your state to your TT-RSS instance. Absolutely awesome :)

A couple of quick screenshots from the web interface (TT-RSS):


… and the Android App (TT-RSS Reader):


Update (2011-07-03): Shortly after posting this, hwoarang offered to take TT-RSS from the Sunrise Overlay into Gentoo’s main repository (Portage), with me proxy-maintaining it. So now it’s even easier to get TT-RSS onto your Gentoo-powered server.

Posts for Monday, June 27, 2011

A vote for me is a vote for action

I’m running for the Gentoo council this year, and I wanted to post my “platform” here: who I am, why I’m running, how I see the council, and how I see Gentoo.

For anyone newer, I’d like to first introduce myself and my history with Gentoo. Over the past 8 years, I’ve spent time doing pretty much everything in Gentoo, from maintaining ebuilds to writing documentation and leading teams and projects. I’ve been a recruiter in devrel, served as desktop manager (back when we had top-level project managers, before GLEP 39), and later chaired the council. I also started the clustering team, led X11 maintenance for about 5 years (when I designed the modular X eclass and wrote all 400+ new modular packages as we transitioned from the old XFree86), spent a term as a foundation trustee, and acted as project manager for our ever-controversial GUI installer.

One of my primary roles at the moment is running our participation in the Google Summer of Code, one of our major sources of both income and new developers. Since I took over 3 years ago, we’ve more than doubled the size of our program (we have 15 students this year!) and greatly increased the proportion of students who eventually become Gentoo devs to roughly 67%.

At this point, I’m convinced I can make the biggest difference to Gentoo in two ways: focusing on specific projects like the git transition and improved eclass testing rather than ebuild maintenance (which we have tons of people doing), and leading Gentoo to greatness as a council member, where I’m in the best position to accomplish that goal.

On my last two terms as a council member, I was extremely active in council-related issues both on mailing lists and at meetings, rather than just showing up at meetings to vote and then disappearing into the sunset. I strongly believe that through preparation and accountability, we can have a more productive council, but this requires a true commitment on the part of every member.

Creating a great community

I see this as an area where the council can set direction for all of Gentoo, both through the positive examples of its members and by taking a stand against anything we won’t stand for in our community. The council should be providing guidance to devrel and userrel on what kinds of behaviors should be encouraged and what kinds shouldn’t be tolerated.

Additionally, we should begin collecting metrics on our community so we know where we’re going. Many other projects (and even distributions) do this already, to give them clues of when things are going wrong, what things are going right, etc.

Making progress now instead of waiting years for perfection

There’s a lot of ongoing projects and GLEPs that have been dragging on for years because people want a “perfect” solution. One personal example is the git transition, where I’ve already made this mistake in spending quite a bit of time trying to get a perfect repository layout working when we could have just done a simple conversion of the whole tree and put it in one repo (the current plan, with some changes).

GLEP 55 is another one. There are some times when any decision is better than no decision.

Removing bureaucracy in favor of more agile development & meritocracy

We all know that GLEP 39 needs some changes. I think that most devs just want to Get Stuff Done without fighting with policies, waiting around forever for votes, not getting majorities without any clear direction, and so forth. I believe that our devs vote in the council because they want those people in charge and trust the council members to do what they think is right, including deciding on changes to GLEP 39 to improve how we run things.

I favor a switch to a smaller group more along the lines of the Linux kernel, with a very small leadership core and more of a hierarchy than a huge committee.

Along the same lines, I favor a switch to a more meritocratic approach such as the lead appointments we’ve been discussing recently. Gentoo isn’t a country government that needs to provide for every sick and needy person in its geography; it’s a nonprofit with specific goals it needs to accomplish and should be run as such. In general, companies, including nonprofits, don’t have checks and balances or long, drawn-out votes. What they do have is a board of trustees at the top, which can replace the leadership when it deems necessary.

Another major problem is the lack of continuity in our leadership, mainly because the whole group is re-elected en masse every year. At a minimum, even if we can’t do the above changes, we should switch to a 2-year term and have half the council up for election each year so new councils can start out quickly.

Promoting innovation from individual developers instead of expecting it to all come from the top

As I mentioned above, one of my focuses now is working on interesting standalone projects. I hope that every developer does the same; in addition, or besides whatever you do every day (maintain ebuilds, write/translate docs, etc.), consider starting a new project that has a clear end in sight and that will help Gentoo get better. It doesn’t have to be anything big; and the great thing about projects with a finite length is that you actually finish them at some point.

Getting rid of policies that were created for a single incident, because they should only exist for patterns of repeated problems

A common problem in Gentoo is feeling like a one-time problem can’t be fixed without making a big policy about it, why it can’t be done, what will happen if it’s done again, etc. If you’ve been around Gentoo for a while and start reading through our developer docs, you’ll be able to connect a specific name and instance with pretty much every line that says something like “Don’t do stupid thing X” and “Don’t do ridiculous thing Y.”

I think part of this is rooted in a fear, for lack of a better word, to take personal responsibility for an action; instead, people want a rulebook to point at and say “That’s wrong” so the rulebook is the bad guy.

But rulebooks should only be for the common cases, the patterns, the problems that keep coming up over and over. One-time problems only deserve one-time solutions.


Tagged: communication, community, development, gentoo, gsoc, leadership

Posts for Sunday, June 26, 2011

Free Software & law related links 20.VI.2011 - 26.VI.2011

First of all I would like to apologise for yet another late Legal News Update. But things I could not ignore were stealing my time — amongst others were the FSFE GA, which I had to cover the logistics for, and a lot of work in relation to some major change.

For this edition I received immense help from Natalia Evdokimova, regarding gathering and initial evaluation of the articles. If all goes well (and it seems like it) we will cooperate on this in the future as well.

If I would have to select the three most important happenings of the past week, it would be: governments considering Creative Commons licenses (under Free Licensing), the overview of Nortel's portfolio sale, and last, but by no means least the AVM case (in Free Software Business).

Free (Software) Licencing

With more and more governments deciding to release (some of) its content under a CC license, the question arises: Is CC enough or should this content be in public domain? Personally, I would argue that such content and data should be in public domain. It follows simple logic that if it is in public interest and is paid by public funding it should be in the public domain.

Software Patents

A nice overview about the very sought after Nortel's patent portfolio sale. Google is being the "stalking horse" in this bid for probably the biggest patent portfolio in the mobile phone business. It's a very non-lawyer friendly article.

Glyn Moody uses the above as an example to underline why (software) patents should be abolished. Interesting to see Microsoft involved here.

Falkvinge: Ten Myths About Patents

Xiph.com has written a response to the US FTC's Request for Comments and Announcement of Workshop on Standard-Setting Issues. In it they explain nicely the threat that patents pose to standards.

BitTorrent sued for patent infringement.

The Register: Nokia takes hit in High Court priority-calls patent battle,

The Register: Wireless networking without paying The Man, man,

Groklaw: Oracle v. Google - Posturing Over Damages

Open Standards

Computerworld UK, Glyn Moody's blog: Interoperability and Open Standards: Help Make It Happen

Government and Free Software Policies

OSOR: HU: Government planning to use vendor-independent document format,

OSOR: DE: Updated vendor independent e-ID application based on open source

Netzpolitik: UNESCO-Kommission will Nutzung offener Lizenzen fördern

Computer weekly: UK Government cancels SME contracts and hands IT services deals to Capita

OSOR: Open process and vendor independence dearest to public administrations

Free Software Business

H-online: LexisNexis joins Linux Foundation, open sources HPCC platform,

100%open: Open Business Models

AVM — who makes Linux-based DSL routers — is suing Cybits — who makes child protection filters — that they are infringing on AVM's copyright because they are modfying the GPLv2-licensed software on their routers' firmware. The outcome of this case could have profound implications on Free Software and related freedoms. FSFE maintains a very useful summary of the whole procedure and Harald Welte's blog posts are also a great commentary to the case.

FreeGamer: Some thoughts on commercial FOSS game development

Copyright and Other Legal Act Reforms

Ars technica: Can Microsoft use the DMCA to kill competing Xbox 360 accessories?

TorrentFreak: Ireland Set To Force ISPs To Disconnect Pirates

KEI online: KEI Statement in opposition to a WIPO Treaty for Broadcasting Organizations

Other interesting links

Pam Chestek reviews some of Righthaven's copyright trolling business.

Google will digitise 250 K books (in public domain) from the British library.

Posts for Saturday, June 25, 2011

Qt Workshop for Columbia’s Application Development Initiative

Back in February I gave a workshop seminar on the basics of Qt — covering signals, slots, the metaobject system, QtGui, QtWebkit, and Qt Creator. We all built a fully functional web browser together, over the course of about an hour. The entirety was spoken just off the top of my head, so it might be slightly disorganized, but there was pretty high reception from it. I know that following the presentation, at least two people went on to use Qt for major projects. Here’s the presentation:

<object height="750" width="405"><param name="movie" value="http://www.youtube.com/v/xtssLlz5pUs?version=3&amp;hl=en_US&amp;rel=0&amp;hd=1"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed allowfullscreen="true" allowscriptaccess="always" height="750" src="http://www.youtube.com/v/xtssLlz5pUs?version=3&amp;hl=en_US&amp;rel=0&amp;hd=1" type="application/x-shockwave-flash" width="405"></embed></object>
Direct YouTube Link

Unfortunately, the projector in the room was broken, so we all had to huddle around my laptop, which actually had the effect of making the workshop much more intimate. If you’re interested, here’s the code we wrote together.

<iframe allowtransparency="true" frameborder="0" scrolling="no" src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.zx2c4.com%2F627&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=65&amp;font=lucida+grande" style="border:none; overflow:hidden; width:450px; height:65px"></iframe>

Keyword Arguments: Ruby, Clojure, Common Lisp

And suddenly I return to blogging, rising from the ashes like some kind of zombie phoenix. Turns out writing a book is a good absorber of time, like some sort of heavy-duty temporal paper towel. Now that I've gotten the terrible similes out of my system, let's talk about keyword arguments, one of my favorite features in any language that supports them.

Ruby, Clojure, and Common Lisp are all languages I enjoy to some degree, and they all have keyword arguments. Let's explore how keyword args differ in those languages.

Why keyword arguments?

Why are keyword arguments good?

  1. You can omit arguments.
  2. You can supply arguments in an arbitrary order.
  3. Arguments are labeled, so you know what argument means what.

Positional arguments require mentally lining up the 7th argument in your function call with the 7th argument in the function signature, and so on. Keyword arguments become more and more attractive the more arguments you have in your function signature.

Keyword arguments trade a bit of verbosity for added explicitness, clarity and reduced mental burden. (Kind of like Lisps do overall. Fancy that.)

Ruby

Ruby doesn't have special support for keyword arguments. But Ruby likes its hashes, so you can just pass one in as an argument to a function. As some syntax sugar, if you pass a "flat" list of :key => val pairs, Ruby slurps them all together and stuffs them into a hash for you.

def foo(arg)
  p arg
end

foo({:x => 123})                  # => {:x=>123}
foo(:x => 123)                    # => {:x=>123}

With even more added sugar, you can leave off the parens in Ruby function calls. So this is pretty common in Ruby:

foo :x => 123                     # => {:x=>123}

How nice and punctuation-less. But then things get ugly. What about this?

foo {:x => 123}

That won't even compile. Ruby thinks {:x => 123} is a code block, and a bare key/value pair isn't valid syntax as the first thing in a code block. You need the parens. A bit unfortunate, but it gets worse...

def bar(arg1,arg2)
  puts "#{arg1} #{arg2}"
end

bar :x => 123, :y => 456          # Runtime error
bar {:x => 123}, {:y => 456}      # Won't compile

In the first example, all of the key/value pairs are slurped into one hash and end up in arg1. There's nothing left for arg2, so you get a "wrong number of arguments" exception. The second example won't even compile, of course, because again Ruby thinks {:x => 123} must be a code block with invalid syntax.

It gets worse if you change the argument list for bar slightly...

def bar2(arg1 = {}, arg2 = {})
  puts "#{arg1} #{arg2}"
end

This way, you don't even have to supply any arguments. This is nice, if all of your argument are optional.

bar2    # => {} {}

Now suppose you want arg1 to be {:x => 123}, and arg2 to be {:y => 456}. You might naively try this:

bar2 :x => 123, :y => 456         # => {:x=>123, :y=>456} {}

Oops, it all got dumped into arg1, and now instead of a missing argument error, arg2 silently ends up with a default, empty hash. You have to explicitly pass in an empty value for arg1 so that everything is slurped into arg2.

bar2 {}, :x => 123, :y => 456     # => WRONG!  Ruby thinks {} is a code block again.

bar2({}, :x => 123, :y => 456)    # => {} {:x=>123, :y=>456}

So much for syntax sugar. You might think you'd be unlikely to find this kind of thing in the wild, but in Ruby on Rails for example, there are quite a few functions whose argument lists look exactly like this. One signature for link_to is:

link_to(body, url_options = {}, html_options = {})

So...

link_to "foo", :controller => :x                          # OK
link_to "foo", :controller => :x, :class => "css_class"   # WRONG! 
link_to "foo", {:controller => :x}, :class => "css_class" # OK

What about support for default arguments? We might want to say that if you didn't pass in an :x argument, we want it to have some default value. You might think this would work:

def baz(x = {:x => 123})
   p x
end

But you would be sadly mistaken.

baz                               # => {:x=>123}
baz :y => 456                     # => {:y=>456} ... oops

Ruby doesn't merge your keyword arguments into the map in the parameter list. It uses that map if you don't supply any arguments, otherwise your map replaces the default entirely. So to get default arguments, you need something like

def baz2(args = {})
  args = {:x => 123}.merge(args)
  p args
end

baz2                              # => {:x=>123}
baz2 :x => 555                    # => {:x=>555}
baz2 :y => 456                    # => {:x=>123, :y=>456}

Kind of messy, but that's OK.

One last subtle ambiguity in Ruby is determining whether someone passed a nil argument for a keyword explicitly, or omitted a keyword entirely. It might make a difference in some circumstances.

def quux(args={})
  p args.include? :x
  args = {:x => nil}.merge(args)
  p args
end

quux                              # true, {:x=>nil}
quux :x => nil                    # false, {:x=>nil}

Pretty messy, but such is life.

Clojure

Part of the fun of Lisps is lack of ambiguity. Everything is spelled out in all its parenthesized glory. In Clojure, when you call a function like (foo :x 123), Clojure requires you to specify what you want to happen with those arguments.

It used to be that Clojure didn't have much support for keyword args at all. Clojure did have support for allowing variable numbers of arguments to functions though. So in the beginning, people used to slurp all of their arguments together into a list, and then turn it into a map inside the function.

user> (defn foo [& args]
        (let [args (apply hash-map args)]
          (prn args)))
#'user/foo
user> (foo)
{}
user> (foo :x 123)
{:x 123}
user> (foo :x 123 :y 456)
{:y 456, :x 123}

That worked. It still works today. But nowadays there's a better way. Why not slurp your arguments directly into a hash-map?

user> (defn foo [& {:as args}]
        (prn args))
#'user/foo
user> (foo)
nil
user> (foo :x 123)
{:x 123}
user> (foo :x 123 :y 456)
{:y 456, :x 123}

This is an example of destructuring. In this case, all of our arguments are slurped into a list (thanks to &), then this list is matched against our destructuring pattern, in this case {:as args}. :as says to take everything in the list, turn it into a map and give the resulting map the name args.

This isn't a special feature of defn. Destructuring works anywhere you're setting up bindings, for example in let, for, doseq etc. Like so:

user> (let [{:as args} (list :x 123 :y 456)] args)
{:y 456, :x 123}

It just so happens that & creates the list for you, out of the arguments you pass.

Destructuring does lots more than that though. We can immediately pull out the values for keywords we care about, so they'll be bound to names in our function body.

user> (defn foo [& {:keys [x y z]}]
        (prn x y z))
#'user/foo

user> (foo :z 123 :x 456)
456 nil 123

It's certainly a bit more verbose than Ruby in the function signature, but it lacks ambiguity and it saves you some repetition in the function body.

Clojure's approach also has the benefit of specifying directly in the function signature which keywords you're expecting. In a smart editor, like Emacs, you get an indicator of what kinds of keywords you should be passing in. See at the bottom?

Emacs function signature display

This is also available at the Clojure REPL via the doc function.

user> (doc foo)
-------------------------
user/foo
([& {:keys [a b c]}])
  nil
nil

There's no better documentation than live, built-in documentation. There's nothing more distracting when programming than context shifts, and having to dig into a web browser to check a function signature is a huge mental page fault.

What about default values? Sure. You can use :or to specify defaults for some or all of your keywords. This works much more like I'd expect, compared to Ruby.

user> (defn foo [& {:keys [x y z] :or {x 1 y 2 z 3}}]
        (prn x y z))
#'user/foo

user> (foo :y 555)
1 555 3

What about determining whether the user passed nil for a keyword or whether they omitted the keyword entirely? For that, you have to resort to testing the argument map for the existence of the key, which isn't fun, but at least it's possible.

user> (defn foo [& {:keys [x y z] 
                    :or {x 1 y 2 z 3}
                    :as args}]
        (prn x y z)
        (prn args)
        (doseq [k [:x :y :z]]
          (println "Contains" k "=>" (contains? args k))))
#'user/foo

user> (foo :x 1 :y 2)
1 2 3
{:x 1, :y 2}
Contains :x => true
Contains :y => true
Contains :z => false

Why do I keep mentioning this? See Common Lisp below.

In any case, our parameter list is becoming huge and unweildy. The first time I saw sample Clojure code like this, I almost did a spit-take. But after a bit of getting used to, I'm finding that this syntax is pretty comfortable.

The simplest case may not be as concise as Ruby, but aside from lack of ambiguity, the benefit of Clojure's approach is being able to safely do powerful (and borderline insane) things, like nested destructuring. And this works everywhere you're setting up a binding.

(defn ow-my-eyes [a & {[b {:keys [x y]}
                        & {[g h] :r
                           :keys [p q]
                           :or {q 123}}]
                       :x}]
  (prn a b g h p q x y))



user> (ow-my-eyes 444 :x [1 {:x 555 :y 666} :p 3 :r [888 999]])
444 1 888 999 3 123 555 666

If you wrote code like that in real life, you'd likely be defenestrated, but at least you know you can do it. And destructuring in Clojure could likely be extended even further in the future, if someone came up with a use case for something that isn't supported.

Official documentation for all of this is here.

Common Lisp

When it comes to keyword arguments, Common Lisp supports mostly everything that Clojure does, and some things it doesn't. CL was likely a big inspiration for Clojure's destructuring. I highly recommend reading Practical Common Lisp to learn more about CL keyword arguments and list destructuring. (Read the rest of the book while you're at it.)

Keyword arguments in CL look like this:

> (defun foo (&key x (y 123) (z 456 z-supplied-p))
    (pprint (list x y z z-supplied-p)))
FOO

> (foo)
(NIL 123 456 NIL)

> (foo :z nil)             ; note, z-supplied-p tells us whether z was omitted or not
(NIL 123 NIL T)

> (foo :z 555 :x 666 :y 777)
(666 777 555 T)

> (foo :x 123)
(123 123 456 NIL)

> (foo :x 555)
(555 123 456 NIL)

Yeah, there's direct support for distinguishing supplied keys with nil values, and un-supplied keys. That's pretty nice.

Common Lisp also supports insane things like having keyword arguments' default values be a function of other arguments in the parameter list.

> (defun bar (&key (x 123) (y (+ x 1000)))
    (pprint (list x y)))
BAR

> (bar)
(123 1123)

> (bar :x 5)
(5 1005)

> (bar :x 5 :y 6)
(5 6)

Clojure destructuring can't do this by default, so you'd have to resort to a let in the function body.

(defn bar [& {:keys [x y] :or {x 123}}]
  (let [y (or y (+ x 1000))]
    (prn x y)

There's nothing stopping Clojure's destructuring from being patched to support this, of course. But this isn't a feature I've ever found myself wanting particularly badly.

As for how to destructure CL keyword arguments into a vector or hash-map, CL doesn't directly support doing it in function parameter lists like Clojure does. (Though there's nothing stopping someone from throwing together a reader macro to let CL do this, of course.) This isn't really surprising, because CL loves its cons cells, while Clojure embraces maps (and vectors and sets etc.), offering them default reader syntax and lots of other built-in support.

So there you have it. Keyword arguments. Use them. Love them.

Lessons:

  1. Sugar can be bad for your health.
  2. Ambiguous, bad. Explicit, good.

Posts for Wednesday, June 22, 2011

Paludis 0.64.1 Released

Paludis 0.64.1 has been released:

  • ‘cave resolve –keep if-same-metadata’ now thinks “cat/pkg[a][b]” and “cat/pkg[b][a]” are “the same”.
  • Support for Portage-format configurations has been improved slightly.

Filed under: paludis releases Tagged: paludis

Posts for Tuesday, June 21, 2011

web development using git

I think that the title says everything. This post describes how I’m using git for version controlling my web apps.

The scheme I use is very simple. There is the live web root, that serves the app to the public, and the local copy where the actual development takes place.

Those of you familiar with git may find the above setup a little bit strange. Git is a  decentralized version control system and it seems that I’m trying to centralize it. But hey, this what I wanted to do and this is why I’m writing this post.

 

Initial Setup

The key here is that we need a bare repository on our server in order to push the updates. A bare repository does not contain a working copy of our files, but the git index, objects reflecting updates to that index. That is why we can’t actually work there, and it simply serves as a collection point for all the developers working on the project that it contains.

So lets go where we have our web app on the server (in my case this usually is a django project). We initialize a git repository:

cd /var/www/myproject
git init
git add .
git commit -am "Initial commit"

So we made a git repository out of my project webroot. I’m guessing you already know how to use .gitignore (for instance I want to exclude django’s settings.py, because I want different settings on my local copy) and git config, to set you name, etc.

No let’s clone it to a bare repository:

cd ..
git clone --bare myproject myproject.git

It’s a good convention to create the bare repository with .git extension, if you want to serve your code through gitweb.

 

Local Repo

Now let’s setup our local repository:

cd /home/me/dev/
git clone ssh://mydomain.net/var/www/myproject.git

Now we have a complete local copy of the server version of our website.

 

Live Web Root

Remember the key repository on the server is the myproject.git, not the myproject. So we need to swap them out.

mv myproject tmpbackup
git clone myproject.git

This puts a clone of our myproject.git directory in the current directory, which will be named myproject.

So let’s sum up. As I said in the beggining all the development process is taking place on my local repo. If this project has more than one collaboratos, each one must clone locally the myproject.git repository as we did earlier.

The live webroot is permantly checked out on the master branch. Locally I use as many branches as my development proccess requires and I’m merging to the master all the code changes I believe are stable to go live.

 

Auto-Update

So what happens when I push? First of all I don’t just push the master branch, because I want to have a copy of my code on the server. Remember: when I push it’s the myproject.git that gets synced. I wanted my live webroot to sync automatically when I push a change. So we create a post-update script that will do the trick:

cd /var/www/myproject.git/hooks
touch post-update
chmod +x post-update

And edit post-update with:

#!/bin/bash
#
WEB_DIR="/var/www/myproject"
export GIT_DIR="$WEB_DIR/.git"
pushd $WEB_DIR > /dev/null
git pull
popd > /dev/null

 

Every Day Developing

Now I keep developing on my local repository, and pushing the changes.

git commit -a -m "Another update"; git push

If a change is merged on the master branch, the live web root would be automatically updated (thanx to the post-update script above).

flattr this!

New Ohai Plugin for Linux VServer

Today I posted my first Ohai plugin to Github and put a link on the Opscode Community Plugins wiki page.  I know not a whole lot of people use VServer, but hopefully some will find it useful. :)

#opschef

 

Posts for Monday, June 20, 2011

new nixos.org mediawiki theme

the wiki.nixos.org mediawiki theme

for some time i am hosting muse-sequencer.org with a mediawiki but i never was able to design a nice custom layout like it is done on spring RTS [1] for example. however, i often use the ‘clean’ theme which looks much better than the standard mediawiki theme.

anyway, there are times when you need a ‘custom theme’, especially when you have to integrate a custom menu bar (as shown in the top part of the nixos-wiki-theme screenshot below). the advantage is that the wiki page feels ‘integrated’ into the page and especially as the top level menubar helps to navigate the site it can be used to get out of the wiki again.

therefore, not integrating the main navigation menu into the wiki stylesheet causes a huge hit on usability as users have to alter the URL filed in order to get back to the other pages. and the wiki not looking like the rest of the pages also degrades the look and feel.

for quite some time i did not want to learn that much CSS and php/html but lately the integration of wiki.nixos.org into the nixos.org domain made me think otherwise and so i started to hack a new stylesheet [2] based on the ‘clean’ skin [3] i already debugged for my page ‘lastlog.de’.

i needed about 9hours to make the design final and i would like to thank zmlka@irc.freenode.net#nixos for his help and fine tuningi would also like to thank viric@irc.freenode.net#nixos for his general attributions towards a nice mediawiki.nix modification which makes it easy to handle several third party mediawiki stylesheets. i might upload these modifications upstream (nixpkgs) soon – if i find the time.

i hope nixos.org folks will use the new style soon!

external and internal links

one nice thing i discovered while creating the nixos mediawiki theme was that it is very easy to add external links. i always thought this to be very complicated.

the nixos-mediawiki-theme does have two menues: a top level menu (header) and a bottom menu (footer). i used require_once(..), which is a php command, to include ‘header.php’ and ‘footer.php’.

this way the style can be extended without having to touch the the style. this is especially nice as nixos wants a stateless packages and one can set the ‘links’ from the /etc/nixos/configuration.nix context.

another nice thing is that it is very easy to add ‘internal’ links, that means: the menu generated from ‘header.php’ can be used to add links which will also end in the mediawiki:

this will create an external link:

  • <li><a href=”http://nixos.org/nixos/”>NixOS</a></li>

this will create an internal link

  • <li><a href=”demo”>Demo</a></li>

conclusion

although it was very time consuming for me to write this stylesheet (except for my ‘ajax patterns’ [4] project i’ve never done that before) i learned quite much about stylesheets, thus i encourage you to do the same for your page. soon i will write a little guide how to do that in more detail.

it is also worth mentioning that CSS can be used to make the content 100% independent of the position in the page but contrary to all my expectations this might not be a default for most pages.

i would also like to recommend firefox+firebug as this helps to analyze css/html errors and also helps to make experimental modifications on the fly!

links

[1] https://springrts.com

[2] https://github.com/qknight/nixos

[3] https://github.com/qknight/clean

[4] http://lastlog.de/wiki/index.php/Ajax_patterns


Posts for Sunday, June 19, 2011

avatar

How can I be a KDE power user?

As far as I can tell, KDE is essentially a desktop environment shell layered on top of many very useful libraries. The difficulty is, how does one test each individual layer?

Here’s a recent example. I started by using Amarok as my music player, a default choice it seems for many KDE users. I put an audio CD in the drive, and it appeared in Amarok. When I tried to play or rip the CD, though, the interface just wouldn’t respond.

Fast-forward many, many hours later, and I’ve traced the issue through logs spit out by Amarok, Phonon, Kscd, gstreamer, ffmpeg, and the kernel itself, and I narrow the issue down to KDE I/O layer. cdparanoia reads disks just fine. No KDE-based app can. There’s a lot of seek errors in the kernel logs, which appear only when a KDE-based app is up and running with a CD in the drive.

So what’s the big deal, you might ask? I figured it out. What’s the problem?

Perhaps I’m spoiled, but in GNOME I debugged issues quite differently. If I had an issue, I’d go through each API layer, and use each one’s executables. Note the difference between KDE and GNOME: GNOME makes every layer, every setting easy to access, if you look for it. KDE gives you everything at once, and hides everything else in a wall of libraries. There’s no intermediate executables I can use to debug each layer, by manually running through steps myself. There’s no ability to get a work-around, or to helpfully narrow down the area where the bug exists for Google searching.

How do I make my debugging with KDE more productive? What steps do I take? How have you debugged KDE-based applications? I know about the KDE wiki page, but is there anything else?


Paludis 0.64.0 Released

Paludis 0.64.0 has been released:

  • Support for Gentoo old-style virtuals has been removed.
  • The ‘accerso’, ‘instruo’ and ‘appareo’ clients have been removed in favour of ‘cave’.
  • ‘cave resolve’ now has ‘if-same-metadata’ options for ‘–keep’ and ‘–keep-targets’, to take care of all those times when Gentoo developers ignore policy and change dependencies without a revbump.
  • Dependent IDs now have their dependency type (e.g. ‘build’, ‘runtime’) shown in the reasons output for ‘cave resolve’ and ‘cave uninstall’.

Filed under: paludis releases Tagged: paludis

Wanted: Nokia E52-2

The Nokia E52 is the most awesome phone ever made. It has a normal T9 keypad, GPS, 3G, Wifi, and runs Symbian. These are the features I need. Sure Android and others are more modern operating systems, but there is no smartphone OS that has phones with T9 hardware keypads of this form factor, except for the E52. There is one problem: it’s not made anymore

There are two models of the E52 — the E52-1, which has European 3G frequencies, and the E52-2, which has North American 3G frequencies. I’m looking for the E52-2.

If anyone knows there whereabouts of an E52-2, please inform me. I will bid high.

<iframe allowtransparency="true" frameborder="0" scrolling="no" src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.zx2c4.com%2F620&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=65&amp;font=lucida+grande" style="border:none; overflow:hidden; width:450px; height:65px"></iframe>

Posts for Friday, June 17, 2011

Paludis 0.62.2 Released

Paludis 0.62.2 has been released:

  • ‘cave fix-linkage’ no longer gets upset at .la files that are missing a final newline character.

Filed under: paludis releases Tagged: paludis

Posts for Thursday, June 16, 2011

avatar

Poor mans pickle implementations benchmark

Gensim is a very cool python2, numpy-based vector space modelling (information retrieval) framework. It does the job in a straightforward way, and it has been a great project for me to learn python with because it uses some nice tricks in real life scenarios (like Generators) and is AFAICT elegantly coded. Sometimes I find it hard to believe how much functionality can be crammed in so few lines of (readable) code.

But anyway we're having some issues in it with cPickle (it breaks when saving large matrices, it breaks with some objects). For now I worked around it by using jsonpickle but I wonder how viable this alternative really is.

To give at least a crude idea of performance characteristics of different pickle methods, I wrote a very simple benchmark program - picklebench - to compare pickle, cPickle and jsonpickle. The script fills a dictionary which gets bigger and bigger, and for certain sizes of dictionary it is saved to, and loaded from disk again. We measure some metrics of each step. We continue until memory is exhausted.



::Read more

Paludis 0.62.1 Released

Paludis 0.62.1 has been released:

  • ‘cave resolve –hide’ now affects resolvent selection too.
  • Various minor bug fixes.

Filed under: paludis for users Tagged: paludis

Posts for Wednesday, June 15, 2011

ubuntu cachefs experiments

motivation

the main purpose is a ‘high availability’ file storage with with two servers: main and failover. the main server has two raid systems:

  • one with fast disks and moderate disk sizes and
  • another raid with slow but very big disks

the idea is to find a way to use the fast raid for file-caching similar to ZFS or BTRFS’.

the goal of this experimental setup is to experiment with fscache [1]. so far it seems that fscache is either bound to NFS, AFS or ISOFS (or a similar network fs technology).

experiment using:

  • virtualbox 3.x on gentoo linux
  • ubuntu 10.10 (guest)
  • currently only main is in the experimental setup and DRBD is not used yet
  • not shown in the diagram is the PV/VG/LV stuff (LVM)

there are two interesting documentations:

  • [3] how to use fscache
  • [4] how fscache is implemented (and how to debug it)

setup using nfs

this is a small setup to test if the mount and fscache are working on the target platform. in this case it was working great with ubuntu 10.10 desktop. setup steps:

  1. using [2] we install the needed tools on ubuntu linux:
    apt-get install nfs-kernel-server nfs-common
  2. cat /etc/exports
    /media/share 127.0.0.1(async,no_subtree_check,rw,insecure,all_squash)
  3. nfs-kernel-server neustarten:
    /etc/init.d/nfs-kernel-server restart
  4. change the permissions on /media/share
    chmod 0777 /media/share
  5. only to test if the nfs export works we do:
    mount -t nfs 127.0.0.1:/media/share /mnt/mounted-Share
  6. after a successful test we unmount it:
    umount /mnt/mounted-Share
  7. create the cacheDir disk:
    dd if=/dev/zero bs=1M count=512 of=cacheLoopDevice.dd
    mkfs.ext4 /mnt/cacheLoopDevice.dd
    according to [3]:
    tune2fs -o user_xattr /mnt/cacheLoopDevice.dd
    mount -o loop,user_xattr /mnt/cacheLoopDevice.dd /mnt/cacheDir
  8. enable the cachefilesd daemon:
    vi /etc/default/cachefilesd # remove the # before RUN=yes
    change the dir=… in /etc/cachefilesd.conf:
    dir /mnt/cacheDir
    /etc/init.d/cachefilesd restart
  9. finally let’s mount it again but this time using ‘fscache’:
    mount 127.0.0.1:/media/share /mnt/cached-Share/ -o fsc
  10. let’s do a functionality tests:
    touch /mnt/cached-Share/a
    ls -la /media/share

setup using nfs – no networking filesystem

as shown in the two following examples, it does not work with ext2 or ext4. it seems as if fscache forces the use of NFS/AFS/ISOFS.

ext2

mkfs.ext2 /dev/sdb1
mount /dev/sdb1 /mnt/cached-Share/
umount /mnt/cached-Share/
mount /dev/sdb1 /mnt/cached-Share/ -o fsc

the error message (response to the shell command):

mount: wrong fs type, bad option, bad superblock on /dev/sdb1,
missing codepage or helper program, or other error
In some cases useful info is found in syslog – try
dmesg | tail  or so

ext4

mkfs.ext4 /dev/sdb1
mount /dev/sdb1 /mnt/cached-Share/
umount /mnt/cached-Share/
mount /dev/sdb1 /mnt/cached-Share/ -o fsc

the error message (response to the shell command):

mount: wrong fs type, bad option, bad superblock on /dev/sdb1,
missing codepage or helper program, or other error
In some cases useful info is found in syslog – try
dmesg | tail  or so

the error message in (/var/log/messages):

[  846.008443] EXT4-fs (sdb1): Unrecognized mount option “fsc” or missing value

some performance experiments

to answer the question if all this setup is worth the effort, lets’ make some experiments:

  • time cp /usr/src/linux /mnt/cached-Share/
  • grep “__” /usr/src/linux -R
  • time rm -Rf /mnt/cached-Share/usr

please note: i’ve changed the described setup a little bit: the virtual machine guest was given a virtual disk which was stored on a SSD driver.

performance tests inside a virtualbox guests seem to be worthless. i have to repeat similar tests on the target machine. but using a local NFS just to get ‘fscache’ working seems to be a bad design IMHO. we’ll see if it is worth it.

conclusion

seems hot-data can be used with the NFS workaround but not without it. in contrast: zfs/btrfs have direct support for adding ‘hot’ data cache:

  • btrfs: ‘hot data relocation‘ functionality [5]
  • zfs: this is referred to as ‘Separate Cache Devices‘ [6]  or ‘ssd caching‘ [7]

it would be nice to have a similar feature to fscache but for any filesystem (not limited to NFS/AFS/ISOFS) with the ability to be added dynamically (maybe using remount, so one does not have to unmount/mount the filesystem).

links

[1] http://en.wikipedia.org/wiki/CacheFS

[2] http://www.ubuntu-forum.de/artikel/32272/nfs-server-unter-ubuntu-einrichten.htm

[3] /usr/share/doc/cachefilesd/howto.txt.gz (coming with deb-package: cachefilesd)

[4] /usr/src/linux/Documentation/filesystems/caching/fscache.txt (found on my Gentoo system in 2.6.36-gentoo-r5)

[5] http://lwn.net/Articles/397643/ (Btrfs: Add hot data tracking functionality)

[6] http://www.solarisinternals.com/wiki/index.php/ZFS_Best_Practices_Guide#Separate_Cache_Devices

[7]  http://blogs.oracle.com/brendan/entry/test


Posts for Monday, June 13, 2011

avatar

What’s next after stabilization?

The last few weeks have shown quite a few interesting improvements on Gentoo Hardened’s SELinux state. We now have improved (simplified) Gentoo profile support, supporting SELinux on no-multilib (an often requested feature, now finally in), we stabilized the 2.20101213 policies that are in the tree and are cleaning up the old ones. The documentation is continuously updated (handbook and FAQ) and we are getting a nice stream of users helping out and reporting stuff on SELinux.

So, besides the further stabilization and bug fixing, what else is on the horizon?

Well, our first concern now will be to make the ebuilds more… correct. Some of them still violate a few QA rules and this needs to be fixed. If possible, we’ll also start converting our ebuilds to a more recent EAPI.

Then, we will take a first stab at MCS within Gentoo Hardened. Our primary concern here is support for the virtualization technologies which, if SELinux-aware, are often using MCS to shield off running guests from each other.

So interesting times are ahead. And of course, while we’re at it, we’ll continue improving policies and submitting our own patches upstream.

Posts for Saturday, June 11, 2011

Adding sequence and patching live databases

As I’m aiming for a more «professional» look in my database, I’ve become rather embarrassed by the way I have previously generated sequential id’s, by SELECT MAX(person_id) + 1 FROM persons, which is not very impressive to say the least. One of the worst aspects of this approach is that you have to initialize table persons with at least one row with more or less nonsensical data:

INSERT INTO persons VALUES (0,NOW(),9,'Enoch','','','Root','','');

Yes I’m a Neal Stephenson fan, but this person is irrelevant to all databases but for those containing all persons mentioned in Mr. Stephenson’s «Cryptonomicon» and the massive «Baroque Cycle». Besides, no person should have the number 0 anyway.

Thus I reckon the time has come for a better approach. Postgres has this thing called SEQUENCE which actually is made for generating sequential id’s, so why not use it?

In a database made from scratch, you can use the data type SERIAL which, behind the scene, creates a sequence and a default value of your id. See the FAQ for the details.

In a live database, the task is a little more complex. The SERIAL can’t be used to redefine your id, you have to add the sequence and the default value by hand. You must also calculate the start value of the sequence, starting with MAX(person_id) + 1.

The problem gets even more hairy when you consider how to create a patch that introduces the SERIAL in a live database at a client to whom you just want to send a patch that he can run in psql. You don’t even know which version of Postgres he’s running. The obvious solution is this:

pgslekt=> CREATE SEQUENCE persons_person_id_seq START WITH (SELECT MAX(person_id) FROM persons);
ERROR:  syntax error at or near "("
LINE 1: CREATE SEQUENCE persons_person_id_seq START WITH (SELECT MAX...

It just doesn’t work, and Tom Lane explains:

«there are no “utility” statements in PG that accept non-constant expressions in their parameters. (A utility statement is anything other than SELECT, INSERT, UPDATE, DELETE.)

There’s been occasional speculation about changing that, but it would take a significant amount of work I think.»

So much for that approach. In version 9.0 and above, you can use the DO syntax, as Andreas Kretschmer explains:

test=# select * from foo;
 i
----
 98
 99
(2 rows)
 
Time: 0,146 ms
test=*# \ds seq_foo;
No matching relations found.
test=*# do $$ declare m int; begin select into m max(i) from foo; execute 'create sequence seq_foo start with ' || m; end; $$;
DO
Time: 1,115 ms
test=*# \ds seq_foo;
            List of relations
 Schema |  Name   |   Type   |   Owner
--------+---------+----------+------------
 public | seq_foo | sequence | kretschmer
(1 row)
 
test=*# select * from seq_foo;
 sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
 seq_foo       |         99 |          99 |            1 | 9223372036854775807 |         1 |           1 |       1 | f         | f
(1 row)

But if your client runs Postgres 8.x, that’s no good. I finally decided to write a one-shot function, which really is the only viable solution* in a fundamentally unknown environment:

CREATE FUNCTION one_shot_start_person_sequence() RETURNS VOID AS $$
DECLARE
    x INTEGER;
BEGIN
    SELECT MAX(person_id) + 1 FROM persons INTO x;
    EXECUTE 'CREATE SEQUENCE persons_person_id_seq START WITH ' || x;
END
$$ LANGUAGE plpgsql VOLATILE;
SELECT one_shot_start_person_sequence();
DROP FUNCTION one_shot_start_person_sequence();
ALTER TABLE persons ALTER COLUMN person_id SET DEFAULT nextval('persons_person_id_seq');
-- delete 'Enoch Root'
DELETE FROM persons WHERE person_id = 0;

And that’s prob’ly it. Zarro Boogs.

The PHP code was surprisingly easy to change, I only had to modify a couple of lines in the person_insert.php script. Here’s the diff.

Thanks to Guillaume Lelarge, Tom Lane, and Andreas Kretschmer on the wonderful Postgres mail lists. You won’t get better support from a company that charges you with an arm and a leg for their services.

* Edit: After reading the two great comments from Marko and Thomas to this posting, I rewrote the patch:

CREATE SEQUENCE persons_person_id_seq;
SELECT SETVAL('persons_person_id_seq', MAX(person_id)) FROM persons;
ALTER TABLE persons ALTER COLUMN person_id SET DEFAULT NEXTVAL('persons_person_id_seq');
ALTER SEQUENCE persons_person_id_seq OWNED BY persons.person_id;
-- delete 'Enoch Root'
DELETE FROM persons WHERE person_id = 0;

Thank you, guys. This is by far the more elegant method.

Posts for Thursday, June 9, 2011

Paludis 0.62.0 Released

Paludis 0.62.0 has been released:

  • New package dep spec syntax for matching masks: ‘[.(mask)?]‘.
  • Added ‘cave sync –revision’, currently only for Git syncs.
  • We now use Google’s ‘gtest’ for unit tests.
  • Fairly hefty code cleanups.

Filed under: paludis releases Tagged: paludis

Posts for Tuesday, June 7, 2011

avatar

World IPv6 Day – The Future is Forever

It’s time!

Tomorrow is the World IPv6 Day and in order to celebrate it in Athens, we are having an IPv6 Party at hackerspace.gr!
I’ll do a small introductory presentation about the basics of IPv6 Protocol and how’s Linux doing with it. After the presentation there will be an open discussion regarding IPv6 … drinking beer.

Everyone’s invited! Be there!

WORLD IPV6 DAY is 8 June 2011 – The Future is Forever

iPhone cloud vs Android

Okay...  So, this isn't gonna be the rant that you thought it was by the title.  With the little time I have, I couldn't come up with a better one...

So, the story is - I had just eaten a delicious burger at Coney's, when on my way home, I happened to turn on Rush Limbaugh.  He was talking about this new "cloud" technology coming out from Apple.  Admittedly, I know nothing of this, but what he said made me cringe...

"With this new technology, you now don't have to be tied down to iTunes to update or sync your iPhone!  Isn't that great!?"

All I've gotta say is - Android has been tied down to NOTHING since its inception.  I had an iPhone for 1.5 years, and since I'm a Linux user, about half of what the phone could do was automatically nullified due to iTunes incompatibility.  Yeah, that sucked.

So I got an android.  I didn't need a computer to activate it.  I didn't need a proprietary program through which to put music on it.  It connected seamlessly to my Linux machine, my windows box, and even (yup) a mac.  Within a month of having my android, I was doing more with it than I ever did with my iPhone.

Vendor lock-in sucks, but when someone as big as Rush Limbaugh says "Holy cow!  Isn't this 'new technology' great", when that "new technology" is nothing more than Apple straining to capture the marketshare it's losing to Android because Android is leaps and bounds ahead, is horrible.

Hey Rush!  Get an Android!

Project hosting and project name

The project «Exodus» is now history.

Instead, say hello to project Yggdrasil-genealogy hosted on Google Code. I’d prefer plain «Yggdrasil» which is what the project will be called informally, – at least by myself, – but that name has been taken by an apparently inactive project a long time ago. The time for a more advanced project management was long overdue, and Google Code seems like a good host for a project like this. With a new hosting, the time for a name change also seems appropriate. The name «Exodus» was tentatively chosen when I migrated my data from The Master Genealogist back in 2005. That phase was of course the real exodus, but preliminary names have an uncanny tendency to stick.

Until further notice, you can still download my backup code tarball from Solumslekt. However, I’ll recommend using anonymous checkout for the future.

There will be a period of transition until the new name is reflected everywhere, and the project may still occasionally be referred to as «the project formerly known as Exodus».

Posts for Saturday, June 4, 2011

Update

It’s been a long time since my last post. Yesterday, I received an email from a potential user of Exodus who had some problems with initialization of the database, and provided me with a detailed report. That made me run a regression test which I haven’t done for a long time. Among the things that were half-way implemented, was my “user settings” cf. previous post. I’ve finally come up with this design:

CREATE TABLE user_settings (
    username                TEXT PRIMARY KEY DEFAULT current_user,
    last_selected_source    INTEGER NOT NULL DEFAULT 0,
    place_filter_level      TEXT NOT NULL DEFAULT 'level_4',
    place_filter_content    TEXT NOT NULL DEFAULT '%',
    show_delete             BOOLEAN NOT NULL DEFAULT FALSE,
    initials                TEXT NOT NULL DEFAULT ''
);
 
INSERT INTO user_settings VALUES(DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT,'LBK');

This makes it possible to have several users with their individual settings. (Edit: Initially the default value for place_filter_level was blank. That’s no good idea, because the filtered_places() function requires a valid column name from the places table in this attribute.)

If any of you want to test the program, now is the time to download it. I haven’t run a full regression test of the interface, but at least the database initialization should work fine.

Planet Larry is not officially affiliated with Gentoo Linux. Original artwork and logos copyright Gentoo Foundation. Yadda, yadda, yadda.