librostlab  1.0.20
rostlab/file_lock_resource.h
Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2011 Laszlo Kajan, Technical University of Munich, Germany
00003 
00004     This file is part of librostlab.
00005 
00006     librostlab is free software: you can redistribute it and/or modify
00007     it under the terms of the GNU Lesser General Public License as published by
00008     the Free Software Foundation, either version 3 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public License
00017     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 #ifndef ROSTLAB_FLOCK_RESOURCE
00020 #define ROSTLAB_FLOCK_RESOURCE
00021 
00022 #include <errno.h>
00023 #include <fcntl.h>
00024 #include <iostream>
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include <unistd.h>
00028 
00029 #include "rostlab/rostlab_stdexcept.h"
00030 
00031 namespace rostlab {
00032 
00037 class file_lock_resource
00038 {
00039   private:
00040     std::string        _filename;
00041     FILE*         _fh;
00042     // this is a resource - disable copy contructor and copy assignment
00043                   file_lock_resource( const file_lock_resource& ){};
00044     file_lock_resource&
00045                   operator=(const file_lock_resource&){return *this;};
00046   public:
00047     bool          dbg;
00048 
00049     class wouldblock : public exception {};
00050 
00051   public:
00052                   file_lock_resource() : _fh(NULL), dbg(false) {};
00053 
00056                   file_lock_resource( const std::string& __file, const std::string& __mode = "r", int __cmd = F_SETLKW, short __type = F_RDLCK, bool __dbg = false ) : _fh(NULL), dbg(__dbg)
00057     {
00058       acquire( __file, __mode, __cmd, __type, __dbg );
00059     }
00060 
00061     inline void   acquire( const std::string& __file, const std::string& __mode = "r", int __cmd = F_SETLKW, short __type = F_RDLCK, bool __dbg = false ) throw ( runtime_error, wouldblock )
00062     {
00063       dbg = __dbg;
00064       release();
00065       //
00066       _filename = __file;
00067       _fh = fopen( _filename.c_str(), __mode.c_str() );
00068       if( !_fh ) throw runtime_error( strerror( errno ) );
00069 
00070       // instead of flock us fcntl()/POSIX locking so that it works with NFS as well
00071       flock lock;
00072       lock.l_type = __type;
00073       lock.l_whence = SEEK_SET;
00074       lock.l_start = 0;
00075       lock.l_len = 0;
00076 
00077       if( fcntl( fileno(_fh), __cmd, &lock ) )
00078       {
00079         int fcntl_errno = errno;
00080         fclose(_fh); _fh = NULL;
00081         if( fcntl_errno == EACCES || fcntl_errno == EAGAIN ) throw wouldblock();
00082         else throw runtime_error( strerror( fcntl_errno ) );
00083       }
00084       else if(dbg) std::cerr << "LOCK_" << __mode << " " << __cmd << " " << __type << " '" << _filename << "'\n";
00085     }
00086 
00087     inline void   release() throw (runtime_error)
00088     {
00089       if( _fh )
00090       {
00091         // lkajan: no need to explicitly release the lock: it is released when the file is closed
00092         if( fclose(_fh) ) throw runtime_error( strerror( errno ) );
00093         if(dbg) std::cerr << "LOCK_UN '" << _filename << "'\n";
00094         _fh = NULL;
00095       }
00096     }
00097 
00098     virtual       ~file_lock_resource()
00099     {
00100       release();
00101     }
00102 
00103     operator      FILE* () { return _fh; }
00104 
00105     inline const std::string&
00106                   filename() const { return _filename; }
00107 };
00108 
00109 };
00110 
00111 #endif // ROSTLAB_FLOCK_RESOURCE
00112 // vim:et:ts=2:ai:
 All Classes Namespaces Files Functions Variables Typedefs