Bug 179006 - akonadi server does not work with afs homes
Summary: akonadi server does not work with afs homes
Status: RESOLVED FIXED
Alias: None
Product: Akonadi
Classification: Frameworks and Libraries
Component: server (show other bugs)
Version: unspecified
Platform: Compiled Sources Linux
: NOR normal
Target Milestone: ---
Assignee: Volker Krause
URL:
Keywords:
: 250107 (view as bug list)
Depends on:
Blocks:
 
Reported: 2008-12-29 00:29 UTC by Andrej Filipcic
Modified: 2011-01-02 15:48 UTC (History)
13 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrej Filipcic 2008-12-29 00:29:41 UTC
Version:           1.0.81 (using Devel)
OS:                Linux
Installed from:    Compiled sources

akonadi server does not start if the home directory is in afs space which does not allow creation of unix sockets (and named pipes). The socket paths in the source are somehow hardcoded to be in ~/.local/share/akonadi/akonadiserver.socket and ~/.local/share/akonadi/db_misc/mysql.socket. Is it possible to move it to /tmp/kde-username or /var/tmp/kdecache-usernameXXXXX?
Comment 1 Juha Tuomala 2009-01-07 13:19:04 UTC
Also note that firefox nor opensync does not work as they try to make pipes into home dir too.
Comment 2 ComputerDruid 2009-04-17 15:49:52 UTC
I saw this today on some afs-homed workstations. Firefox DOES work on these workstations however...

a /tmp/kde-username location as an option would be much appreciated.
Comment 3 Martin Vala 2009-12-02 10:12:56 UTC
i had problem with AFS too,so i did

mkdir -p /tmp/kde-$USER/akonadi
ln -s /tmp/kde-$USER/akonadi/ $HOME/.local/share/

and it worked. But i don't like this solution.

i did it also because i had timeout error when i started clean KDE4 (i cleaned my $HOME/.kde4)

so my solution was to put 

mkdir -p /tmp/kde-$USER/akonadi
ln -s /tmp/kde-$USER/akonadi/ $HOME/.local/share/

in to /etc/kde/startup/agent-startup.sh

(I use gentoo linux)
Comment 4 Martin Vala 2009-12-02 10:14:07 UTC
i had problem with AFS too,so i did

mkdir -p /tmp/kde-$USER/akonadi
ln -s /tmp/kde-$USER/akonadi/ $HOME/.local/share/

and it worked. But i don't like this solution.

i did it also because i had timeout error when i started clean KDE4 (i cleaned my $HOME/.kde4)

so my solution was to put 

mkdir -p /tmp/kde-$USER/akonadi
ln -s /tmp/kde-$USER/akonadi/ $HOME/.local/share/

in to /etc/kde/startup/agent-startup.sh

(I use gentoo linux)
Comment 5 Tobias Koenig 2010-03-16 12:51:38 UTC
Hej,

in the current version of Akonadi server you can specify a custom socket path
by entering

[Connection]
SocketDirectory=/tmp/akonadi-myuser/

into $HOME/.config/akonadi/akonadiserverrc
Comment 6 David Benjamin 2010-03-16 13:58:01 UTC
Could it be set up somehow to be globally configured? I would imagine most deployments of AFS apply to all users (for instance, MIT's Athena system). We would certainly prefer a solution which did not involve customizing a configuration file separately per-user.

What if the string was a template and accepted $USER somewhere? Or perhaps the underlying code could automatically fallback to /tmp/akonadi-$USER when creating the local socket fails.
Comment 7 Rex Dieter 2010-03-16 14:38:23 UTC
Can a solution similar to kde's
~/.kde/socket-<hostname> => /tmp/ksocket-<username>
symlink be used in akonadi too?
Comment 8 Stijn Hoop 2010-03-16 17:05:57 UTC
Same bug as bug 182292 I suppose?

My suggestion on how to fix it is there:

https://bugs.kde.org/show_bug.cgi?id=182292#c6
Comment 9 Wolfgang Scheicher 2010-08-26 13:56:05 UTC
*** This bug has been confirmed by popular vote. ***
Comment 10 David Faure 2010-10-11 14:14:50 UTC
Yes the lnusertemp solution (make symlink if possible, otherwise mkdir) as used by $KDEHOME/ksocket-$HOSTNAME would be better than a configurable path. No configuration needed, it would just work out of the box for all users.

Reopening this one, which IMHO makes 203460 unnecessary.
Comment 11 Tobias Koenig 2010-11-09 23:36:14 UTC
*** Bug 250107 has been marked as a duplicate of this bug. ***
Comment 12 Tobias Koenig 2010-12-06 19:56:07 UTC
commit e4affdfc2922efc10b647939fd4e068c02e256eb
branch master
Author: Tobias Koenig <tokoe@kde.org>
Date:   Mon Dec 6 19:56:07 2010 +0100

    Use symlink to /tmp as socket directory by default
    
    This patch is based on the one written by Ansgar Burchardt to use
    a socket directory linked to /tmp/<username>-akonadi.<random> instead
    of the hard-coded one from ~/.local/share/akonadi.
    With this patch Akonadi will start on systems with $HOME on AFS without
    any further configuration needed.
    
    BUG: 179006

diff --git a/server/src/utils.cpp b/server/src/utils.cpp
index 37949db..4575292 100644
--- a/server/src/utils.cpp
+++ b/server/src/utils.cpp
@@ -22,9 +22,21 @@
 
 #include "libs/xdgbasedirs_p.h"
 
+#include <QtCore/QDebug>
 #include <QtCore/QDir>
 #include <QtCore/QFileInfo>
 #include <QtCore/QSettings>
+#include <QtNetwork/QHostInfo>
+
+#include <cerrno>
+#include <cstdlib>
+#include <pwd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+static QString akonadiSocketDirectory();
+static bool checkSocketDirectory( const QString &path );
+static bool createSocketDirectory( const QString &link, const QString &tmpl );
 
 using namespace Akonadi;
 
@@ -33,7 +45,16 @@ QString Utils::preferredSocketDirectory( const QString &defaultDirectory )
   const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
   const QSettings serverSettings( serverConfigFile, QSettings::IniFormat );
 
-  QString socketDir = serverSettings.value( QLatin1String( "Connection/SocketDirectory" ), defaultDirectory ).toString();
+  QString socketDir = defaultDirectory;
+  if ( !serverSettings.contains( QLatin1String( "Connection/SocketDirectory" ) ) ) {
+    // if no socket directory is defined, use the symlinked from /tmp
+    socketDir = akonadiSocketDirectory();
+
+    if ( socketDir.isEmpty() ) // if that does not work, fall back on default
+      socketDir = defaultDirectory;
+  } else {
+    socketDir = serverSettings.value( QLatin1String( "Connection/SocketDirectory" ), defaultDirectory ).toString();
+  }
 
   const QString userName = QString::fromLocal8Bit( qgetenv( "USER" ) );
   if ( socketDir.contains( QLatin1String( "$USER" ) ) && !userName.isEmpty() )
@@ -50,3 +71,74 @@ QString Utils::preferredSocketDirectory( const QString &defaultDirectory )
 
   return socketDir;
 }
+
+QString akonadiSocketDirectory()
+{
+  const QString hostname = QHostInfo::localHostName();
+
+  if ( hostname.isEmpty() ) {
+    qCritical() << "QHostInfo::localHostName() failed";
+    return QString();
+  }
+
+  const uid_t uid = getuid();
+  const struct passwd *pw_ent = getpwuid( uid );
+  if ( !pw_ent ) {
+    qCritical() << "Could not get passwd entry for user id" << uid;
+    return QString();
+  }
+
+  const QString link = XdgBaseDirs::saveDir( "data", QLatin1String( "akonadi" ) ) + QLatin1Char( '/' ) + QLatin1String( "socket-" ) + hostname;
+  const QString tmpl = QLatin1String( "akonadi-" ) + QLatin1String( pw_ent->pw_name ) + QLatin1String( ".XXXXXX" );
+
+  if ( checkSocketDirectory( link ) )
+    return link;
+
+  if ( createSocketDirectory( link, tmpl ) )
+    return link;
+
+  qCritical() << "Could not create socket directory for Akonadi.";
+  return QString();
+}
+
+static bool checkSocketDirectory( const QString &path )
+{
+  QFileInfo info( path );
+
+  if ( !info.exists() )
+    return false;
+
+  if ( info.isSymLink() )
+    info = QFileInfo( info.symLinkTarget() );
+
+  if ( !info.isDir() )
+    return false;
+
+  if ( info.ownerId() != getuid() )
+    return false;
+
+  return true;
+}
+
+static bool createSocketDirectory( const QString &link, const QString &tmpl )
+{
+  QString directory = QString::fromLatin1( "%1%2%3" ).arg( QDir::tempPath() ).arg( QDir::separator() ).arg( tmpl );
+
+  QByteArray directoryString = directory.toLocal8Bit().data();
+
+  if ( !mkdtemp( directoryString.data() ) ) {
+    qCritical() << "Creating socket directory with template" << directoryString << "failed:" << strerror( errno );
+    return false;
+  }
+
+  directory = QString::fromLocal8Bit( directoryString );
+
+  QFile::remove( link );
+
+  if ( !QFile::link( directory, link ) ) {
+    qCritical() << "Creating symlink from" << directory << "to" << link << "failed";
+    return false;
+  }
+
+  return true;
+}
Comment 13 LuRan 2010-12-16 05:08:25 UTC
This change in git will cause trouble with old akonadi config files where the socket has been set to $HOME/.local/share/akonadi/db_misc/mysql.socket, akonadi will crash with the error message like:

Last driver error: "QMYSQL: Unable to connect"
Last database error: "Can't connect to local MySQL server through socket '/home/luran/.local/share/akonadi/db_misc/mysql.socket' (2)"
Unable to open database "Can't connect to local MySQL server through socket '/home/luran/.local/share/akonadi/db_misc/mysql.socket' (2) QMYSQL: Unable to connect"

And multiple mysqld will be started. There should be some announcement beside the commit log, or some code to fix the path automatically.
Comment 14 Tobias Koenig 2011-01-02 15:48:21 UTC
(In reply to comment #13)
> This change in git will cause trouble with old akonadi config files where the
> socket has been set to $HOME/.local/share/akonadi/db_misc/mysql.socket,
> akonadi will crash with the error message like:
This has been fixed in the meantime.