KDE PIM/Akonadi/Development Tools: Difference between revisions

    From KDE TechBase
    (17 intermediate revisions by 5 users not shown)
    Line 62: Line 62:


    The database console enables developers to directly send commands to the database engine.
    The database console enables developers to directly send commands to the database engine.
    === Access to the Server Database with mysql ===
    Alternative for the one who can formulate the SQL commands. Use directly the mysql command with the socket:
    Let say the username is "user" and the hostname is "falun".
    <syntaxhighlight lang="text">
    $ mysql --socket=/home/user/.local/share/akonadi/socket-falun/mysql.socket
    </syntaxhighlight>
    You get the same answers from the server:
    <syntaxhighlight lang="text">
    mysql> use akonadi;
    ...
    mysql> select * from  collectionattributetable;
    +----+--------------+----------------------------+-----------------------------------------------+
    | id | collectionId | type                      | value                                        |
    +----+--------------+----------------------------+-----------------------------------------------+
    |  5 |            4 | ENTITYDISPLAY              | ("std.ics" "office-calendar")                |
    |  6 |            4 | AccessRights              | wcdW                                          |
    |  9 |            6 | AccessRights              | a                                            |
    | 15 |            9 | ENTITYDISPLAY              | ("Personal Calendar" "office-calendar" "" ()) |
    | 16 |            9 | AccessRights              | wcdW                                          |
    | 17 |          10 | AccessRights              | wcdC                                          |
    | 18 |          10 | SpecialCollectionAttribute | local-mail                                    |
    | 19 |          10 | ENTITYDISPLAY              | ("Local Folders" "folder" "" ())              |
    | 20 |          11 | SpecialCollectionAttribute | outbox                                        |
    | 21 |          11 | ENTITYDISPLAY              | ("outbox" "mail-folder-outbox" "" ())        |
    +----+--------------+----------------------------+-----------------------------------------------+
    10 rows in set (0.00 sec)
    </syntaxhighlight>
    === Access to the Server Database with phpMyAdmin ===
    You can also use a HTTP-server (apache) and phpMyAdmin. This gives you a quick overview from all the data, but phpMyAdmin cannot decode the data as well as akonadi console.
    First, the phpMyAdmin config file as to be changed. This only works for *ONE* user at a time. The config file is:
    <syntaxhighlight lang="text">
    <directory_of_http>/phpMyAdmin/config.inc.php
    </syntaxhighlight>
    Here the important lines:
    <syntaxhighlight lang="text">
    /* Server: localhost [1] */
    $i++;
    $cfg['Servers'][$i]['verbose'] = 'akonadi';
    $cfg['Servers'][$i]['socket'] = '/home/user/.local/share/akonadi/socke-falun/mysql.socket';
    $cfg['Servers'][$i]['connect_type'] = 'socket';
    $cfg['Servers'][$i]['extension'] = 'mysql';
    $cfg['Servers'][$i]['auth_type'] = 'config';
    $cfg['Servers'][$i]['user'] = 'user';
    $cfg['Servers'][$i]['password'] = '';
    $cfg['Servers'][$i]['nopassword'] = true;
    $cfg['Servers'][$i]['AllowNoPassword'] = true;
    </syntaxhighlight>
    The http process runs under another user as *you*. You must give access to the socket:
    <syntaxhighlight lang="text">
    $ chmod o+x /tmp/akonadi-user.MSQm6h
    $ ls -ld /tmp/akonadi-user.MSQm6h
    drwx-----x 2 user users 4096 May 26 18:50 /tmp/akonadi-user.MSQm6h
    </syntaxhighlight>
    With your browser you can now type the URL
    <syntaxhighlight lang="text">
    http://localhost/phpMyAdmin/
    </syntaxhighlight>
    and get access to the same data:
    [[Image:Akonadi-phpMyAdmin.png]]


    = Debugging Akonadi Agents =
    = Debugging Akonadi Agents =
    Line 70: Line 135:


    Export the environment variable '''AKONADI_DEBUG_WAIT''' and put the agent type in there you want to debug. You only need to specify a part of the agent type, not the whole one. Example:
    Export the environment variable '''AKONADI_DEBUG_WAIT''' and put the agent type in there you want to debug. You only need to specify a part of the agent type, not the whole one. Example:
    <code>
    <syntaxhighlight lang="text">
    export AKONADI_DEBUG_WAIT=knut
    export AKONADI_DEBUG_WAIT=knut
    </code>
    </syntaxhighlight>


    When starting an agent of this type, you'll see the following debug output by the Akonadi server which is pretty much self-explanatory.
    When starting an agent of this type, you'll see the following debug output by the Akonadi server which is pretty much self-explanatory.
    Line 78: Line 143:
    <pre>
    <pre>
    ============================================================
    ============================================================
    ProcessControl: Suspending process akonadi_knut_resouce
    ProcessControl: Suspending process akonadi_knut_resource
    'gdb -pid 1234' to debug
    'gdb -pid 1234' to debug
    'kill -SIGCONT 1234' to continue
    'kill -SIGCONT 1234' to continue
    ============================================================
    ============================================================
    </pre>
    </pre>
    This work only if the process are runing from a console. To check it, type:
    <syntaxhighlight lang="text">
    $ ps -ef | grep akonadi_control
    user      1737    1  0 17:58 ?        00:00:00 /usr/bin/akonadi_control
    </syntaxhighlight>
    The parent process ist 1 (one), the process doesn't run from a console.
    Stop the process, start it again and check:
    <syntaxhighlight lang="text">
    $ akonadictl stop
    $ akonadi_control
    $ ps -ef | grep akonadi_control
    user      1956  1841  2 18:08 pts/2    00:00:00 akonadi_control
    $ lsof -p 1956
    ...
    akonadi_c 1956  user    0u  CHR              136,2      0t0      5 /dev/pts/2
    akonadi_c 1956  user    1u  CHR              136,2      0t0      5 /dev/pts/2
    akonadi_c 1956  user    2u  CHR              136,2      0t0      5 /dev/pts/2
    </syntaxhighlight>
    But you need some time to start a debugger, set some breakpoints and some more actions. The default value of timeout is 150 seconds. If you need some more time, you can export '''AKONADI_DEBUG_TIMEOUT''' with another value, ie. one hour in milliseconds:
    <syntaxhighlight lang="text">
    export AKONADI_DEBUG_TIMEOUT=3600000
    </syntaxhighlight>


    == Running an agent in valgrind ==
    == Running an agent in valgrind ==
    Line 120: Line 207:
    The solution for this is the Akonadi Remote Debugging Server (Akonadi RDS), a small tunnel server that runs next to the Akonadi server. Starting it is trivial:
    The solution for this is the Akonadi Remote Debugging Server (Akonadi RDS), a small tunnel server that runs next to the Akonadi server. Starting it is trivial:


    <code bash>
    <syntaxhighlight lang="bash">
    $ akonadi_rds
    $ akonadi_rds
    </code>
    </syntaxhighlight>


    Now you need to tell your client how to connect to the remote instance. This is done by setting the following environment variables:
    Now you need to tell your client how to connect to the remote instance. This is done by setting the following environment variables:


    <code bash>
    <syntaxhighlight lang="bash">
    $ export AKONADI_SERVER_ADDRESS=tcp:<server ip>,port=31415
    $ export AKONADI_SERVER_ADDRESS=tcp:host=<server ip>,port=31415
    $ export DBUS_SESSION_BUS_ADDRESS=tcp:<server ip>,port=31416
    $ export DBUS_SESSION_BUS_ADDRESS=tcp:host=<server ip>,port=31416
    </code>
    </syntaxhighlight>


    Afterwards, just start your client as usual. Obviously, this is not limited to Akonadi but will just as well work for pure D-Bus connections with any D-Bus client, which can be quite useful by itself already.
    Afterwards, just start your client as usual. Obviously, this is not limited to Akonadi but will just as well work for pure D-Bus connections with any D-Bus client, which can be quite useful by itself already.
    When using akonadiconsole, this can be done even easier by the following command, without the need of setting up the environment variables:
    <syntaxhighlight lang="bash">
    $ akonadiconsole --remote <server ip>
    </syntaxhighlight>


    == Limitations ==
    == Limitations ==


    There are currently a few limitations when using akonadi_rds:
    There are currently a few limitations when using akonadi_rds (which at the same time can be seen as a TODO list ;) ):
    * External payload transfer is not supported. If you use Akonadi server with an enabled FS store, payloads greater than the configured threshold will not be transferred correctly. This is fixable in libakonadi with limited effort.
     
    * Remote access to Nepomuk is not yet support. Effort unknown.
    * External payload transfer is not supported. If you use Akonadi server with an enabled FS store, payloads greater than the configured threshold will not be transferred correctly. This is fixable in libakonadi with limited effort by not requesting external transfer when using TCP transfer.
    * Remote access to the underlying database is not yet support in akonadiconsole. Effort unknown.
    * Remote access to Nepomuk is not yet support. Effort unknown, probably requires tunneling the Nepomuk socket in the same way as we do it for Akonadi and D-Bus, as well as adjustments in the Nepomuk library to support TCP sockets.
    * D-Bus remote connections only work if server and client have the same UID. That for example means to connect to a Maemo5 N900 you need to use UID 29999 on the client. Possible fixes involve D-Bus protocol parsing, ie. unreasonable effort.
    * Remote access to the underlying database is not yet support in akonadiconsole. Should be relatively easy to do for external DB servers which likely can be forwarded in the same way as Akonadi and D-Bus, no idea about Sqlite.
    * '''D-Bus remote connections only work if server and client have the same UID. That for example means to connect to a Maemo5 N900 you need to use UID 29999 on the client.''' Possible fixes involve D-Bus protocol parsing, ie. unreasonable effort.
    * The raw socket console in akonadiconsole does not work yet. Easily fixable by honoring the environment variable.
    * The raw socket console in akonadiconsole does not work yet. Easily fixable by honoring the environment variable.
    * (Re-)Starting Akonadi remotely does not work.


    [[Category:Akonadi]]
    [[Category:Akonadi]]
    [[Category:PIM]]
    [[Category:PIM]]

    Revision as of 16:10, 23 January 2013

    Akonadi Developer Tools

    Akonadi Console

    Akonadi Console is a tool for developers working with Akonadi or on Akonadi itself.

    It provides GUI for

    • managing agents and resources
    • retrieving, checking and even manipulating data
    • monitoring communication between Akonadi server and its clients
    • convenience access to the database used by the server

    Managing Agents

    This facility is basically a GUI for Akonadi::AgentManager and Akonadi::AgentInstance.

    It enables the developer to quickly add or remove agents from the currently running Akonadi system, to check an agent's basic properties and status, etc.

    While most of these actions can also be performed through end user GUI, e.g. KDE's Systemsettings, this is usually quicker and it provides more detailed information.

    Tip
    The Synchronize action menu can be used to just synchronize the collection tree, basically a convenient way for a resource developer to call just the retrieveCollections() method.


    Collections and Items

    This facility shows all Akonadi collections, how they are organized as a tree and their items and enables the developer to perform actions on these entities.

    Developers working on agents can use this perform the most common tasks such as

    • retrieving items: see the context menu of collection entries, basically a call to the respective resource's retrieveItems() method
    • retrieve item payloads: either by clicking on an item or, for certain type such as contacts by switching the item view's mode to the respective data type.
    • copy and delete items: see the context menu of item entries
    • modify items: e.g. by changing the serialized form of the item on the Raw Payload tab

    without having to go through an end user application.

    Developers working on end user applications can use this to simulate respective changes by other clients and to check whether changes done by the application itself are correctly applied to the shared data.

    Tip
    If a newly added resource's collections do not show up in the collection tree, it might be necessary to explicitly synchronize it. This functionality is available on the Agents tab.

    }

    Monitoring Akonadi Communication

    This facility allows to monitor the Akonadi data protocol based communication between client sessions and the server. It contains commands, responses and the data transported between the two sides.

    Note
    Since this can slow down operations it is disabled by default and has to be enabled manually when needed.


    Access to the Server Database

    Akonadi uses a SQL database for keeping relations such as which collection an item is in, properties such as MIME types, etc. as well as cached item payload data.

    Since this is quite internal to the Akonadi server, it will most likely only be interesting to people working on Akonadi, not for developers working with Akonadi.

    The database browser can query and display the database tables used by Akonadi.

    The database console enables developers to directly send commands to the database engine.

    Access to the Server Database with mysql

    Alternative for the one who can formulate the SQL commands. Use directly the mysql command with the socket: Let say the username is "user" and the hostname is "falun".

    $ mysql --socket=/home/user/.local/share/akonadi/socket-falun/mysql.socket
    

    You get the same answers from the server:

    mysql> use akonadi;
    ...
    mysql> select * from  collectionattributetable;
    +----+--------------+----------------------------+-----------------------------------------------+
    | id | collectionId | type                       | value                                         |
    +----+--------------+----------------------------+-----------------------------------------------+
    |  5 |            4 | ENTITYDISPLAY              | ("std.ics" "office-calendar")                 |
    |  6 |            4 | AccessRights               | wcdW                                          |
    |  9 |            6 | AccessRights               | a                                             |
    | 15 |            9 | ENTITYDISPLAY              | ("Personal Calendar" "office-calendar" "" ()) |
    | 16 |            9 | AccessRights               | wcdW                                          |
    | 17 |           10 | AccessRights               | wcdC                                          |
    | 18 |           10 | SpecialCollectionAttribute | local-mail                                    |
    | 19 |           10 | ENTITYDISPLAY              | ("Local Folders" "folder" "" ())              |
    | 20 |           11 | SpecialCollectionAttribute | outbox                                        |
    | 21 |           11 | ENTITYDISPLAY              | ("outbox" "mail-folder-outbox" "" ())         |
    +----+--------------+----------------------------+-----------------------------------------------+
    10 rows in set (0.00 sec)
    

    Access to the Server Database with phpMyAdmin

    You can also use a HTTP-server (apache) and phpMyAdmin. This gives you a quick overview from all the data, but phpMyAdmin cannot decode the data as well as akonadi console. First, the phpMyAdmin config file as to be changed. This only works for *ONE* user at a time. The config file is:

    <directory_of_http>/phpMyAdmin/config.inc.php
    

    Here the important lines:

    /* Server: localhost [1] */
    $i++;
    $cfg['Servers'][$i]['verbose'] = 'akonadi';
    $cfg['Servers'][$i]['socket'] = '/home/user/.local/share/akonadi/socke-falun/mysql.socket';
    $cfg['Servers'][$i]['connect_type'] = 'socket';
    $cfg['Servers'][$i]['extension'] = 'mysql';
    $cfg['Servers'][$i]['auth_type'] = 'config';
    $cfg['Servers'][$i]['user'] = 'user';
    $cfg['Servers'][$i]['password'] = '';
    $cfg['Servers'][$i]['nopassword'] = true;
    $cfg['Servers'][$i]['AllowNoPassword'] = true;
    

    The http process runs under another user as *you*. You must give access to the socket:

    $ chmod o+x /tmp/akonadi-user.MSQm6h
    $ ls -ld /tmp/akonadi-user.MSQm6h
    drwx-----x 2 user users 4096 May 26 18:50 /tmp/akonadi-user.MSQm6h
    

    With your browser you can now type the URL

    http://localhost/phpMyAdmin/
    

    and get access to the same data:

    Debugging Akonadi Agents

    Agents are automatically started by the Akonadi server and thus are not debugable from the start on by the usual methods. A similar problem is known from KIO slaves, the solution is similar as well.

    Attaching gdb at startup

    Export the environment variable AKONADI_DEBUG_WAIT and put the agent type in there you want to debug. You only need to specify a part of the agent type, not the whole one. Example:

    export AKONADI_DEBUG_WAIT=knut
    

    When starting an agent of this type, you'll see the following debug output by the Akonadi server which is pretty much self-explanatory.

    ============================================================
    ProcessControl: Suspending process akonadi_knut_resource
    'gdb -pid 1234' to debug
    'kill -SIGCONT 1234' to continue
    ============================================================
    

    This work only if the process are runing from a console. To check it, type:

    $ ps -ef | grep akonadi_control
    user       1737     1  0 17:58 ?        00:00:00 /usr/bin/akonadi_control
    

    The parent process ist 1 (one), the process doesn't run from a console. Stop the process, start it again and check:

    $ akonadictl stop
    $ akonadi_control
    $ ps -ef | grep akonadi_control
    user       1956  1841  2 18:08 pts/2    00:00:00 akonadi_control
    $ lsof -p 1956
    ...
    akonadi_c 1956  user    0u   CHR              136,2      0t0       5 /dev/pts/2
    akonadi_c 1956  user    1u   CHR              136,2      0t0       5 /dev/pts/2
    akonadi_c 1956  user    2u   CHR              136,2      0t0       5 /dev/pts/2
    

    But you need some time to start a debugger, set some breakpoints and some more actions. The default value of timeout is 150 seconds. If you need some more time, you can export AKONADI_DEBUG_TIMEOUT with another value, ie. one hour in milliseconds:

    export AKONADI_DEBUG_TIMEOUT=3600000
    

    Running an agent in valgrind

    Running an agent in valgrind is done in a similar way, you need to export AKONADI_VALGRIND and put the agent type in there.

    To specify the valgrind tool to use by exporting AKONADI_VALGRIND_SKIN, the default is memcheck.

    Additional config options can be given using AKONADI_VALGRIND_OPTIONS.

    Example:

    valgrind akonadi_cpntacs_resource using memcheck:

    export AKONADI_VALGRIND=akonadi_contacts_resource
    

    To get the name of a resource, open akonadiconsole, select your resource and use the identifier being displayed at the bottom, but stip the _0 or similar from the end.

    Profile the persons resource using callgrind, disabling instrumentation on start for faster startup, and dumping the callgrind output to a custom file:

    export AKONADI_VALGRIND=akonadi_contacts_resource
    export AKONADI_VALGRIND_SKIN=callgrind
    export AKONADI_VALGRIND_OPTIONS="--instr-atstart=no --callgrind-out-file=$HOME/callgrind-vcard.%p"
    

    Akonadi Testing and Benchmark Infrastructure

    The Akonadi Test project provides tools to run Akonadi tests in self-contained environments, i.e. separated from the developer's personal setup, as well as running automated tests, e.g. as part of a unit test suite.

    Remote Debugging

    When running Akonadi on embedded devices or on a non-UI system, it can be useful to connect to it with clients such as akonadiconsole from a remote system. However, the Akonadi server uses local sockets for communication and therefore does not allow this directly. Same for D-Bus, which is essential for Akonadi client-server communication as well as the various debugging features in akonadiconsole.

    The solution for this is the Akonadi Remote Debugging Server (Akonadi RDS), a small tunnel server that runs next to the Akonadi server. Starting it is trivial:

    $ akonadi_rds
    

    Now you need to tell your client how to connect to the remote instance. This is done by setting the following environment variables:

    $ export AKONADI_SERVER_ADDRESS=tcp:host=<server ip>,port=31415
    $ export DBUS_SESSION_BUS_ADDRESS=tcp:host=<server ip>,port=31416
    

    Afterwards, just start your client as usual. Obviously, this is not limited to Akonadi but will just as well work for pure D-Bus connections with any D-Bus client, which can be quite useful by itself already.

    When using akonadiconsole, this can be done even easier by the following command, without the need of setting up the environment variables:

    $ akonadiconsole --remote <server ip>
    

    Limitations

    There are currently a few limitations when using akonadi_rds (which at the same time can be seen as a TODO list ;) ):

    • External payload transfer is not supported. If you use Akonadi server with an enabled FS store, payloads greater than the configured threshold will not be transferred correctly. This is fixable in libakonadi with limited effort by not requesting external transfer when using TCP transfer.
    • Remote access to Nepomuk is not yet support. Effort unknown, probably requires tunneling the Nepomuk socket in the same way as we do it for Akonadi and D-Bus, as well as adjustments in the Nepomuk library to support TCP sockets.
    • Remote access to the underlying database is not yet support in akonadiconsole. Should be relatively easy to do for external DB servers which likely can be forwarded in the same way as Akonadi and D-Bus, no idea about Sqlite.
    • D-Bus remote connections only work if server and client have the same UID. That for example means to connect to a Maemo5 N900 you need to use UID 29999 on the client. Possible fixes involve D-Bus protocol parsing, ie. unreasonable effort.
    • The raw socket console in akonadiconsole does not work yet. Easily fixable by honoring the environment variable.
    • (Re-)Starting Akonadi remotely does not work.