Adventures in D programming
I recently wrote a bigger project in the D programming language, the appstream-generator (asgen). Since I rarely leave the C/C++/Python realm, and came to like many aspects of D, I thought blogging about my experience could be useful for people considering to use D.
Disclaimer: I am not an expert on programming language design, and this is not universally valid criticism of D – just my personal opinion from building one project with it.
Why choose D in the first place?
The previous AppStream generator was written in Python, which wasn’t ideal for the task for multiple reasons, most notably multiprocessing and LMDB not working well together (and in general, multiprocessing being terrible to work with) and the need to reimplement some already existing C code in Python again.
So, I wanted a compiled language which would work well together with the existing C code in libappstream. Using C was an option, but my least favourite one (writing this in C would have been much more cumbersome). I looked at Go and Rust and wrote some small programs performing basic operations that I needed for asgen, to get a feeling for the language. Interfacing C code with Go was relatively hard – since libappstream is a GObject-based C library, I expected to be able to auto-generate Go bindings from the GIR, but there were only few outdated projects available which did that. Rust on the other hand required the most time in learning it, and since I only briefly looked into it, I still can’t write Rust code without having the coding reference open. I started to implement the same examples in D just for fun, as I didn’t plan to use D (I was aiming at Go back then), but the language looked interesting. The D language had the huge advantage of being very familiar to me as a C/C++ programmer, while also having a rich standard library, which included great stuff like std.concurrency.Generator, std.parallelism, etc. Translating Python code into D was incredibly easy, additionally a gir-d-generator which is actively maintained exists (I created a small fork anyway, to be able to directly link against the libappstream library, instead of dynamically loading it).
What is great about D?
This list is just a huge braindump of things I had on my mind at the time of writing 
Interfacing with C
There are multiple things which make D awesome, for example interfacing with C code – and to a limited degree with C++ code – is really easy. Also, working with functions from C in D feels natural. Take these C functions imported into D:
extern(C):
nothrow:
struct _mystruct {}
alias mystruct_p = _mystruct*;
mystruct_p = mystruct_create ();
mystruct_load_file (mystruct_p my, const(char) *filename);
mystruct_free (mystruct_p my);
You can call them from D code in two ways:
auto test = mystruct_create ();
// treating "test" as function parameter
mystruct_load_file (test, "/tmp/example");
// treating the function as member of "test"
test.mystruct_load_file ("/tmp/example");
test.mystruct_free ();
This allows writing logically sane code, in case the C functions can really be considered member functions of the struct they are acting on. This property of the language is a general concept, so a function which takes a `string` as first parameter, can also be called like a member function of `string`.
Writing D bindings to existing C code is also really simple, and can even be automatized using tools like dstep. Since D can also easily export C functions, calling D code from C is also possible.
Getting rid of C++ “cruft”
There are many things which are bad in C++, some of which are inherited from C. D kills pretty much all of the stuff I found annoying. Some cool stuff from D is now in C++ as well, which makes this point a bit less strong, but it’s still valid. E.g. getting rid of the `#include` preprocessor dance by using symbolic import statements makes sense, and there have IMHO been huge improvements over C++ when it comes to metaprogramming.
Incredibly powerful metaprogramming
Getting into detail about that would take way too long, but the metaprogramming abilities of D must be mentioned. You can do pretty much anything at compiletime, for example compiling regular expressions to make them run faster at runtime, or mixing in additional code from string constants. The template system is also very well thought out, and never caused me headaches as much as C++ sometimes manages to do.
Built-in unit-test support
Unittesting with D is really easy: You just add one or more `unittest { }` blocks to your code, in which you write your tests. When running the tests, the D compiler will collect the unittest blocks and build a test application out of them.
The `unittest` scope is useful, because you can keep the actual code and the tests close together, and it encourages writing tests and keep them up-to-date. Additionally, D has built-in support for contract programming, which helps to further reduce bugs by validating input/output.
Safe D
While D gives you the whole power of a low-level system programming language, it also allows you to write safer code and have the compiler check for that, while still being able to use unsafe functions when needed.
Unfortunately, `@safe` is not the default for functions though.
Separate operators for addition and concatenation
D exclusively uses the `+` operator for addition, while the `~` operator is used for concatenation. This is likely a personal quirk, but I love it very much that this distinction exists. It’s nice for things like addition of two vectors vs. concatenation of vectors, and makes the whole language much more precise in its meaning.
Optional garbage collector
D has an optional garbage collector. Developing in D without GC is currently a bit cumbersome, but these issues are being addressed. If you can live with a GC though, having it active makes programming much easier.
Built-in documentation generator
This is almost granted for most new languages, but still something I want to mention: Ddoc is a standard tool to generate code documentation for D code, with a defined syntax for describing function parameters, classes, etc. It will even take the contents of a `unittest { }` scope to generate automatic examples for the usage of a function, which is pretty cool.
Scope blocks
The `scope` statement allows one to execute a bit of code before the function exists, when it failed or was successful. This is incredibly useful when working with C code, where a free statement needs to be issued when the function is exited, or some arbitrary cleanup needs to be performed on error. Yes, we do have smart pointers in C++ and – with some GCC/Clang extensions – a similar feature in C too. But the scopes concept in D is much more powerful. See Scope Guard Statement for details.
Built-in syntax for parallel programming
Working with threads is so much more fun in D compared to C! I recommend taking a look at the parallelism chapter of the “Programming in D” book.
“Pure” functions
D allows to mark functions as purely-functional, which allows the compiler to do optimizations on them, e.g. cache their return value. See pure-functions.
D is fast!
D matches the speed of C++ in almost all occasions, so you won’t lose performance when writing D code – that is, unless you have the GC run often in a threaded environment.
Very active and friendly community
The D community is very active and friendly – so far I only had good experience, and I basically came into the community asking some tough questions regarding distro-integration and ABI stability of D. The D community is very enthusiastic about pushing D and especially the metaprogramming features of D to its limits, and consists of very knowledgeable people. Most discussion happens at the forums/newsgroups at forum.dlang.org.
What is bad about D?
Half-proprietary reference compiler
This is probably the biggest issue. Not because the proprietary compiler is bad per se, but because of the implications this has for the D ecosystem.
For the reference D compiler, Digital Mars’ D (DMD), only the frontend is distributed under a free license (Boost), while the backend is proprietary. The FLOSS frontend is what the free compilers, LLVM D Compiler (LDC) and GNU D Compiler (GDC) are based on. But since DMD is the reference compiler, most features land there first, and the Phobos standard library and druntime is tuned to work with DMD first.
Since major Linux distributions can’t ship with DMD, and the free compilers GDC and LDC lack behind DMD in terms of language, runtime and standard-library compatibility, this creates a split world of code that compiles with LDC, GDC or DMD, but never with all D compilers due to it relying on features not yet in e.g. GDCs Phobos.
Especially for Linux distributions, there is no way to say “use this compiler to get the best and latest D compatibility”. Additionally, if people can’t simply `apt install latest-d`, they are less likely to try the language. This is probably mainly an issue on Linux, but since Linux is the place where web applications are usually written and people are likely to try out new languages, it’s really bad that the proprietary reference compiler is hurting D adoption in that way.
That being said, I want to make clear DMD is a great compiler, which is very fast and build efficient code. I only criticise the fact that it is the language reference compiler.
UPDATE: To clarify the half-proprietary nature of the compiler, let me quote the D FAQ:
The front end for the dmd D compiler is open source. The back end for dmd is licensed from Symantec, and is not compatible with open-source licenses such as the GPL. Nonetheless, the complete source comes with the compiler, and all development takes place publically on github. Compilers using the DMD front end and the GCC and LLVM open source backends are also available. The runtime library is completely open source using the Boost License 1.0. The gdc and ldc D compilers are completely open sourced.
Phobos (standard library) is deprecating features too quickly
This basically goes hand in hand with the compiler issue mentioned above. Each D compiler ships its own version of Phobos, which it was tested against. For GDC, which I used to compile my code due to LDC having bugs at that time, this means that it is shipping with a very outdated copy of Phobos. Due to the rapid evolution of Phobos, this meant that the documentation of Phobos and the actual code I was working with were not always in sync, leading to many frustrating experiences.
Furthermore, Phobos is sometimes removing deprecated bits about a year after they have been deprecated. Together with the older-Phobos situation, you might find yourself in a place where a feature was dropped, but the cool replacement is not yet available. Or you are unable to import some 3rd-party code because it uses some deprecated-and-removed feature internally. Or you are unable to use other code, because it was developed with a D compiler shipping with a newer Phobos.
This is really annoying, and probably the biggest source of unhappiness I had while working with D – especially the documentation not matching the actual code is a bad experience for someone new to the language.
Incomplete free compilers with varying degrees of maturity
LDC and GDC have bugs, and for someone new to the language it’s not clear which one to choose. Both LDC and GDC have their own issues at time, but they are rapidly getting better, and I only encountered some actual compiler bugs in LDC (GDC worked fine, but with an incredibly out-of-date Phobos). All issues are fixed meanwhile, but this was a frustrating experience. Some clear advice or explanation which of the free compilers is to prefer when you are new to D would be neat.
For GDC in particular, being developed outside of the main GCC project is likely a problem, because distributors need to manually add it to their GCC packaging, instead of having it readily available. I assume this is due to the DRuntime/Phobos not being subjected to the FSF CLA, but I can’t actually say anything substantial about this issue. Debian adds GDC to its GCC packaging, but e.g. Fedora does not do that.
No ABI compatibility
D has a defined ABI – too bad that in reality, the compilers are not interoperable. A binary compiled with GDC can’t call a library compiled with LDC or DMD. GDC actually doesn’t even support building shared libraries yet. For distributions, this is quite terrible, because it means that there must be one default D compiler, without any exception, and that users also need to use that specific compiler to link against distribution-provided D libraries. The different runtimes per compiler complicate that problem further.
The D package manager, dub, does not yet play well with distro packaging
This is an issue that is important to me, since I want my software to be easily packageable by Linux distributions. The issues causing packaging to be hard are reported as dub issue #838 and issue #839, with quite positive feedback so far, so this might soon be solved.
The GC is sometimes an issue
The garbage collector in D is quite dated (according to their own docs) and is currently being reworked. While working with asgen, which is a program creating a large amount of interconnected data structures in a threaded environment, I realized that the GC is significantly slowing down the application when threads are used (it also seems to use UNIX signals `SIGUSR1` and `SIGUSR2` to stop/resume threads, which I still find odd). Also, the GC performed poorly on memory pressure, which did get asgen killed by the OOM killer on some more memory-constrained machines. Triggering a manual collection run after a large amount of these interconnected data structures wasn’t needed anymore solved this problem for most systems, but it would of course have been better to not needing to give the GC any hints. The stop-the-world behavior isn’t a problem for asgen, but it might be for other applications.
These issues are at time being worked on, with a GSoC project laying the foundation for further GC improvements.
“version” is a reserved word
Okay, that is admittedly a very tiny nitpick, but when developing an app which works with packages and versions, it’s slightly annoying. The `version` keyword is used for conditional compilation, and needing to abbreviate it to `ver` in all parts of the code sucks a little (e.g. the “Package” interface can’t have a property “version”, but now has “ver” instead).
The ecosystem is not (yet) mature
In general it can be said that the D ecosystem, while existing for almost 9 years, is not yet that mature. There are various quirks you have to deal with when working with D code on Linux. It’s always nothing major, usually you can easily solve these issues and go on, but it’s annoying to have these papercuts.
This is not something which can be resolved by D itself, this point will solve itself as more people start to use D and D support in Linux distributions gets more polished.
Conclusion
I like to work with D, and I consider it to be a great language – the quirks it has in its toolchain are not that bad to prevent writing great things with it.
At time, if I am not writing a shared library or something which uses much existing C++ code, I would prefer D for that task. If a garbage collector is a problem (e.g. for some real-time applications, or when the target architecture can’t run a GC), I would not recommend to use D. Rust seems to be the much better choice then.
In any case, D’s flat learning curve (for C/C++ people) paired with the smart choices taken in language design, the powerful metaprogramming, the rich standard library and helpful community makes it great to try out and to develop software for scenarios where you would otherwise choose C++ or Java. Quite honestly, I think D could be a great language for tasks where you would usually choose Python, Java or C++, and I am seriously considering to replace quite some Python code with D code. For very low-level stuff, C is IMHO still the better choice.
As always, choosing the right programming language is only 50% technical aspects, and 50% personal taste 
UPDATE: To get some idea of D, check out the D tour on the new website tour.dlang.org.
Mind the gap between platform and app
With the Open Source Event Manager (OSEM), one of the Ruby on Rails apps I hack on, we're heading down the road to version 1.0. A feature we absolutely wanted to have, before making this step, was an easy deployment to at least one of the many Platform as a Service (PaaS) providers. We deemed this important for two reasons:
- Before people commit to use your precious little app they want to try it. And this has to be hassle free.
- Getting your server operating system ready to deploy Ruby on Rails applications can be tedious, too tedious for some people.
So I have been working on making our app ready for Heroku which is currently the most popular PaaS provider for rails (is it?). This was an interesting road, this is my travelogue.
Storage in the public cloud
Storing files is incredibly easy in Rails, there are many ready made solutions for it like paperclip, dragonfly or carrierwave. The challenge with Heroku is, that on their free plan, your apps storage will be discarded the moment it is stopped or restarted. This happens for instance every time during a deployment or when the app goes to sleep because nobody is using it.
And even though it's easy to store files in Rails, we in the OSEM team have long discouraged this in our app. We rather try to make it as easy as possible to reference things you have shared somewhere else. Want to show a picture of your Events location? Use the ones you share on flickr or instagram anyway. Embed a video of a Talk? Just paste the Youtube or Vimeo link. Share the slides with your audience? Slideshare or Speakerdeck to the rescue!
OSEM commercials by Henne Vogelsang licensed CC BY 4.0
Still there are some places left in our app where we upload pictures. Pictures we think conference organizers are not necessarily free to share on other platforms, like sponsor logos or pictures of sponsored lodgings. So to be able to use OSEM on Heroku our file upload needed support for offloading the files to someone else's computer a.k.a. *the cloud*. In the end I have settled for the carrierwave plug in of cloudinary (pull request #970).
This means it's now as easy as configuring the cloudinary gem and making use of their free plan to shove off all the storage OSEM needs to them.
Storage was the first gap in OSEM that I closed, another piece of the puzzle was configuration.
Configuration in the environment
According to some clever people it's too easy to mistakenly check in your apps configuration file into your version control system. That's the reason your apps environment should provide all the settings. I'm not a big fan of putting stickers onto microwaves that say you can't use it to dry your cat. If people want to be stupid, let them.
But hey 12-Factor is a thing, let's roll with it! So in pull request #900 I removed all traces of OSEMs YAML configuration file and now all the settings happen in environment variables.
This was the second gap I had to close to be able to run our app on Heroku. Now all of the sudden things where falling into place and some very interesting things emerged for OSEM.
Continuous Deployment
One of the reasons I have gone down this road was to make it easy for people to try out OSEM. Now once you can run your app on Heroku you can also integrate your github repository and run a continuous deployment (every commit get's deployed right away). That made it possible for us to set up an OSEM demo instance for people to try which always runs the latest code. All we had to do is to make use of data from our test suite to populate the demo (pull request #982) and voila...
OSEM demo by Henne Vogelsang licensed CC BY 4.0
Continuous Review
So a continuous deployment of the latest code with some sample data. Does that sound useful for you as free software developer? I think being a free software developer first and foremost means collaborating with varying people from all over. People I work with on a daily basis and people who I never had contact with before. Collaboration mostly means reviewing each others changes to our code. It's pretty easy as we have rules and tools for that in place. What is not so easy is to do the same for changes to the functionality, the user experience design, of our app.
In the OSEM team we some times attach a series of screenshots or animated gifs to a github pull requests to convey changes to the user interaction and work flows, but this is usually no replacement for trying yourself. Then in the middle of me doing all of this Heroku Review Apps happened. Review apps are instant, disposable deployments of your app that spin up automatically with each pull request.
OSEM heroku pipeline by Henne Vogelsang licensed CC BY 4.0
Now, once someone sends a pull request where I want to review the user experience design I just press the 'Create Review App' button on Heroku and a minute later I get the a temporary instance populated with test data. Magic.
More things to come?
Another thing we might want to replace in the future is how we spin up developer instances. So far we use Vagrant which starts your OSEM checkout in a virtual machine. But nowadays you have to have docker containers in the mix right? Let's see what the future brings.
All in all, I must say, it was a nice trip into the Platform as a Service world. Surprisingly easy to do and even more surprisingly rewarding for the development work flow. What do you think?
Thursday: ownCloud at Open Tech Summit!
If you'd like to join, there's a number of free tickets available. Go to this website to register and use the code WELOVEOWNCLOUD.
See you there!
Danbooru Client 0.6.0 released
A new version of Danbooru Client is now available!
What is Danbooru Client?
Danbooru Client is an application to access Danbooru-based image boards (Wikipedia definition).
It offers a convenient, KF5 and Qt5-based GUI coupled with a QML image view to browse, view, and download images hosted in two of the most famous Danbooru boards (konachan.com and yande.re).
Highglights of the new version
- Support for width / height based filtering: now you can exclude posts that are below a specific width or height (or both)
- New dependency: KTextWidgets
Coming up next
Sooner or later I’ll get to finish the multiple API support, but given that there’s close to no interest for these programs (people are happy to use a browser) and that I work on this very irregularly (every 6-7 months at best), there’s no ETA at all. It might be done this year, perhaps the next.
Release details
Currently, there is only a source tarball. For security, I have signed it with my public GPG key (A29D259B) and I have also provided a SHA-512 hash of the release.
[Help Needed] FOSS License, CLA Query
- The project is a database (say, like mongodb, Cassandra etc.). It will have a server piece that users can deploy for storing data. Though it is a hobby personal project as of now, I may offer the database as a paid, hosted solution in future.
- There are some client libraries too, for providing the ability to connect to the above mentioned server, from a variety of programming languages.
- The client libraries will all be in Creative Commons Zero License / Public Domain. Basically anyone can do anything with the client library sources. The server license is where I have difficulty choosing.
- Anyone who contributes any source to the server software should re-assign their copyrights and ownership of the code, to me. By "me", I refer to myself as an individual and not any company. I should reserve the right to transfer the ownership in future to anyone / any company. I may relicense the software in future to public domain or sell it off to a company like: SUSE, Red Hat, Canonical, (or) a company like: Amazon, Google, Microsoft etc.
- Anyone who contributes code to my project, should make sure that [s]he has all the necessary copyrights to submit the changes to me and to re-assign the copyrights to me. I should not be liable for someone's contribution. If a contributor's employer has a sudden evil plan and want to take over my personal project to court (unlikely to happen, nevertheless), it should not be possible
- I or the users of the software, should not be sued for any patent infringement cases, for code that is contributed by someone else. If a patent holder wants to sue me for a code that I have written in the software, that is fine. I will find a way around.
- Anyone should be free to take the server sources, modify it and deploy it in his/her own hardware/cloud, for their personal and/or commercial needs, without paying me or any of the contributors any money/royalty/acknowledgement.
- If they choose to either sell the server software or host it and sell it as a service, (basically commercial reasons) they must be enforced to open source their changes in public domain, unless they have a written permission from me, at my discretion. For instance, if coursera wants to use my database source, after modifications, it is fine with me; but I will not want, say Oracle to modify my software and sell the modified software / service, without opensourcing their changes. If someone is hosting and selling a service of my software, with modified sources, there is no easy way for me to prove their modification, but I would still like to have that legal protection.
The best license model that I could come up for the above is: Dual license the source code to AGPLv3 and a proprietary license. Enforce a CLA to accept all contributions only after a copyright reassignment to me, with a guarantee that I have the right to change the license at a future time.
What is not clear to me however, is the patent infringement and ownership violation related constraints and AGPL's protection on such disputes. Another option is: Mozilla Public License 2.0 but that does not seem to cover the hosting-as-a-service-and-selling-the-service aspect clearly imho.
Are you readers of the internet have any better solution ?
Are you aware of any other project using any other license, CLA model that may suit my needs and/or is similar ?
What other things should I be reading to understand more ?
Or, should I lose all faith in licenses and keep the sources private and release the binary as freeware, instead of open sourcing ? That would suck.
Or should I just not bother about someone making proprietary modifications and selling the software/service, by releasing the software to public domain ?
Note: Of course, all these is assuming that my 1 hour a month, hobby project would make it big, be useful to others and someone may sue. In reality, the software may not be tried by even a dozen people, but I'm just romanticizing.
Why are AppStream metainfo files XML data?
This is a question raised quite quite often, the last time in a blogpost by Thomas, so I thought it is a good idea to give a slightly longer explanation (and also create an article to link to…).
There are basically three reasons for using XML as the default format for metainfo files:
1. XML is easily forward/backward compatible, while YAML is not
This is a matter of extending the AppStream metainfo files with new entries, or adapt existing entries to new needs.
Take this example XML line for defining an icon for an application:
<icon type="cached">foobar.png</icon>
and now the equivalent YAML:
Icons:
cached: foobar.png
Now consider we want to add a width and height property to the icons, because we started to allow more than one icon size. Easy for the XML:
<icon type="cached" width="128" height="128">foobar.png</icon>
This line of XML can be read correctly by both old parsers, which will just see the icon as before without reading the size information, and new parsers, which can make use of the additional information if they want. The change is both forward and backward compatible.
This looks differently with the YAML file. The “foobar.png” is a string-type, and parsers will expect a string as value for the `cached` key, while we would need a dictionary there to include the additional width/height information:
Icons:
cached: name: foobar.png
width: 128
height: 128
The change shown above will break existing parsers though. Of course, we could add a `cached2` key, but that would require people to write two entries, to keep compatibility with older parsers:
Icons:
cached: foobar.png
cached2: name: foobar.png
width: 128
height: 128
Less than ideal.
While there are ways to break compatibility in XML documents too, as well as ways to design YAML documents in a way which minimizes the risk of breaking compatibility later, keeping the format future-proof is far easier with XML compared to YAML (and sometimes simply not possible with YAML documents). This makes XML a good choice for this usecase, since we can not do transitions with thousands of independent upstream projects easily, and need to care about backwards compatibility.
2. Translating YAML is not much fun
A property of AppStream metainfo files is that they can be easily translated into multiple languages. For that, tools like intltool and itstool exist to aid with translating XML using Gettext files. This can be done at project build-time, keeping a clean, minimal XML file, or before, storing the translated strings directly in the XML document. Generally, YAML files can be translated too. Take the following example (shamelessly copied from Dolphin):
<summary>File Manager</summary>
<summary xml:lang="bs">Upravitelj datoteka</summary>
<summary xml:lang="cs">Správce souborů</summary>
<summary xml:lang="da">Filhåndtering</summary>
This would become something like this in YAML:
Summary:
C: File Manager
bs: Upravitelj datoteka
cs: Správce souborů
da: Filhåndtering
Looks manageable, right? Now, AppStream also covers long descriptions, where individual paragraphs can be translated by the translators. This looks like this in XML:
<description>
<p>Dolphin is a lightweight file manager. It has been designed with ease of use and simplicity in mind, while still allowing flexibility and customisation. This means that you can do your file management exactly the way you want to do it.</p>
<p xml:lang="de">Dolphin ist ein schlankes Programm zur Dateiverwaltung. Es wurde mit dem Ziel entwickelt, einfach in der Anwendung, dabei aber auch flexibel und anpassungsfähig zu sein. Sie können daher Ihre Dateiverwaltungsaufgaben genau nach Ihren Bedürfnissen ausführen.</p>
<p>Features:</p>
<p xml:lang="de">Funktionen:</p>
<p xml:lang="es">Características:</p>
<ul>
<li>Navigation (or breadcrumb) bar for URLs, allowing you to quickly navigate through the hierarchy of files and folders.</li>
<li xml:lang="de">Navigationsleiste für Adressen (auch editierbar), mit der Sie schnell durch die Hierarchie der Dateien und Ordner navigieren können.</li>
<li xml:lang="es">barra de navegación (o de ruta completa) para URL que permite navegar rápidamente a través de la jerarquía de archivos y carpetas.</li>
<li>Supports several different kinds of view styles and properties and allows you to configure the view exactly how you want it.</li>
....
</ul>
</description>
Now, how would you represent this in YAML? Since we need to preserve the paragraph and enumeration markup somehow, and creating a large chain of YAML dictionaries is not really a sane option, the only choices would be:
- Embed the HTML markup in the file, and risk non-careful translators breaking the markup by e.g. not closing tags.
- Use Markdown, and risk people not writing the markup correctly when translating a really long string in Gettext.
In both cases, we would loose the ability to translate individual paragraphs, which also means that as soon as the developer changes the original text in YAML, translators would need to translate the whole bunch again, which is inconvenient.
On top of that, there are no tools to translate YAML properly that I am aware of, so we would need to write those too.
3. Allowing XML and YAML makes a confusing story and adds complexity
While adding YAML as a format would not be too hard, given that we already support it for DEP-11 distro metadata (Debian uses this), it would make the business of creating metainfo files more confusing. At time, we have a clear story: Write the XML, store it in `/usr/share/metainfo`, use standard tools to translate the translatable entries. Adding YAML to the mix adds an additional choice that needs to be supported for eternity and also has the problems mentioned above.
I wanted to add YAML as format for AppStream, and we discussed this at the hackfest as well, but in the end I think it isn’t worth the pain of supporting it for upstream projects (remember, someone needs to maintain the parsers and specification too and keep XML and YAML in sync and updated). Don’t get me wrong, I love YAML, but for translated metadata which needs a guarantee on format stability it is not the ideal choice.
So yeah, XML isn’t fun to write by hand. But for this case, XML is a good choice.
A GNOME Software Hackfest report
Two weeks ago was the GNOME Software hackfest in London, and I’ve been there! And I just now found the time to blog about it, but better do it late than never
.
Arriving in London and finding the Red Hat offices
After being stuck in trains for the weekend, but fortunately arriving at the airport in time, I finally made it to London with quite some delay due to the slow bus transfer from Stansted Airport. After finding the hotel, the next issue was to get food and a place which accepted my credit card, which was surprisingly hard – in defence of London I must say though, that it was a Sunday, 7 p.m. and my card is somewhat special (in Canada, it managed to crash some card readers, so they needed a hard-reset). While searching for food, I also found the Red Hat offices where the hackfest was starting the next day by accident. My hotel, the office and the tower bridge were really close, which was awesome! I have been to London in 2008 the last time, and only for a day, so being that close to the city center was great. The hackfest didn’t leave any time to visit the city much, but by being close to the center, one could hardly avoid the “London experience”
.
Cool people working on great stuff
That’s basically the summary for the hackfest
. It was awesome to meet with Richard Hughes again, since we haven’t seen each other in person since 2011, but work on lots of stuff together. This was especially important, since we managed to solve quite some disagreements we had over stuff – Richard even almost managed to make me give in to adding <kudos/> to the AppStream spec, something which I was pretty against supporting (it didn’t make it yet, but I am no longer against the idea of having that – the remaining issues are solvable).
Meeting Iain Lane again (after FOSDEM) was also very nice, and also seeing other people I’ve only worked with over IRC or bug reports (e.g. William, Kalev, …) was great. Also lots of “new” people were there, like guys from Endless, who build their low-budget computer for developing/emerging countries on top of GNOME and Linux technologies. It’s pretty cool stuff they do, you should check out their website! (they also build their distribution on top of Debian, which is even more awesome, and something I didn’t know before (because many Endless people I met before were associated with GNOME or Fedora, I kind of implicitly assumed the system was based on Fedora
)).
The incarnation of GNOME Software used by endless looks pretty different from what the normal GNOME user sees, since it’s adjusted for a different audience and input method. But it looks great, and is a good example for how versatile GS already is! And for upstream GNOME, we’ve seen some pretty great mockups done by Endless too – I hope those will make it into production somehow.


XdgApp and sandboxing of apps was also a big topic, aside from Ubuntu and Endless integration. Fortunately, Alexander Larsson was also there to answer all the sandboxing and XdgApp-questions.
I used the time to follow up on a conversation with Alexander we started at FOSDEM this year, about the Limba vs. XdgApp bundling issue. While we are in-line on the sandboxing approach, the way how software is distributed is implemented differently in Limba and XdgApp, and it is bad to have too many bundling systems around (doesn’t make for a good story where we can just tell developers “ship as this bundling format, and it will be supported everywhere”). Talking with Alex about this was very nice, and I think there is a way out of the too-many-solutions dilemma, at least for Limba and XdgApp – I will blog about that separately soon.
On the Ubuntu side, a lot of bugs and issues were squashed and changes upstreamed to GNOME, and people were generally doing their best to reduce Richard’s bus-factor on the project a little
.
I mainly worked on AppStream issues, finishing up the last pieces of appstream-generator and running it against some sample package sets (and later that week against the whole Debian archive). I also started to implement support for showing AppStream issues in the Debian PTS (this work is not finished yet). I also managed to solve a few bugs in the old DEP-11 generator and prepare another release for Ubuntu.
We also enjoyed some good Japanese food, and some incredibly great, but also suddenly very expensive Indian food (but that’s a different story
).
The most important thing for me though was to get together with people actually using AppStream metadata in software centers and also more specialized places. This yielded some useful findings, e.g. that localized screenshots are not something weird, but actually a wanted feature of Endless for their curated AppStore. So localized screenshots will be part of the next AppStream spec. Also, there seems to be a general need to ship curation information for software centers somehow (which apps are featured? how are they styled? added special banners for some featured apps, “app of the day” features, etc.). This problem hasn’t been solved, since it’s highly implementation-specific, and AppStream should be distro-agnostic. But it is something we might be able to address in a generic way sooner or later (I need to talk to people at KDE and Elementary about it).
In summary…
It was a great event! Going to conferences and hackfests always makes me feel like it moves projects leaps ahead, even if you do little coding. Sorting out issues together with people you see in person (rather than communicating with them via text messages or video chat), is IMHO always the most productive way to move forward (yeah, unless you do this every week, but I think you get my point
).
For me, being the only (and youngest ^^) developer at the hackfest who was not employed by any company in the FLOSS business, the hackfest was also motivating to continue to invest spare time into working on these projects.
So, the only thing left to do is a huge shout out of “THANK YOU” to the Ubuntu Community Fund – and therefore the Ubuntu community – for sponsoring me! You rock! Also huge thanks to Canonical for organizing the sponsoring really quickly, so I didn’t get into trouble with paying my flights.

To worried KDE people: No, I didn’t leave the blue side – I just generally work on cross-desktop stuff, and would like all desktops to work as well as possible 
Upgrading my home NAS server - (HP Proliant Microserver Gen8 + FreeBSD 10.3 + ZFS + Jails)
I am using FreeBSD+ZFS for my NAS home server since 2009, see my old post about it here: My ZFS Home NAS/HTPC Box Build
The setup worked perfectly in the last years and even if I had a few hard drives failures I never lost any data. Replacing the hard drives was really easy and the system was back to normal in a matter of minutes. Over the last years I also upgraded the hardware a few times:
- two years ago I replaced the mainboard, cpu and added more ram: ASUS P8H77-I + Intel Celeron G460 + 8GB Ram
- about one year ago I replaced the cpu with an Intel Core i3-3250 and went up to 16GB Ram (maximum supported)
And finally, a few weeks ago, I have just found a great deal for a HP Proliant Microserver Gen8 having in standard configuration Intel G1610T cpu and 4GB ECC Ram and I could not miss it. I replaced the Ram with 2x8GB ECC. So that's my new, current, Home Server (NAS) and I am really happy with it. I spent some time with its configuration because of some little issues with running FreeBSD on it and I also decided to change a bit my setup (adding jails for services). I am not using this box for HTPC anymore.
# dmesg
Copyright (c) 1992-2016 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 10.3-RELEASE #0 r297264: Fri Mar 25 02:10:02 UTC 2016
root@releng1.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64
FreeBSD clang version 3.4.1 (tags/RELEASE_34/dot1-final 208032) 20140512
CPU: Intel(R) Celeron(R) CPU G1610T @ 2.30GHz (2294.84-MHz K8-class CPU)
Origin="GenuineIntel" Id=0x306a9 Family=0x6 Model=0x3a Stepping=9
Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
Features2=0xd9ae3bf<SSE3,PCLMULQDQ,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,POPCNT,TSCDLT,XSAVE,OSXSAVE>
AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
AMD Features2=0x1<LAHF>
Structured Extended Features=0x281<FSGSBASE,SMEP,ERMS>
XSAVE Features=0x1<XSAVEOPT>
VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
TSC: P-state invariant, performance statistics
real memory = 17179869184 (16384 MB)
avail memory = 16571678720 (15803 MB)
Event timer "LAPIC" quality 600
ACPI APIC Table: <HP ProLiant>
FreeBSD/SMP: Multiprocessor System Detected: 2 CPUs
[...SKIP...]
Here is a short story with the issues I had: The HP ProLiant MicroServer Gen8 is a small, quiet, and stylishly designed server that is ideal for a NAS storage. It has 4-Bay for hard drives (main storage) and one place for an ODD drive but there is no ODD drive supplied. Initially I decided to add a SSD to this Sata II port to have it for FreeBSD OS and use it also as a storage for some virtual machines (more about my home virtual lab setup in future posts). The first issue was that I could not boot from that SSD because the system is able to boot only from the HDD in the first bay or from usb. After some research I found that the system will be able to boot from the Sata port connected to ODD drive but only if you create a RAID0 and add only the single SSD disk to it. I tried it but if the RAID card is enabled in BIOS, there is no chance to boot FreeBSD. Even from USB is not booting anymore, I always got "BTX Halted" error (there is a screenshot in the photo album below).
The solution was to just disable the RAID card in BIOS, and anyway because I am using ZFS for my NAS is not recommended to use the RAID card (for ZFS storage) which is coming with the server, so is better to just disable it and use the AHCI mode for hard drives.
Not being able to boot FreBSD from my SSD I had to change my plan a bit and perhaps boot from usb. I picked up a SanDisk Ultra 16GB usb stick, installed FreeBSD on it and thrown it in the internal usb port. After I was sure that everything was working as expected I decided to move /usr and /var on the SSD drive and let just keep the / partition on my usb stick. Importing the storage drives with mirrored ZFS pools was really easy and everything is working perfectly now.
I mentioned that I decided also to change a bit my NAS configuration and instead having all services (samba, afp, transmission, plex, monitoring, ...) on my host machine, move them to run each of them in their jail will be preferred. Here are the current jails I run right now:
# jls
JID IP Address Hostname Path
1 192.168.0.41 samba.home.local /storage/jails/samba
2 192.168.0.42 afs.home.local /storage/jails/afs
3 192.168.0.43 transmission.home.local /storage/jails/transmission
4 192.168.0.44 plex.home.local /storage/jails/plex
5 192.168.0.45 monitoring.home.local /storage/jails/monitoring
6 192.168.0.46 gitlab.home.local /storage/jails/gitlab
7 192.168.0.47 confluence.home.local /storage/jails/confluence
8 192.168.0.48 virt.home.local /storage/jails/virtual
And here are some pictures: HP Proliant Microserver Gen 8 Home NAS Photos
Introducing AppStream-Generator
Since mid-2015 we were using the dep11-generator in Debian to build AppStream metadata about available software components in the distribution.
Getting rid of dep11-generator
Unfortunately, the old Python-based dep11-generator was hitting some hard limits pretty soon. For example, using multiprocessing with Python was a pain, since it resulted in some very hard-to-track bugs. Also, the multiprocessing approach (as opposed to multithreading) made it impossible to use the underlying LMDB database properly (it was basically closed and reopened in each forked off process, since pickling the Python LMDB object caused some really funny bugs, which usually manifested themselves in the application hanging forever without any information on what was going on). Additionally to that, the Python-based generator forced me to maintain two implementations of the AppStream YAML spec, one in C and one in Python, which consumes quite some time. There were also some other issues (e.g. no unit-tests) in the implementation, which made me think about rewriting the generator.
Adventures in Go / Rust / D
Since I didn’t want to write this new piece of software in C (or basically, writing it in C was my last option
), I explored Go and Rust for this purpose and also did a small prototype in the D programming language, when I was starting to feel really adventurous. And while I never intended to write the new generator in D (I was pretty fixated on Go…), this is what happened. The strong points for D for this particular project were its close relation to C (and ease of using existing C code), its super-flat learning curve for someone who knows and likes C and C++ and its pretty powerful implementations of the concurrent and parallel programming paradigms. That being said, not all is great in D and there are some pretty dark spots too, mainly when it comes to the standard library and compilers. I will dive into my experiences with D in a separate blogpost.
What good to expect from appstream-generator?
So, what can the new appstream-generator do for you? Basically, the same as the old dep11-generator: It will extract metadata from a distribution’s package archive, download and resize screenshots, search for icons and size them properly and generate reports in JSON and HTML of found metadata and issues.
LibAppStream-based parsing, generation of YAML or XML, multi-distro support, …
As opposed to the old generator, the new generator utilizes the metadata parsers and writers of libappstream. This allows it to return the extracted metadata as AppStream YAML (for Debian) or XML (everyone else) It is also written in a distribution-agnostic way, so if someone wants to use it in a different distribution than Debian, this is possible now. It just requires a very small distribution-specific backend to be written, all of the details of the metadata extraction are abstracted away (just two interfaces need to be implemented). While I do not expect anyone except Debian to use this in the near future (most distros have found a solution to generate metadata already), the frontend-backend split is a much cleaner design than what was available in the previous code. It also allows to unit-test the code properly, without providing a Debian archive in the testsuite.
Feature Flags, Optipng, …
The new generator also allows to enable and disable certain sets of features in a standardized way. E.g. Ubuntu uses a language-pack system for translations, which Debian doesn’t use. Features like this can be implemented as disableable separate modules in the generator. We use this at time to e.g. allow descriptions from packages to be used as AppStream descriptions, or for running optipng on the generated PNG images and icons.
No more Contents file dependency
Another issue the old generator had was that it used the Contents file from the Debian archive to find matching icons for an application. We could never be sure whether the contents in the Contents file actually matched the contents of the package we were currently dealing with. What made things worse is that at Ubuntu, the archive software is only updating the Contents file weekly daily (while the generator might run multiple times a day), which has lead to software being ignored in the metadata, because icons could not yet be found. Even on Debian, with its quickly-updated Contents file, we could immediately see the effects of an out-of-date Contents file when updating it failed once. In the new generator, we read the contents of each package ourselves now and store them in a LMDB database, bypassing the Contents file and removing the whole class of problems resulting from missing or wrong contents-data.
It can’t all be good, right?
That is true, there are also some known issues the new generator has:
Large amounts of RAM required
The better speed of the new generator comes at the cost of holding more stuff in RAM. Much more. When processing data from 5 architectures initially on Debian, the amount of required RAM might lie above 4GB, with the OOM killer sometimes being quicker than the garbage collector… That being said, on subsequent runs the amount of required memory is much lower. Still, this is something I am working on to improve.
What are symbolic links?
To be faster, the appstream-generator will read the md5sum file in .deb packages instead of extracting the payload archive and reading its contents. Since the md5sums file does not list symbolic links, symlinks basically don’t exist for the new generator. This is a problem for software symlinking icons or even .desktop files around, like e.g. LibreOffice does.
I am still investigating how widespread the use of symlinks for icons and .desktop files is, but it looks like fixing packages (making them not-symlink stuff and rather move the files) might be the better approach than investing additional computing power to find symlinks or even switch back to parsing the Contents file. Input on this is welcome!
Deploying asgen
I finished the last pieces of the appstream-generator (together with doing lots of other cool things and talking to great people) at the GNOME Software Hackfest in London last week (detailed blogposts about things that happened there will follow – many thanks once again for the Ubuntu community for sponsoring my attendance!).
Since today, the new generator is running on the Debian infrastructure. If bigger issues are found, we can still roll back to the old code. I decided to deploy this faster, so we can get some good testing done before the Stretch release. Please report any issues you may find!
Volumio2 Release Candidate
Last night I found time to finally install the first release candidate of Volumio 2, my preferred audio player software. This is more exciting than it sounds, because when I read the blogpost last summer that Volumio is going to be completely rewritten, with replacing the base technologies, I was a bit afraid that this will be one of the last bits that we heard from this project. Too many cool projects died after famous last announcements like that.
But not Volumio.

After quite some development time the project released RC1. While there were a few small bugs in a beta, my feelings about the RC1 are really positive. Volumio2 has a very nice and stylish GUI, a great improvement over Volumio1. Album-art is now nicely integrated in the playback pane and and everything is more shiny, even if the general concept is the same as in Volumio1.
I like it because it is only a music player. Very reduced on that, but also very thought through and focussed to fulfill that job perfectly. I just want to find and play music from my collection, quickly and comfortable and with good sound quality. No movies, series, images. Just sound.
About speed: While the scanning of my not too big music collection on a NAS was a bit of a time consuming task in the past, this feels now much faster (maybe thats only because of a faster network between the Raspberry and the NAS?). Searching, browsing and everything works quite fluid on an Raspberry2. And with the Hifiberry DAC for output, the sound quality is more than ok.
This is an release candidate of the first release of the rewritten project, and the quality is already very good. Nevertheless I found a few things that did not work for me or could be improved. That the volume control is not working is probably because of the Hifiberry DAC driver, I remember there was something, but haven’t investigated yet.
There are some things in the GUI that could be looked at again: For example on the Browse page, there is the very well working search field. After entering the search term and Enter, the search result is displayed as a list of songs to select from. I wished that the songs were additionally grouped by albums, which should also be selectable to be pushed to the play queue.
Also it would be great if the Queue would somehow indicate which entry is currently played. I could not spot that.
But these are only minor findings which can easily be addressed later after enhancement requests were posted :-)
I think Volumio2 is already a great success, even before it was released! You should not hesitate to try it if you love to listen to music!
Thanks for the hard work Volumio-Team!
