[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-pim
Subject:    [Kde-pim] KSharedFile RFC
From:       Holger Freyther <freyther () gmx ! net>
Date:       2001-12-16 17:12:22
[Download RAW message or body]

Hi Cornelius, kde-pims,
Cornelius and me created KSharedFile. Cornelius I added all the stuff you 
missed and I think my file is ready for committing. I would like to add it to 
kio? Any comments>
KSharedFile is a class to share file access between processes. It gives api 
to lock a file. Locking means no other process than the holder can write to 
the file. This is done in 2 ways. First the holder needs to have a ticket and 
the other is inside the class.

Actually I don't know what to say else

regards Holger

PS: Cornelius sorry it took so long. But I had to study and did some work for 
kafka and kitchensync
["ksharedfile.h" (text/x-c++)]

/* This file is part of the KDE libraries
    Copyright (C) 2001 Holger Freyther <freyher@kde.org>
    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
		  
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/

#ifndef ksharedfile_h
#define ksharedfile_h

#include <sys/types.h>

#include <qstring.h>
#include <qobject.h>

class QFile;
class QTimer; 

/** The point of KSharedFile is to make it possible for more than one 
    program to work with a file. It take's care that only one program
    writes to the file at a time. There's no really way of pretending a
program to write to the file.
    The program creates a instance of KSharedFile and sets the FileName.
    If it want's to write to the file it calls tryLockFile( ) and either get's
    the lock or not.
    Then there are also signal which signalize a change.
    @short KSharedFile to lock a file
    @author Holger Freyther <freyther@kde.org>
    @version 0.5 
 */

class KSharedFile : public QObject 
{
  Q_OBJECT;
 public:
  /** Instantiate the class.
    @param filename The resource to be shared with others
   */
  KSharedFile( const QString &filename );
  /** this function is for convience 
      it does the same a above but takes a file as paramter
      @param file The file to be shared.
  */
  KSharedFile( const QFile &file );
  ~KSharedFile( );
  
  class Ticket
  {
      friend class KSharedFile;
      Ticket ( const QString &filename ) : m_fileName( filename ) {}
    private:
      QString m_fileName;

  };
  /** sets the Filename
      @param filename The name of the resource to be shared 
   */
  void setFileName( const QString &filename );
  /** This method is for convience.It sets the File
      @param file The file to be shared
   */
  void setFile( const QFile &file );
  /** @return the fileName of the shared file
   */
  QString fileName( ) const;

  /** This tries to lock the file. It returns right after trying either successful or not
 @return if Ticket is not equal to 0l the file was successfully locked
  */
  Ticket* tryLockFile( );
  /** This loads the file specified
     @see setFileName(const QString & )
   */
  QString load( );
  /** This writes to the file if the ticket is valid
 @param 
   */
  bool save( Ticket *ticket, const QString &string );
  /** after locking this unlocks the file
   */
  bool unlockFile( Ticket *ticket );
  /** check whether or not the file is locked
   @return the state of the lock
   */
  bool isLocked( );
  /**
     @returns whether or not I locked the file
   */
  bool didILock( );
  /** In future this will tell you who to blame for the file is locked.

   */
  QString whoHoldsLock( ) const;


 protected:
  QString m_uniqueName;

 private:
  QString m_fileName;
  bool m_locked:1;
  bool m_lockedOther:1;
  QTimer *m_FileCheckTimer;
  time_t m_ChangeTime;

 private slots:
  void checkFile( );
 signals:
  /**
    This signal get emitted when the file get unlocked
    @param filename The name of the file which gets locked
   */
  void fileUnlocked( const QString &filename);
  /** The file got locked
      @param filename filename got locked
  */  
  void fileLocked( const QString &filename );
  /**
      The file changed during a lock and unlock session
      @param filename The file with the name filenam changed
   */
  void fileChanged( const QString &filename );
};

#endif

["ksharedfile.cpp" (text/x-c)]

/* This file is part of the KDE libraries
    Copyright (C) 2001 Holger Freyther <freyher@kde.org>
    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
		  
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/
#include <sys/stat.h>
#include <unistd.h>


#include <kapplication.h>
#include <kdebug.h>

#include <qfile.h>
#include <qtimer.h>
#include <qtextstream.h>
#include "ksharedfile.h"

KSharedFile::KSharedFile( const QString &filename ) : QObject( 0, "KSharedFile" )
{
  m_locked = false;
  m_FileCheckTimer = new QTimer (this );
  connect( m_FileCheckTimer, SIGNAL( timeout() ), SLOT( checkFile()) );
  setFileName( filename);
}
KSharedFile::KSharedFile( const QFile &file ) : QObject( 0, "KSharedFile" )
{
  m_locked = false;
  m_FileCheckTimer = new QTimer(this  );
  connect( m_FileCheckTimer, SIGNAL( timeout() ), SLOT( checkFile()) );
  setFile( file);
}
KSharedFile::~KSharedFile( )
{
  unlockFile(new Ticket(m_fileName) );
  delete m_FileCheckTimer; // qt would do this too
}

void KSharedFile::setFileName ( const QString &filename )
{
  unlockFile(new Ticket(m_fileName) );
  m_lockedOther = false;
  m_fileName = filename;
  struct stat s;
  int result = stat( QFile::encodeName( m_fileName ), &s );
  if ( result == 0 ) { // file exists 
    m_ChangeTime = s.st_ctime; // last change
    m_FileCheckTimer->start( 500 );
  }
}
void KSharedFile::setFile( const QFile &file )
{
  setFileName( file.name() );
}
QString KSharedFile::fileName( )const 
{
  return m_fileName;
}


KSharedFile::Ticket *KSharedFile::tryLockFile( )
{ 
  kdDebug(5910) << "KSharedFile::tryLockFile " << m_fileName << endl; 
  if(!QFile::exists( m_fileName ) ) return 0l;  
  if(QFile::exists( m_fileName+".lock") ) return 0l;
  QString lockFile(m_fileName + ".lock" );

  //create unique file
  m_uniqueName =  m_fileName + kapp->randomString(8) ;
  QFile file( m_uniqueName);
  file.open( IO_WriteOnly );
  file.close( );

  // Create lock file
  int result = link ( QFile::encodeName( m_uniqueName ),
		      QFile::encodeName( m_fileName + ".lock" ));
  if( result == 0 )
  {
    emit fileLocked(m_fileName );
    m_locked = true;
    return new KSharedFile::Ticket(m_fileName );
  }
  return 0l;
}

bool KSharedFile::unlockFile( Ticket* ticket )
{
  if( m_locked && ticket->m_fileName==m_fileName){
    m_locked = false;
    unlink( QFile::encodeName(m_fileName+ ".lock") );
    QFile::remove( m_uniqueName );
    emit fileUnlocked( m_fileName );   
    delete ticket;
    ticket=0;
    return true;
  }else
    return false;
}
bool KSharedFile::isLocked( )
{
  //return m_locked;
  return QFile::exists(m_fileName + ".lock");
}
bool KSharedFile::didILock( )
{
  return m_locked;
}
QString KSharedFile::whoHoldsLock( ) const
{
  return QString();
}
bool KSharedFile::save( Ticket *ticket, const QString &string )
{
  if ( m_locked && ticket->m_fileName == m_fileName ){
    QFile file( m_fileName ); // handles unicode names inernal
    file.open(IO_WriteOnly);
    QTextStream stream( &file );
    //file.writeBlock( string ); //doesn't work
    stream << string;
    file.close();
    return true;
  }
  return false;
}
QString KSharedFile::load( )
{
  QString dummy;
  QFile file( m_fileName );
  file.open(IO_ReadOnly);
  dummy = QString(file.readAll() );
  file.close();
  return dummy;
}
void KSharedFile::checkFile( )
{ 
  // ok somebody holds the lock
  if( !m_lockedOther && !m_locked && QFile::exists( QFile::encodeName( m_fileName+ ".lock" ) ) ) {
    emit fileLocked( m_fileName );
    m_lockedOther= true; // other locked our file
    return; 
  }
  else if( m_lockedOther && !m_locked &&!QFile::exists( QFile::encodeName( m_fileName + ".lock" ) ) ) {
    emit fileUnlocked( m_fileName );
    m_lockedOther = false; // other
   
  }  
  struct stat s;
  int result = stat( QFile::encodeName( m_fileName ), &s );
  if ( result == 0 && (m_ChangeTime != s.st_ctime ) ){
    m_ChangeTime = s.st_ctime;
    emit fileChanged( m_fileName );
  }
  
}

#include "ksharedfile.moc"

_______________________________________________
kde-pim mailing list
kde-pim@mail.kde.org
http://mail.kde.org/mailman/listinfo/kde-pim

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic