R16+ and CentOS 6.4

Because of disabled cipher suite, currently it’s not possible to compile Erlang R16 under CentOS 6.4 with up-to-date OpenSSL (1.0.1e-16.el6_5.7). The solution can already be found on erlang-questions but I thought it might be useful to store it somewhere else too. :)

The symptom of a problem appears when you try to do anything with crypto module:

Unable to load crypto library. Failed with error:
"load_failed, Failed to load NIF library: 'crypto.so: undefined symbol: 
EC_GROUP_new_curve_GF2m'"

To solve it, recompiling OTP is necessary with new environment variable set during configuration phase:

CFLAGS="-DOPENSSL_NO_EC=1 -O2 -g" ./configure

Worked for me with R16B03-1. :) I don’t know if the problem still occurs with R17.

Edit: I forgot that setting CFLAGS overrides default -O2 -g used for OTP compilation. Fixed above. ;)

Posted in Development, Erlang | Tagged , , , | Leave a comment

Mnesia migration from noname node

We have a task of complete rewrite of an old system and as you might guess, one of the challenges awaiting us is database migration. This means double challenge, since we’re not only migrating to new, heavily changed schema, but also from Mnesia to PostgreSQL.

Unfortunately the legacy node has been running Mnesia for ages without any node name, so at first the only easy approach I could think of was using mnesia:dump_to_textfile/1 but I’m afraid it is broken in some way or existing DB is really crappy because I couldn’t get it to export all data. :)

OK, so perhaps load Mnesia data to named node, setup Mnesia cluster and then migrate data? Nope, tables are displayed as “remote” and I couldn’t find the way to modify node name in Mnesia schema files.

You might consider it a messy solution but I decided to first start noname node and then use this nice command:

net_kernel:start(['newname@host', shortnames]).

And there you go! Now you have named node, with which you can connect in Erlang way. :) Sadly this breaks Mnesia, so we are going to exploit the fact, that non-disk_copy_only tables are kept in ets. With RPC call from node doing the migration we can get all the data and save it in PostgreSQL:

rpc:call('newname@host', ets, tab2list, [table])

Of course it probably won’t work too well with high amounts of data but in our case the largest table has less than 1000 records, so I don’t worry about performance here.

BTW: I haven’t tested migration script yet. :) RPC call works though and returns correct set of data from legacy node. :)

Posted in Databases, Development, Erlang | Tagged , , , | 2 Comments

How to run a system command in Erlang?

piotrnosekpl:

I found this blog post very useful, as I needed a way of calling ejabberdctl script from Common Test case and checking the return code of the command. os:cmd/1 is not good enough, as it returns only standard output, not the code.

Originally posted on Piotr Gabryanczyk's Blog:

Problem

I would like to be able to run ie. ls -al / from erlang and process the results using erlang. ie.

Files = cmd:run("ls -al /").

Solution

-module(cmd).
-export([run/1, run/2, test/0]).

run(Cmd) -> 
	run(Cmd, 5000).
	
run(Cmd, Timeout) ->
	Port = erlang:open_port({spawn, Cmd},[exit_status]),
	loop(Port,[], Timeout).
	
loop(Port, Data, Timeout) ->
	receive
		{Port, {data, NewData}} -> loop(Port, Data++NewData, Timeout);
		{Port, {exit_status, 0}} -> Data;
		{Port, {exit_status, S}} -> throw({commandfailed, S})
	after Timeout ->
		throw(timeout)
	end.

test() -> 
	shouldReturnCommandResult(),
	shouldThrowAfterTimeout(),
	shouldThrowIfCmdFailed(),
	{ok, "Tests PASSED"}.

shouldReturnCommandResult() ->
	"Hello\n" = run("echo Hello").

shouldThrowAfterTimeout()->
	timeout = (catch run("sleep 10", 20)).
	
shouldThrowIfCmdFailed()->
		{commandfailed, _} = (catch run("wrongcommand")),
		{commandfailed, _} = (catch run("ls nonexistingfile")).

View original

Posted in Development, Erlang | Tagged , , , | Leave a comment

KnockoutJS: making JavaScript a bit less crappy

If you are JavaScript fan, let me explain myself before you tie me to the pole in the middle of stack and start the fire. I just rather don’t feel this language. Perhaps if I had to write more projects in it and familiarize more with various libraries, my opinion would be more neutral but well… I’m just too tainted by Erlang. Imagine my frustration when I was looking for some bug in the JS code, which was caused by lack of “return” before expression at the end of function definition. I just got too much used to thinking that whatever I write as last expression of the function, it will be returned without some “return” keyword.

Those who know me, already guessed I’m writing about my experiences with implementing Erlang Central Cafe. First version was an effect of cooperation with Stefan Strigler. Do I have to mention that after about two-year break in JavaScript programming and zero knowledge of Google Closure library I virtually crippled Stefan’s code. :) It worked but I was bit ashamed of how it looked internally. :) Finally I made a decision: full rewrite using KnockoutJS!

With somewhat different set of requirements than at the beginning of the project, I could create quite different class hierarchy with clear Model-View-Controller separation. Since we are going to open the source code sooner or later, I tried to make it as generic as possible – so other developers will be able to put their own chat solution together with connection and room controllers, models and views. When I thought of implementing models and views I instantly remembered a project where I used KnockoutJS. It was a bit less then two years ago and back then the library managed modal window display for user registration/login. Even though it was still JavaScript, it was a really cool experience.

KnockoutJS has excellent tutorials, which makes you want to try all these nice tricks in your application. For those who don’t know this library yet: It allows you to create objects in your model called “observables”. Whenever they are updated, KO will automatically modify the view. All you need is to declare bindings in your views like <span data-bind="text: firstName" />. You have a really wide range of bindings to choose from and if you need something really strange – you can write your own binding!

I want to share with you some tricks/caveats, so you will be able to save time I had to spend at some point. :) From now on I will assume you already have done KnockoutJS tutorials and know the basics.

Apply bindings to specific node
It is a bit hidden in documentation, because the official way of applying bindings is to invoke ko.applyBindings(myViewModel); to apply the model to whole document. If you want better control of what is applied where, use ko.applyBindingsToDescendants(model, domElement);. It will bind data only to descendants of domElement, which may be for example obtained with jQuery.

Scroll window to bottom after view update, a.k.a. call function after view update
Unfortunately for this one you have to use template functionality, because only with them you can use “afterRender” property, where you can specify callback to be executed after the update. You can also subscribe to observable change event but here is a trap! The function subscribed to the observable will be invoked before the rendering, so it is not possible to keep window scrolled to the bottom after new message arrives (you can imagine it is quite important in chat application :)). The binding is following: data-bind="template: { name: getMsgTmpl, foreach: messages, afterRender: afterRenderCb }". See the getMsgTmpl? Read below.

Dynamically choose template for binding
You don’t have to provide specific template name in the binding. It can be also a function name and this function can return template name. In Erlang Central Cafe it is used for choosing which of the following templates use: user message, room message or “GUI message” (the info about external Jabber clients is a GUI message).

Snippet for scrolling window to bottom
First of all you have to detect if the view is scrolled before the update, so we won’t annoy the user, who wanted to see earlier messages intentionally. This is where observables subscription is useful:

this.messages.subscribe(function(newVal) {
    var el = self.view.logElement();
    self.isScrolledToBottom = (el.scrollTop == el.scrollHeight - el.clientHeight);
});

And here is the scrolling function:

mongoosechat.view.ChatBox.prototype.scrollToBottom = function(checkIfBottom) {
    var box = $(this.uiChatboxLog);
    box.scrollTop(box[0].scrollHeight+100);
};

If KnockoutJS was a human being, I would kiss him/her/it. It was an amazing relief to forget about appending DOM nodes to chat log and worrying if correct values are displayed. Now it’s transparent and required me to spend only a few hours of learning the library. I remember someone saying (regarding garbage collection) that there are people who consider memory management too important to leave it to computer. But the truth is, memory management is so vital, we can’t leave it to human (right, C/C++ developers?).
I could paraphrase it today: Displaying view is so vital and prone to errors, we can’t just let human being do all the updates manually. Praise KnockoutJS for returning part of my faith in JavaScript. :)

Posted in Development, Webdevelopment, XMPP | Tagged , , , | Leave a comment

Groupchat for Your WordPress website

Hello kids, in this episode of Sesame Street we learn the letters ‘M’ for MongooseIM, ‘G’ for GroupChat and ‘X’ for XMPP. We assume you should already know letters ‘W’ for WordPress and ‘S’ for (My)SQL and you are just looking for a method to embed a groupchat on your website.

Sure, there are many WordPress plugins for doing this but the ones that allow you to choose your own Jabber server are usually paid or simply don’t match your concept. You can benefit from this tutorial in two ways:

  1. You already have a chat plugin but you’d like to host your own Jabber server for better control.
  2. You have some programming skills and you need a guide on how to integrate your custom solution with Jabber.

In first case, you’d probably be limited to plain old username/password authentication unless you have some really cool plugin that integrates with your site’s sessions. In second case you’ll be able to create a really nice integration but you will need at least moderate knowledge of JavaScript, PHP and CSS is required.

This tutorial assumes you have no previous knowledge of XMPP and Erlang. Of course it’s always better to know at least some basics but don’t worry – you can make it. :) Also you need to be quite comfortable with Linux console and basic administrative tasks.

Preparing the server

For our setup, we’ll use MongooseIM, which is an ejabberd server fork we developed at Erlang Solutions. The recently released version (1.2.2) doesn’t have a WordPress plugin yet (most probably it will be included in next release) so we’ll need to build MongooseIM from sources. Instructions below are for Fedora 17; They should be similar for any RedHat-based Linux. For Debian/Ubuntu you’ll need to install equivalents of yum’s packages.

OK, I assume you already have WordPress installed and MySQL database created. Important: Auth plugin assumes that your WordPress tables have wp_ prefix!
Now, follow these steps:

  1. Install Erlang using the instructions from Erlang Solutions website.
  2. Install essential packages & tools:
    # yum install git gcc expat-devel openssl-devel pam-devel
  3. Checkout MongooseIM repo:
    git clone git://github.com/esl/ejabberd.git
    and enter ejabberd directory.
  4. Checkout WordPress branch:
    git checkout wordpress
  5. Edit rel/vars.config and adjust following parameters:
    • hosts: can by anything but most convenient would be the same domain as your website has
    • odbc_server: remove %% at the beginning and enter your WordPress database config; it is recommended to create separate user just for MongooseIM and limit its privileges to read-only, but using the same account both for WordPress and Jabber will work just fine
    • auth_method: set it to [wordpress, internal] or [wordpress, anonymous, internal], should you need to allow guests to access the chat
    • wp_logged_in_key, wp_logged_in_salt: enter exactly the same values as you’ve entered in wp-config.php
  6. Execute make rel and wait… :)
  7. Now in folder rel/ejabberd you have a standalone MongooseIM instance ready to be used with both ordinary Jabber clients, Websockets or BOSH (AJAX calls encapsulating Jabber requests); you can move this folder anywhere you want and start it with any user
  8. You can start the server with rel/ejabberd/bin/ejabberd start and stop with rel/ejabberd/bin/ejabberd stop

What about SSL?

Adding SSL support requires some additional steps. Let’s say you have your certificate already or use steps 1-4 from this site to create self-signed one. You’ll need to prepare three files (all in PEM format):

  • with both private key certificate; if you used tutorial above, do
    cat server.crt server.key > server.pem
    Private key in this file must not be protected by password
  • with private key only (server.key)
  • with certificate only (server.crt)

You may keep them anywhere you want, as long as the user running MongooseIM has read privileges for them. Now we start with editing rel/vars.config:

  • tls_config: remove %% at the beginning and set path to the file with both private key and certificate
  • wss_config: remove %% (don’t remove the comma, it’s there on purpose!) and enter paths to the files plus key password

BOSH doesn’t support SSL connections yet, so above configuration is for ordinary Jabber connection and Websockets.

And it’s done! Now you can execute make rel again to rebuild the release. If you get following error during rebuild:

ERROR: Failed to generate target from spec: "copy file /usr/lib/
    erlang/erts-5.9.3.1/bin/epmd -> /home/mongoose/ejabberd/rel/
    ejabberd/erts-5.9.3.1/bin/epmd: text file or pseudo-device busy\n"
ERROR: Unexpected error: rebar_abort
ERROR: generate failed while processing /home/mongoose/ejabberd/rel:
    rebar_abort

just execute killall epmd and don’t worry. :)

Here are ports used by MongooseIM. You might need them for configuring your client and firewall.
Ordinary Jabber: 5222
BOSH: 5280
Websockets: 5288
Websockets Secure: 5289

Creating rooms

The easiest way to manage rooms is to use ordinary Jabber client to connect to the server. My personal choice for development is Psi, as it comes with good XML Console but any other will also do the trick.

  1. Install Psi client. Assuming you’re using some graphical environment on your Fedora box:
    # yum install psi
  2. On first launch Psi will ask you if you want to create an account. Choose option for existing account.
  3. If such startup window didn’t pop up, navigate to General->Account Setup and press Add
  4. Call your new account whatever you like, for example “Site Admin”
  5. Your Jabber ID is [Wordpress admin username]@[XMPP domain], e.g. admin@localhost
  6. Your Password is the same as you use for WordPress account
  7. If you haven’t enabled SSL in MongooseIM config, switch to Connection tab and in Allow plaintext authentication select Always
  8. Now go online and after Psi connects, select General->Join Groupchat
  9. Your Host is muc.[XMPP domain], e.g. muc.localhost
  10. Choose any room name and nickname you like and click Join
  11. In new window click a button with an arrow pointing down (it’s in upper right corner) and select Configure Room
  12. Switch to General tab. Most default settings are nice enough but it’s important to Make room persistent and set some room title. Then click Apply and Close

Repeat above steps with joining a room and configuring it for every room you’d like to be available for your users. There you go! Now the only thing left is to configure web client…

Client-side configuration

Connecting with ordinary Jabber client is easy. Enter username, domain, password and you’re there. But what if we would like to integrate chat with WordPress (or any other CMS/MVC framework) session system?

Good news: we can use “logged in” cookie! The name is wordpress_logged_in_[site name hash here]. The bad news is, it’s HttpOnly cookie, so it cannot be accessed via JavaScript. This means a bit of coding in PHP. We will create our example using MUCkl, which you can obviously customize to match your site look and feel. It is not a very active project but modifying it is quite simple, so it’s good learning material. :)

  1. Clone MUCkl repository (original software created by Stefan Strigler, my fork modified it a bit for sake of this tutorial):
    git clone git://github.com/fenek/MUCkl.git
  2. Clone JSJaC repository:
    git clone git://github.com/sstrigler/JSJaC.git
  3. Enter JSJaC directory and just run make
  4. Copy jsjac.js to [MUCkl dir]/lib/jsjac/
  5. Enter MUCkl directory and create config file:
    cp config.js.example config.js
  6. Edit configuration:
    • BACKENDTYPE: set it to binding if you’d like to have the same chat open across multiple pages or websockets if your groupchat is designed to be unique for specific page (e.g. discussion under video stream) and you don’t care if users of some browsers won’t be able to use your chat.
    • HTTPBASE: should be http://your.host.name:5280/http-bind/ or if you’ve chosen to use Websockets: ws://your.host.name:5288/ws-xmpp (should begin with wss:// if you configured SSL)
    • XMPPDOMAIN: set it to the same value as you’ve entered in hosts in vars.config
    • AUTHTYPE: set it to sasl if you want to login with username and password or saslanon for anonymous authentication; you can also make the value generated by PHP based on user status:
      <?php
      global $user_login;
      
      if($user_login == '')
        $authtype = 'saslanon';
      else
        $authtype = 'sasl';
      ?>
      
      var AUTHTYPE='<?php echo $authtype; ?>';
    • MUCKLJID, MUCKLPASS: if you’re using saslanon authentication, you don’t need to bother with it; you can hardcode this parameter but the best solution is to generate values (again) with PHP:
      <?php
      global $user_login;
      ?>
      var MUCKLJID='<?php echo $user_login; ?>';
      var MUCKLPASS='<?php echo $_COOKIE["wordpress_logged_in_"
                                     .COOKIEHASH; ?>';
    • Add MUCKLNICK below MUCKLPASS: this will be specific user’s nick in rooms; You can always set it to:
      var MUCKLNICK = MUCKLJID;
    • ROOMS: Using the template in config file, create a list of rooms to which your users will be able to connect; default server for your setup is muc.[xmpp_domain]
  7. Done! If you chose to use some PHP, follow steps below. If not, you can open muckl.html in your browser and enjoy your chat. :)
  8. Easiest way of embedding the groupchat in WordPress page is to insert iframe into post/page content:
    <iframe style="display: block; width: 966px; height: 400px;"
                    src="http://path/to/your/MUCkl/muckl.html?room=[room ID]">

    where [room ID] is the sequence number of room entry in config.js starting at 0; if you want to allow users to choose room, just skip ?room= in URL

What if I used PHP in config file?

  1. First of all, you need to rename config.js to config.js.php
  2. Replace old config file name in index.html:8, muckl.html:9 and groupchat.html:9
  3. At the beginning of config.js.php add:
    <?php
    include_once '../wp-config.php';
    include_once '../wp-includes/pluggable.php';
    include_once '../wp-includes/default-constants.php';
    ?>
  4. Copy MUCkl folder into WordPress root dir

Conclusion

That’s all. Maybe it’s not a short process but unfortunately custom solutions always cost more time than generic ones. This is not the last post about MongooseIM & Web integration. Next one will describe some more advanced aspects of configuration and another will cover WordPress plugin still under development, which you may observe already as Erlang Central Cafe chatbox.

The only downside of the current wordpress branch is that the groupchat module there is experimental and even though it passes unit tests, it is still not considered stable yet. The “experimental” part is possibility of single user joining room from multiple tabs but with the same nick. Original groupchat module doesn’t allow such behaviour and as you might guess – it is quite vital.

Have a nice programming session! ;)

Posted in Erlang, MongooseIM, XMPP | Tagged , , , , | 2 Comments

Erlang Factory is coming.

Finally! My first talk submitted and accepted for Erlang Factory. Perhaps it’s a bit strange that I’m going to Budapest instead of presenting something during Krakow Erlang Factory Lite but the reason is simple: the topic of my talk matured after SF Bay Factory and now I have more information than it is possible to incude in 20-30 minutes of presentation.

What is this topic actually? Well, you can read most important info in Erlang Factory page. Obviously the talk would be based on my experiences with Erlang Central chats. My previous post gave you a general idea what it takes to tap into WordPress session. The main objective now is to (after I get green light) open source of WordPress integration, so everyone could benefit from MongooseIM flexibility. When this happens, I’m going to create some detailed tutorials here on the easy and pleasant integration. I guess you can imagine such stuff would be difficult to compress into relatively short slideshow. If I had about 60 minutes, I’d probably risk live demo, but as many people already know – live demos during conferences always go wrong. More than 5 years ago it was physics contest when transistors in my device were fried by colleague’s experiment emitting EMPs. :) Year ago it was Erlang User Group meeting when I by accident used R12B-5 for compiling project designed for R15. :) So I can seriously suspect that live demos done by me are cursed.

Most probably the conference will be streamed over the Internet (check erlangcentral.org on May 30th!) Unfortunately this conference won’t be streamed over the Internet :( but of course I invite you to join us in Budapest. :)

Posted in Development, Erlang, XMPP | Tagged , , | 2 Comments

WordPress, MongooseIM and Websocket-based chat

Yeah, it’s almost certain that someone will say that this post is just a one, big MongooseIM advertisement. Maybe in small part it is, but my main goal here is to not let my effort remain undocumented. Yes, it’s been quite a challenging task to tap into WordPress session, in order to use it in MongooseIM.

But first things first. Have you already visited Erlang Central? Last Thursday & Friday we had an occasion to give new feature a test drive, which is/was Erlang Factory live streaming. San Francisco Erlang Factory, to be more precise. When you open streaming subpage (“Erlang Factory Live”), you can see the chat below streaming window (obviously stream is inactive now). It is embedded, quite heavily modified version of MUCkl Jabber client designed for group chats. Original version features status changing, list of all participants, choosing nick and combo box with rooms to choose. All of these were removed due to concept of one room per WordPress page (which means removing combo box), automatic user login (don’t need to ask for nick), and focusing only on what people say, not who is logged in (no roster frame -> no use for status changing).

JavaScript and HTML were the easy part – remove few lines here and there and there you go – simpler, nice client. But what about automatic login?

I decided it would be a quite messy solution to write some PHP script and make MongooseIM use it as external authentication option. I wanted native support for WordPress session in Jabber server. The first natural step was to check what cookie contains session data in case of wordpress. It is wp_logged_in_[site name hash] and consists of following parts:
user_name:cookie_expiration_time:session_id
First one is obvious. Second one is the cookie expiration time in form of Unix timestamp. The third one is created as combination of user name, expiration date and user password. Yes, session cookie in WordPress is pretty deterministic, no random numbers. It wasn’t easy though to reconstruct PHP functions in Erlang. Here are the steps used to generate logged_in cookie:

  1. Get user password from DB (in its hashed string form, no processing needed)
  2. Get characters 9-12 from password
  3. Create HMAC key from concatenating WordPress logged in key & salt
  4. Data for HMAC is concatenation of: username, password fragment, ‘|’, expiration time in string form
  5. Do md5 HMAC with key from 3. on data from 4.
  6. Convert result from 5. to hexadecimal, string representation of hash (remember about zero-padding bytes lesser than 16)
  7. Do md5 HMAC with 6 as a key and concatenation of username, ‘|’ and expiration in string form as data
  8. There you go! Just convert the result to hexadecimal string and you can compare it with cookie

Sounds simple, right? It wasn’t. It wasn’t difficult either, just required some guessing and executing PHP code to figure out how it represents data in all intermediate steps.

No, it’s not over. We embedded MUCkl as iframe in WordPress page, since we didn’t have enough time to properly integrate it with all the JavaScript WordPress has inside. Too great risk of some conflicts.We put it also in different domain (stream.erlang-solutions.com), so it forced me to create some hack to pass logged_in cookie to MUCkl page. JavaScript was a dead end – this cookie is HttpOnly, meaning it can’t be accessed by scripts running in the page. The solution was to create small redirect page within erlangcentral.org domain to just read cookie and pass it further as HTTP parameter to MUCkl. Done! MUCkl just had to pass cookie value as user password to MongooseIM and custom ejabberd_auth checked it against algorithm described earlier. That’s how current solution works.

As a conclusion I would like to state that if not for complicated WordPress cookie creation, incorporating multi-user chat in own website with MongooseIM is a very pleasant stuff. Traffic was not that high last weekend but good performance and stability of such combination is one step more towards sending BOSH to (un)deserved retirement. Especially given that all modern browsers support Websockets, even the mobile ones.

Posted in Erlang | Tagged , , , , | 1 Comment

Load testing with Tsung

Please note that this post is based on experiences with Tsung version from (about) November 2012. As far as I can see, most commits added since then are bugfixes or minor changes. Perhaps one of them would make some conclusions different, but no one says that everybody always uses most recent code from Github. :)

For those who are not yet aware what Tsung is: It is a load-testing framework developed in Erlang by ProcessOne along with community (and my small input for Websockets ;)). I used it only for ejabberd testing so I have no opinion on other protocols support than Jabber via TCP/BOSH/Websockets.

Yeah, multiple protocols support. This definitely sounds nice. Unfortunately it enforces some architectural solutions, which can make writing scenarios maybe not hard but sometimes troublesome.

In general, things I don’t like are:

Redundancy in scenario XML
Even if you specify session type as Jabber, you also have to use <jabber> nodes for issuing commands like connect or send message.

Inconsistent protocol options
For example: it took me some time to discover that BOSH doesn’t support plaintext authentication, as opposed to direct TCP one or Websockets. One might ask why I even bothered with plaintext. The answer is: At the beginning I couldn’t find valid nodes sequence for SASL authentication. It’s really not that obvious:

<request><jabber type="auth_sasl" ack="local" /></request>
<request><jabber type="connect" ack="local" /></request>
<request><jabber type="auth_sasl_bind" ack="local" /></request>
<request><jabber type="auth_sasl_session" ack="local" /></request>

What is more, I don’t know why plaintext auth is even allowed, since Tsung by default sets XML stream version to 1.0 and it causes server to deny this method.

Too large overhead when sending messages
Nothing extraordinary: I would like every client to send a message to any other online client. Of course it’s possible but the CPU load on controller node suggests it is queried by every client for random online JID. I would like to set that they can assume every client with JID number lower than own one. Indeed I used scenarios divided in two phases (not to be mistaken for arrival phases): connecting all users and message exchange and in such case online JID is any JID.

Global ACK sucks
Any request can have three types of acknowledgements:

  • none – will just continue to next command
  • local – will continue after receiving any response from server
  • global – will synchronize all clients at this point in scenario

Ejabberd and MongooseIM can take a lot of users before running out of resources. This means creating *many* client instances and imagine e.g. 100k instances trying to synchronize with each other at the same time. I’ll make it easier: 100Mbps network had a hard time processing this load.
The practical solutions in some scenarios is to set thinktime for each client equal to estimated time of whole login phase or use dynamic variables to set thinktime in more adaptive way.

Who cares if users really connected
I think intuition suggests that when load testing suite fails to connect a user, it should be screaming that something’s wrong. At least it should be the default behaviour. Of course in case of Tsung you have to check session count inside server to make sure that these amazing results you’re getting are not caused by half of users never starting a valid session.

Latency measurement
In general: it’s not realiable when Tsung nodes become heavily loaded. I can understand it, of course. The thing is, I was’t particularly happy with using another Erlang node running custom code just for pinging two clients and checking latencies.

A lot of “manufacture” when using more than one network interface
Good thing is that Tsung nodes allow usage of more than one interface (Kernel bless the quite low limit on port number range per interface…). Less nice is that for each client you have to precisely specify IP of every interface you’d like to use. I think the most preferable solution would be to specify subnet and have nodes use all interfaces that have IP in this subnet.

Please do not think I hate this tool. It was very helpful:

Very good monitoring
Built-in monitoring (except for latency measurement) provides wide range of various parameters, of which for me the most helpful were CPU & RAM usage and request rate. Since gnuplot is used for creating graphs, Tsung creates a lot of gnuplot-friendly data files you can use to create your own images. Actually, I usually opened mentioned graphs in Eye of Gnome and had them constantly updated by watchn executing tsung_stats.pl.

Is stable
Actually I never experienced a sudden crash e.g. after an hour of running the load test. When something went wrong, it wasn’t because of some bug in the core code.

Distributes well
Sometimes it requires more processing power to generate the load than handle it. Tsung was perfectly able to manage 10 nodes.

Does its job
When i dealt with the issues described earlier, Tsung eventually proved to be a good tool. It has many configuration options and since it is written in Erlang, it wasn’t hard to adjust some aspects in the source code. It is fairly easy to use, with some nice sample scenarios publicly available. After initial setup performing tests themselves was quite pleasant.

Would I ever use it again? Probably yes. I have the scenario- and knowledgebase that would allow me to skip the initial difficulties. On the other hand I would certainly welcome similar project dedicated for XMPP with friendly learning curve.

Posted in Development, Erlang | Tagged , , , | 2 Comments

Thoughts on IKM Assessment

Not so long ago I had an occasion to take a test created by IKM. I’m not sure if it’s a very common way to assess programming skills but certainly the process itself looks interesting. Sadly, it seems they don’t have Erlang suite but as I developed a few things in C++ and Java before I learnt Erlang, I thought “why not?” and decided to check how much I have forgotten and how much still lingers in my skull after 2-3 years.

I have to admit – at the beginning I wasn’t sure what to expect. I was told just “IKM”, of what I’ve never heard earlier. I was wondering whether will it be problem solving, knowledge of the language core or some fancy libraries? It turned out it was the second option with a bit of the third one. I was a bit disappointed, since language is a tool (of course it is important to know your tool!) but what use is of a developer who kicks ass in C/Java/Erlang/etc. and is unable to understand the project as a whole or design a simple state machine and is just programming robot?

Anyway, probably problem solving is a difficult class of skills to be judged by computer algorithm. The tests in case of both languages consist of questions checking the understanding of language mechanisms plus some aspects from core libraries like java.io or STL. The libraries were the most difficult part for me, since I always had a problem with remembering all these BufferedFileWriterReaderShredderDiaperChanger classes (e.g. it took me a really long time to remember argument order for lists:foldl/3 :)). There were some tricky questions where I was asked for a predicted result of executing the snippet and there was just one semicolon missing or lack of int in front of function declaration. I especially liked the question about finalize method in Java; I still remembered it is not guaranteed for it to be called ever. :) The frustrating one was about diamond inheritance in C++. I’ve used it once about 10 years ago when I was learning C++ and still knew the concept but even with utmost effort I couldn’t recall the correct syntax for it.

The creators of the test algorithm state that the software can adjust questions difficulty so to the assessed folk the questions will always seem challenging but not impossible. I must admit this is true. There were few questions I could answer without hesitation but I also haven’t utterly failed the rest.
I haven’t mentioned it’s a multiple choice test and bad answers lower your final score. This means sometimes it’s just better to skip the question than pick random answers (and so did I in a few cases). Answers are weighted, which means some correct ones are more obvious than others, which means less points for them. The same goes for wrong ones – completely stupid option means a considerable loss of points.

In general, both Java and C++ tests took about 1 hour each and I got about 80% in both. Perhaps for someone it would be a complete failure but given my long break and using mostly Erlang on daily basis, I’m very pleased with such results. I clearly forgot java.io, never learnt STL too well but at least my results on core language mechanisms are more than average.

… and yes, I decided to be fair and didn’t have any handbook on my desk or Google opened on laptop. Most of all, I was curious and eager to try my actual knowledge. I didn’t care about getting 100% result. I even dared to have a beer when I had only a handful of questions left. :)

In overall, I consider it a nice experience. I understand, that for an average company it is a good way to judge if the candidate has certain skills without spending a lot of time on “manually” checking everyone. The big mistake that some probably make, is relying only on this tool or treating it as basic sieve. It’s good that final report actually divides the questions in certain classes like “memory management” or “Java IO”, so someone who understands memory management in C++, won’t be at much disadvantage because of poor skill in STL.

… but the best assessment ever will always be:

‘Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.’

(Ref.: CodingHorror and Imran on Tech)

Posted in Development | Tagged , | 7 Comments

Board generation for CitadErl

When playing Citadel of Blood, it seemed to be quite trivial to just pick random pieces and check if they match existing board. Maybe checking adjacent fields is easy for computer but there are certain conditions where more distant blocks can determine what kinds of corridors should the new piece have. This is a problem to be solved later, for now I decided to stick to (almost) basic pieces generation.

I thought it would be best to avoid completely random generation and checking the new field against conditions. Maybe it is quite unlikely but in theory very specific requirements could lead to very long generation. Taking conditions into consideration at the very beginning leads to a more complicated and maybe less efficient code but the generation time won’t extend significantly. Of course without proper benchmarks it is difficult to tell. :)

What generation function needs is a list of limits. For now it is a piece type (corridor/room) and a minimal counts for: any, “wide” and “narrow” passages. Wide passages are ordinary corridors and narrow are doorways usually leading to rooms. If no min. values are specified, any passage (or none) is added in every direction. I know that I have to prevent adding wide passages to rooms. :) If specific passages are defined, they are inserted in random nth free spot in passages list.

Thinking about potential algorithm for limits definition, led me to a conclusion that two conditions will/could be also necessary:

  • Piece must have adjacent/opposite passages of specific/any type
  • Piece musn’t have more than X passages of specific type

Perhaps condition list will grow so much, it will eventually become more efficient to just rely on brute-force generation from certain point?

For a moment I was tempted by complete board generation when the game starts but there is one rule in Citadel of Blood that makes it impossible: “When a piece can be inserted in many ways, it is up to players to choose the rotation they want.” Maybe I described CitadErl as “inspired by Citadel of Blood”, but this is a nice feature to have and by inspiration I rather meant creating a modular server which rules can be later extended or removed at developer’s will.

So, this is some start. What will come next? Well, I intend to improve monster generation (now it’s a bit bugged and incomplete) and dungeon level modifiers. Code should also have function specs included and more comments butI wanted so badly to commit something that works, I forgot about such details this time. ;)

I am aware that not much was done since I announced the project but lack of time is quite common in case of hobby projects. :(

Posted in CitadErl, Erlang | Tagged , , | Leave a comment