Exemple #1
0
 def session_write(self):
     """ Writes the locked set to the session file. 
         The global lock MUST be held for this function to work, although on NFS additional
         locking is done
         Raises RepositoryError if session file is inaccessible """
     #logger.debug("Openining Session File: %s " % self.fn )
     try:
         # If this fails, we want to shutdown the repository (corruption
         # possible)
         fd = self.delayopen(self.fn)
         if not self.afs:
             fcntl.lockf(fd, fcntl.LOCK_EX)
         self.delaywrite(fd, pickle.dumps(self.locked))
         if not self.afs:
             fcntl.lockf(fd, fcntl.LOCK_UN)
         os.fsync(fd)
         os.close(fd)
     except OSError as x:
         if x.errno != errno.ENOENT:
             raise RepositoryError(
                 self.repo,
                 "Error on session file access '%s': %s" % (self.fn, x))
         else:
             #logger.debug( "File NOT found %s" %self.fn )
             raise RepositoryError(
                 self.repo,
                 "SessionWrite: Own session file not found! Possibly deleted by another ganga session.\n\
                                 Possible reasons could be that this computer has a very high load, or that the system clocks on computers running Ganga are not synchronized.\n\
                                 On computers with very high load and on network filesystems, try to avoid running concurrent ganga sessions for long.\n '%s' : %s"
                 % (self.fn, x))
     except IOError as x:
         raise RepositoryError(
             self.repo,
             "Error on session file locking '%s': %s" % (self.fn, x))
Exemple #2
0
    def global_lock_setup(self):

        if self.afs:
            self.lockfn = os.path.join(self.sdir, "global_lock")
            lock_path = str(self.lockfn) + '.afs'
            lock_file = os.path.join(lock_path, "lock_file")
            try:
                if not os.path.exists(lock_path):
                    os.makedirs(lock_path)
                if not os.path.isfile(lock_file):
                    lock_file_hand = open(lock_file, "w")
                    lock_file_hand.close()
            except Exception as err:
                logger.debug("Global Lock Setup Error: %s" % str(err))
        else:
            try:
                self.lockfn = os.path.join(self.sdir, "global_lock")
                if not os.path.isfile(self.lockfn):
                    lock = open(self.lockfn, "w")
                    # create file (does not interfere with existing sessions)
                    lock.close()
                self.lockfd = self.delayopen_global(self.lockfn)
                registerGlobalSessionFile(self.lockfn)
                registerGlobalSessionFileHandler(self.lockfd)
            except IOError as x:
                raise RepositoryError(
                    self.repo,
                    "Could not create lock file '%s': %s" % (self.lockfn, x))
            except OSError as x:
                raise RepositoryError(
                    self.repo,
                    "Could not open lock file '%s': %s" % (self.lockfn, x))
Exemple #3
0
    def startup(self):
        self.last_count_access = None

        # Ensure directories exist
        self.mkdir(os.path.join(self.realpath, "sessions"))
        self.mkdir(os.path.join(self.realpath, self.name))

        # setup global lock
        self.global_lock_setup()
        self.global_lock_acquire()
        try:
            # setup counter file if it does not exist, read it if it does
            if not os.path.exists(self.cntfn):
                try:
                    fd = self.delay_init_open(self.cntfn)
                    try:
                        os.write(fd, "0")
                    finally:
                        os.close(fd)
                    #registerGlobalSessionFile( self.cntfn )
                except OSError as x:
                    if x.errno != errno.EEXIST:
                        raise RepositoryError(
                            self.repo, "OSError on count file create: %s" % x)
            try:
                self.count = max(self.count, self.cnt_read())
            except ValueError, err:
                logger.debug("Startup ValueError Exception: %s" % err)
                logger.error("Corrupt count file '%s'! Trying to recover..." %
                             (self.cntfn))
            except OSError as err:
                logger.debug("Startup OSError Exception: %s" % err)
                raise RepositoryError(
                    self.repo,
                    "OSError on count file '%s' access!" % (self.cntfn))
            self.cnt_write()
            # Setup session file
            try:
                fd = self.delay_init_open(self.fn)
                try:
                    os.write(fd, pickle.dumps(set()))
                finally:
                    os.close(fd)
                registerGlobalSessionFile(self.fn)
            except OSError as err:
                logger.debug("Startup Session Exception: %s" % err)
                raise RepositoryError(
                    self.repo,
                    "Error on session file '%s' creation: %s" % (self.fn, err))

            setupGlobalLockRef(self.session_name, self.sdir, self.gfn,
                               self.afs)

            session_lock_refresher.addRepo(self.fn, self.repo)
            self.session_write()
Exemple #4
0
    def cnt_read(self):
        """ Tries to read the counter file.
            Raises ValueError (invalid contents)
            Raises OSError (no access/does not exist)
            Raises RepositoryError (fatal)
            """
        try:
            global last_count_access
            if len(last_count_access) == 2:
                last_count_time = last_count_access[0]
                last_count_val = last_count_access[1]
                last_time = os.stat(self.cntfn).st_ctime
                if last_time == last_count_time:
                    last_count_val
            _output = None
            fd = os.open(self.cntfn, os.O_RDONLY)
            try:
                if not self.afs:  # additional locking for NFS
                    fcntl.lockf(fd, fcntl.LOCK_SH)
                # 100 bytes should be enough for any ID. Can raise ValueErrorr
                _output = int(os.read(fd, 100).split("\n")[0])
            finally:
                if not self.afs:  # additional locking for NFS
                    fcntl.lockf(fd, fcntl.LOCK_UN)
                os.close(fd)

                if _output != None:
                    if len(last_count_access) != 2:
                        last_count_access = []
                        last_count_access.append(os.stat(self.cntfn).st_ctime)
                        last_count_access.append(_output)
                    else:
                        last_count_access[0] = os.stat(self.cntfn).st_ctime
                        last_count_access[1] = _output
                    return _output

        except OSError as x:
            if x.errno != errno.ENOENT:
                raise RepositoryError(
                    self.repo,
                    "OSError on count file '%s' read: %s" % (self.cntfn, x))
            else:
                # This can be a recoverable error, depending on where it occurs
                raise
        except IOError as x:
            raise RepositoryError(
                self.repo,
                "Locking error on count file '%s' write: %s" % (self.cntfn, x))
    def flush(self, ids):
        logger.debug("Flushing: %s" % ids)

        #import traceback
        #traceback.print_stack()
        for this_id in ids:
            try:
                logger.debug("safe_flush")
                self._safe_flush_xml(this_id)

                self._cache_load_timestamp[this_id] = time.time()
                self._cached_cls[this_id] = getName(self.objects[this_id])
                self._cached_cat[this_id] = self.objects[this_id]._category
                self._cached_obj[this_id] = self.objects[
                    this_id].getNodeIndexCache()

                try:
                    self.index_write(this_id)
                except:
                    logger.debug("Index write failed")
                    pass

                if this_id not in self._fully_loaded.keys():
                    self._fully_loaded[this_id] = self.objects[this_id]

            except (OSError, IOError, XMLFileError) as x:
                raise RepositoryError(
                    self, "Error of type: %s on flushing id '%s': %s" %
                    (type(x), str(this_id), str(x)))
Exemple #6
0
    def __init__(self, repo, root, name, minimum_count=0):

        # Used for self runtime thread safety
        self.sync_lock = threading.RLock()

        # Required to pretend there are some locked jobs from other sessions
        self.locked = set()

        self.repo = repo
        self.mkdir(root)
        realpath = os.path.realpath(root)

        # Location of the count file for this repo
        self.cntfn = os.path.join(realpath, name, "cnt")

        # Required for lock files
        sessions_folder = os.path.join(realpath, "sessions")
        if not os.path.exists(sessions_folder):
            os.mkdir(sessions_folder)

        # Location of fixed lock for this repo
        self.global_lock = os.path.join(sessions_folder,
                                        '%s_fixed_lock' % name)
        self.count = minimum_count
        if os.path.exists(self.global_lock):
            msg = "\n\nCannot start this registry: %s due to a lock file already existing: '%s'\n" % (
                name, self.global_lock)
            msg += "If you are trying to run only 1 ganga session please remove this file and re-launch ganga\n"
            raise RepositoryError(repo, msg)

        with open(self.global_lock, 'w'):
            pass
Exemple #7
0
    def _add(self, obj, force_index=None):
        """ Add an object to the registry and assigns an ID to it. 
        use force_index to set the index (for example for metadata). This overwrites existing objects!
        Raises RepositoryError
        Args:
            _obj (GangaObject): This is th object which is to be added to this Registy/Repo
            force_index (int): This is the index which we will give the object, None = auto-assign
        """
        logger.debug("_add")

        if self.hasStarted() is not True:
            raise RepositoryError("Cannot add objects to a disconnected repository!")

        if force_index is None:
            ids = self.repository.add([obj])
        else:
            if len(self.repository.lock([force_index])) == 0:
                raise RegistryLockError("Could not lock '%s' id #%i for a new object!" % (self.name, force_index))
            ids = self.repository.add([obj], [force_index])

        obj._setRegistry(self)
        obj._registry_locked = True

        self.repository.flush(ids)

        return ids[0]
Exemple #8
0
 def session_read(self, fn):
     """ Reads a session file and returns a set of IDs locked by that session.
         The global lock MUST be held for this function to work, although on NFS additional
         locking is done
         Raises RepositoryError if severe access problems occur (corruption otherwise!) """
     try:
         # This can fail (thats OK, file deleted in the meantime)
         fd = self.delay_session_open(fn)
         os.lseek(fd, 0, 0)
         try:
             if not self.afs:  # additional locking for NFS
                 fcntl.lockf(fd, fcntl.LOCK_SH)
             try:
                 # 00)) # read up to 1 MB (that is more than enough...)
                 return pickle.loads(os.read(fd, 1048576))
             except Exception as x:
                 logger.warning(
                     "corrupt or inaccessible session file '%s' - ignoring it (Exception %s %s)."
                     % (fn, getName(x), str(x)))
         finally:
             if not self.afs:  # additional locking for NFS
                 fcntl.lockf(fd, fcntl.LOCK_UN)
             os.close(fd)
     except OSError as x:
         if x.errno != errno.ENOENT:
             raise RepositoryError(
                 self.repo,
                 "Error on session file access '%s': %s" % (fn, x))
     return set()
Exemple #9
0
    def add(self, objs, force_ids=None):
        ids = []

        def _readonly():
            return True

        for o in objs:
            obj = copy.deepcopy(o)
            fn = os.path.join(self.filebase,
                              '%s.%s' % (obj.name, self.file_ext))
            try:
                if self.pickle_files:
                    obj._registry = None

                    pickle.dump(obj, open(fn, 'wb'))

                else:
                    if not stripped_export(obj, fn):
                        raise RepositoryError(
                            self,
                            'Failure in stripped_export method, returned False'
                        )
            except:
                logger.error("Unable to write to file '%s'" % fn)
                raise
            else:
                obj.id = self._next_id
                obj._registry = self.registry
                obj._registry_id = self._next_id
                setattr(obj, '_readonly', _readonly)

                self.objects[self._next_id] = obj
                ids.append(self._next_id)
                self._next_id += 1
        return ids
Exemple #10
0
    def startup(self):
        """ Starts a repository and reads in a directory structure.
        Raise RepositoryError"""
        self._load_timestamp = {}

        # New Master index to speed up loading of many, MANY files
        self._cache_load_timestamp = {}
        self._cached_cat = {}
        self._cached_cls = {}
        self._cached_obj = {}
        self._master_index_timestamp = 0

        self.known_bad_ids = []
        if "XML" in self.registry.type:
            self.to_file = xml_to_file
            self.from_file = xml_from_file
        elif "Pickle" in self.registry.type:
            self.to_file = pickle_to_file
            self.from_file = pickle_from_file
        else:
            raise RepositoryError(
                self.repo, "Unknown Repository type: %s" % self.registry.type)
        self.sessionlock = SessionLockManager(self, self.lockroot,
                                              self.registry.name)
        self.sessionlock.startup()
        # Load the list of files, this time be verbose and print out a summary
        # of errors
        self.update_index(verbose=True, firstRun=True)
        logger.debug("GangaRepositoryLocal Finished Startup")
Exemple #11
0
    def lock_ids(self, ids):

        self.safe_LockCheck()

        #logger.debug( "locking: %s" % str(ids) )
        ids = set(ids)
        self.global_lock_acquire()
        try:
            try:
                sessions = [
                    sn for sn in os.listdir(self.sdir)
                    if sn.endswith(self.name + ".locks")
                ]
            except OSError as x:
                raise RepositoryError(
                    self.repo,
                    "Could not list session directory '%s'!" % (self.sdir))

            slocked = set()
            for session in sessions:
                sf = os.path.join(self.sdir, session)
                if sf == self.fn:
                    continue
                slocked.update(self.session_read(sf))
            #logger.debug( "locked: %s" % str(slocked) )
            ids.difference_update(slocked)
            self.locked.update(ids)
            #logger.debug( "stored_lock: %s" % str(self.locked) )
            self.session_write()
            #logger.debug( "list: %s" % str(list(ids)) )
            return list(ids)
        finally:
            self.global_lock_release()
Exemple #12
0
 def make_new_ids(self, n):
     """ Locks the next n available ids and returns them as a list 
         Raise RepositoryError on fatal error"""
     self.global_lock_acquire()
     try:
         # Actualize count
         try:
             newcount = self.cnt_read()
         except ValueError:
             logger.warning(
                 "Corrupt job counter (possibly due to crash of another session)! Trying to recover..."
             )
             newcount = self.count
         except OSError:
             raise RepositoryError(
                 self.repo,
                 "Job counter deleted! External modification to repository!"
             )
         if not newcount >= self.count:
             #raise RepositoryError(self.repo, "Counter value decreased - logic error!")
             logger.warning(
                 "Internal counter increased - probably the count file was deleted."
             )
             newcount = self.count
         # someone used force_ids (for example old repository imports)
         if self.locked and max(self.locked) >= newcount:
             newcount = max(self.locked) + 1
         ids = range(newcount, newcount + n)
         self.locked.update(ids)
         self.count = newcount + n
         self.cnt_write()
         self.session_write()
         return list(ids)
     finally:
         self.global_lock_release()
Exemple #13
0
 def mkdir(self, dn):
     """Make sure the given directory exists"""
     try:
         os.makedirs(dn)
     except OSError as x:
         if x.errno != errno.EEXIST:
             raise RepositoryError(self.repo,
                                   "OSError on directory create: %s" % x)
Exemple #14
0
    def add(self, objs, force_ids=None):
        """ Add the given objects to the repository, forcing the IDs if told to.
        Raise RepositoryError"""

        logger.debug("add")

        if force_ids not in [
                None, []
        ]:  # assume the ids are already locked by Registry
            if not len(objs) == len(force_ids):
                raise RepositoryError(
                    self,
                    "Internal Error: add with different number of objects and force_ids!"
                )
            ids = force_ids
        else:
            ids = self.sessionlock.make_new_ids(len(objs))

        logger.debug("made ids")

        for i in range(0, len(objs)):
            fn = self.get_fn(ids[i])
            try:
                os.makedirs(os.path.dirname(fn))
            except OSError as e:
                if e.errno != errno.EEXIST:
                    raise RepositoryError(self,
                                          "OSError on mkdir: %s" % (str(e)))
            self._internal_setitem__(ids[i], objs[i])

            # Set subjobs dirty - they will not be flushed if they are not.
            if self.sub_split and self.sub_split in objs[i].getNodeData():
                try:
                    sj_len = len(objs[i].getNodeAttribute(self.sub_split))
                    if sj_len > 0:
                        for j in range(sj_len):
                            objs[i].getNodeAttribute(
                                self.sub_split)[j]._dirty = True
                except AttributeError as err:
                    logger.debug("RepoXML add Exception: %s" % str(err))

        logger.debug("Added")

        return ids
Exemple #15
0
    def cnt_read(self):
        """ Tries to read the counter file.
            Raises ValueError (invalid contents)
            Raises OSError (no access/does not exist)
            Raises RepositoryError (fatal)
            """
        try:
            if self.last_count_access is not None:
                last_count_time = self.last_count_access.time
                last_count_val = self.last_count_access.val
                last_time = os.stat(self.cntfn).st_ctime
                if last_time == last_count_time:
                    return last_count_val  # If the file hasn't changed since last check, return the cached value
            _output = None
            fd = os.open(self.cntfn, os.O_RDONLY)
            try:
                if not self.afs:  # additional locking for NFS
                    fcntl.lockf(fd, fcntl.LOCK_SH)
                # 100 bytes should be enough for any ID. Can raise ValueErrorr
                _output = int(os.read(fd, 100).split("\n")[0])
            finally:
                if not self.afs:  # additional locking for NFS
                    fcntl.lockf(fd, fcntl.LOCK_UN)
                os.close(fd)

                if _output != None:
                    self.last_count_access = SessionLockManager.LastCountAccess(
                        os.stat(self.cntfn).st_ctime, _output)
                    return _output

        except OSError as x:
            if x.errno != errno.ENOENT:
                raise RepositoryError(
                    self.repo,
                    "OSError on count file '%s' read: %s" % (self.cntfn, x))
            else:
                # This can be a recoverable error, depending on where it occurs
                raise
        except IOError as x:
            raise RepositoryError(
                self.repo,
                "Locking error on count file '%s' write: %s" % (self.cntfn, x))
Exemple #16
0
 def get_index_listing(self):
     """Get dictionary of possible objects in the Repository: True means index is present,
         False if not present
     Raise RepositoryError"""
     try:
         obj_chunks = [
             d for d in os.listdir(self.root)
             if d.endswith("xxx") and d[:-3].isdigit()
         ]
     except OSError as err:
         logger.debug("get_index_listing Exception: %s" % str(err))
         raise RepositoryError(
             self, "Could not list repository '%s'!" % (self.root))
     objs = {}  # True means index is present, False means index not present
     for c in obj_chunks:
         try:
             listing = os.listdir(os.path.join(self.root, c))
         except OSError as err:
             logger.debug("get_index_listing Exception: %s")
             raise RepositoryError(
                 self, "Could not list repository '%s'!" %
                 (os.path.join(self.root, c)))
         objs.update(dict([(int(l), False) for l in listing
                           if l.isdigit()]))
         for l in listing:
             if l.endswith(".index") and l[:-6].isdigit():
                 this_id = int(l[:-6])
                 if this_id in objs:
                     objs[this_id] = True
                 else:
                     try:
                         rmrf(self.get_idxfn(this_id))
                         logger.warning(
                             "Deleted index file without data file: %s" %
                             self.get_idxfn(this_id))
                     except OSError as err:
                         logger.debug(
                             "get_index_listing delete Exception: %s" %
                             str(err))
     return objs
Exemple #17
0
 def cnt_write(self):
     """ Writes the counter to the counter file. 
         The global lock MUST be held for this function to work correctly
         Raises OSError if count file is inaccessible """
     finished = False
     try:
         # If this fails, we want to shutdown the repository (corruption
         # possible)
         fd = os.open(self.cntfn, os.O_WRONLY)
         if not self.afs:
             fcntl.lockf(fd, fcntl.LOCK_EX)
         os.write(fd, str(self.count) + "\n")
         if not self.afs:
             fcntl.lockf(fd, fcntl.LOCK_UN)
         os.close(fd)
         finished = True
     except OSError as x:
         if x.errno != errno.ENOENT:
             raise RepositoryError(
                 self.repo,
                 "OSError on count file '%s' write: %s" % (self.cntfn, x))
         else:
             raise RepositoryError(
                 self.repo,
                 "Count file '%s' not found! Repository was modified externally!"
                 % (self.cntfn))
     except IOError as x:
         raise RepositoryError(
             self.repo,
             "Locking error on count file '%s' write: %s" % (self.cntfn, x))
     finally:
         if finished is True:
             global last_count_access
             if len(last_count_access) != 2:
                 last_count_access = []
                 last_count_access.append(os.stat(self.cntfn).st_ctime)
                 last_count_access.append(self.count)
             else:
                 last_count_access[0] = os.stat(self.cntfn).st_ctime
                 last_count_access[1] = self.count
Exemple #18
0
    def global_lock_release(self):
        try:
            if self.afs:
                lock_path = str(self.lockfn) + '.afs'
                os.system("fs setacl %s %s rlidwka" %
                          (lock_path, getpass.getuser()))
            else:
                self.delay_lock_mod(self.lockfd, fcntl.LOCK_UN)

            #logger.debug("global release")
        except IOError as x:
            raise RepositoryError(
                self.repo, "IOError on unlock ('%s'): %s" % (self.lockfn, x))
Exemple #19
0
    def _open_xml_file(self, fn, this_id, _copy_backup=False):
        """
        This loads the XML for the job "this_id" in self.objects using the file "fn" and knowing whether we want the file or the backup by _copy_backup
        """
        fobj = None

        has_loaded_backup = False

        try:
            if not os.path.isfile(fn) and _copy_backup:
                if os.path.isfile(fn + '~'):
                    logger.warning(
                        "XML File: %s missing, recovering from backup, recent changes may have been lost!"
                        % fn)
                    has_loaded_backup = True
                    try:
                        from shutil import copyfile
                        copyfile(fn + '~', fn)
                    except:
                        logger.warning(
                            "Error Recovering the backup file! loading of Job may Fail!"
                        )
            fobj = open(fn, "r")
        except IOError as x:
            if x.errno == errno.ENOENT:
                # remove index so we do not continue working with wrong information
                try:
                    # remove internal representation
                    self._internal_del__(this_id)
                    rmrf(os.path.dirname(fn) + ".index")
                except OSError as err:
                    logger.debug("load unlink Error: %s" % err)
                    pass
                raise KeyError(this_id)
            else:
                raise RepositoryError(self, "IOError: %s" % x)
        finally:
            try:
                if os.path.isdir(os.path.dirname(fn)):
                    ld = os.listdir(os.path.dirname(fn))
                    if len(ld) == 0:
                        os.rmdir(os.path.dirname(fn))
                        logger.warning(
                            "No job index or data found, removing empty directory: %s"
                            % os.path.dirname(fn))
            except Exception as err:
                logger.debug("load error %s" % err)
                pass

        return fobj, has_loaded_backup
Exemple #20
0
def getGlobalLockRef(session_name, sdir, gfn, _on_afs):
    global session_lock_refresher
    if session_lock_refresher is None:
        try:
            os.close(SessionLockManager.delay_init_open(gfn))
            registerGlobalSessionFile(gfn)
        except OSError as err:
            logger.debug("Startup Lock Refresher Exception: %s" % str(err))
            raise RepositoryError(
                None, "Error on session file '%s' creation: %s" % (gfn, err))
        session_lock_refresher = SessionLockRefresher(session_name, sdir, gfn,
                                                      None, _on_afs)
        session_lock_refresher.start()
    return session_lock_refresher
Exemple #21
0
 def _reallyUpdateLocks(self, index, failCount=0):
     this_index_file = self.fns[index]
     now = None
     try:
         oldnow = self.delayread(this_index_file)
         os.system('touch %s' % str(this_index_file))
         now = self.delayread(this_index_file)  # os.stat(self.fn).st_ctime
     except OSError as x:
         if x.errno != errno.ENOENT:
             logger.debug(
                 "Session file timestamp could not be updated! Locks could be lost!"
             )
             if now is None and failCount < 4:
                 try:
                     logger.debug(
                         "Attempting to lock file again, unknown error:\n'%s'"
                         % str(x))
                     import time
                     time.sleep(0.5)
                     failcount = failCount + 1
                     now = self._reallyUpdateLocks(index, failcount)
                 except Exception as err:
                     now = -999.
                     logger.debug(
                         "Received another type of exception, failing to update lockfile: %s"
                         % str(this_index_file))
             else:
                 logger.warning("Failed to update lock file: %s 5 times." %
                                str(this_index_file))
                 logger.warning(
                     "This could be due to a filesystem problem, or multiple versions of ganga trying to access the same file"
                 )
                 now = -999.
         else:
             if self.repos[index] != None:
                 raise RepositoryError(
                     self.repos[index],
                     "[SessionFileUpdate] Run: Own session file not found! Possibly deleted by another ganga session.\n\
                 Possible reasons could be that this computer has a very high load, or that the system clocks on computers running Ganga are not synchronized.\n\
                 On computers with very high load and on network filesystems, try to avoid running concurrent ganga sessions for long.\n '%s' : %s"
                     % (this_index_file, x))
             else:
                 from Ganga.Core import GangaException
                 raise GangaException(
                     "Error Opening global .session file for this session: %s"
                     % this_index_file)
     return now
Exemple #22
0
    def global_lock_acquire(self):
        try:
            if self.afs:

                lock_path = str(self.lockfn) + '.afs'
                lock_file = os.path.join(lock_path, "lock_file")

                def clean_path():
                    oldtime = os.stat(lock_file).st_ctime
                    nowtime = time.time()
                    if abs(int(nowtime) - oldtime) > 10:
                        #logger.debug( "cleaning global lock" )
                        os.system("fs setacl %s %s rlidwka" %
                                  (lock_path, getpass.getuser()))

                while True:
                    try:
                        if os.path.isfile(lock_file):
                            clean_path()
                        os.unlink(lock_file)
                        break
                    except Exception as err:
                        logger.debug("Global Lock aquire Exception: %s" %
                                     str(err))
                        time.sleep(0.01)

                os.system("fs setacl %s %s rliwka" %
                          (lock_path, getpass.getuser()))

                while not os.path.isfile(lock_file):
                    lock_file_hand = open(lock_file, "w")
                    lock_file_hand.close()
                    time.sleep(0.01)

            else:
                self.delay_lock_mod(self.lockfd, fcntl.LOCK_EX)

            #logger.debug("global capture")
        except IOError as x:
            raise RepositoryError(
                self.repo, "IOError on lock ('%s'): %s" % (self.lockfn, x))
Exemple #23
0
    def _safe_flush_xml(self, this_id):

        fn = self.get_fn(this_id)
        obj = self.objects[this_id]
        from Ganga.Core.GangaRepository.VStreamer import EmptyGangaObject
        if not isType(obj, EmptyGangaObject):
            split_cache = None

            has_children = (not self.sub_split is None) and (
                self.sub_split in obj.getNodeData()) and obj.getNodeAttribute(
                    self.sub_split) and len(
                        obj.getNodeAttribute(self.sub_split)) > 0

            if has_children:

                logger.debug("has_children")

                if hasattr(obj.getNodeAttribute(self.sub_split), 'flush'):
                    # I've been read from disk in the new SubJobXMLList format I know how to flush
                    obj.getNodeAttribute(self.sub_split).flush()
                else:
                    # I have been constructed in this session, I don't know how to flush!
                    if hasattr(
                            obj.getNodeAttribute(self.sub_split)[0], "_dirty"):
                        split_cache = obj.getNodeAttribute(self.sub_split)
                        for i in range(len(split_cache)):
                            if not split_cache[i]._dirty:
                                continue
                            sfn = os.path.join(os.path.dirname(fn), str(i),
                                               self.dataFileName)
                            if not os.path.exists(os.path.dirname(sfn)):
                                logger.debug("Constructing Folder: %s" %
                                             str(os.path.dirname(sfn)))
                                os.makedirs(os.path.dirname(sfn))
                            else:
                                logger.debug("Using Folder: %s" %
                                             str(os.path.dirname(sfn)))
                            safe_save(sfn, split_cache[i], self.to_file)
                            split_cache[i]._setFlushed()
                    from Ganga.Core.GangaRepository.SubJobXMLList import SubJobXMLList
                    # Now generate an index file to take advantage of future non-loading goodness
                    tempSubJList = SubJobXMLList(os.path.dirname(fn),
                                                 self.registry,
                                                 self.dataFileName,
                                                 False,
                                                 parent=obj)
                    ## equivalent to for sj in job.subjobs
                    tempSubJList._setParent(obj)
                    job_dict = {}
                    for sj in obj.getNodeAttribute(self.sub_split):
                        job_dict[sj.id] = stripProxy(sj)
                    tempSubJList._reset_cachedJobs(job_dict)
                    tempSubJList.flush()
                    del tempSubJList

                safe_save(fn, obj, self.to_file, self.sub_split)
                # clean files not in subjobs anymore... (bug 64041)
                for idn in os.listdir(os.path.dirname(fn)):
                    split_cache = obj.getNodeAttribute(self.sub_split)
                    if idn.isdigit() and int(idn) >= len(split_cache):
                        rmrf(os.path.join(os.path.dirname(fn), idn))
            else:

                logger.debug("not has_children")

                safe_save(fn, obj, self.to_file, "")
                # clean files leftover from sub_split
                for idn in os.listdir(os.path.dirname(fn)):
                    if idn.isdigit():
                        rmrf(os.path.join(os.path.dirname(fn), idn))
            self.index_write(this_id)
            #obj.setNodeIndexCache(None)
            obj._setFlushed()
        else:
            raise RepositoryError(
                self, "Cannot flush an Empty object for ID: %s" % str(this_id))

        if this_id not in self._fully_loaded.keys():
            self._fully_loaded[this_id] = obj
Exemple #24
0
    def load(self, ids, load_backup=False):
        """
        Load the following "ids" from disk
        If we want to load the backup files for these ids then use _copy_backup
        Correctly loaded objects are dirty, Objects loaded from backups for whatever reason are marked dirty
        """
        #print("load: %s " % ids)
        #import traceback
        #traceback.print_stack()
        #print("\n")

        logger.debug("Loading Repo object(s): %s" % ids)

        for this_id in ids:

            if this_id in self.incomplete_objects:
                raise RepositoryError(
                    self.repo,
                    "Trying to re-load a corrupt repository id: %s" % this_id)

            fn = self.get_fn(this_id)
            if load_backup:
                has_loaded_backup = True
                fn = fn + "~"
            else:
                has_loaded_backup = False

            fobj = None

            try:
                fobj, has_loaded_backup2 = self._open_xml_file(
                    fn, this_id, _copy_backup=True)
                if has_loaded_backup2:
                    has_loaded_backup = has_loaded_backup2
            except Exception as err:
                logger.debug("XML load: Failed to load XML file: %s" % fn)
                logger.debug("Error was:\n%s" % err)
                logger.error(
                    "Adding id: %s to Corrupt IDs will not attempt to re-load this session"
                    % this_id)
                self.incomplete_objects.append(this_id)
                raise

            try:
                self._actually_load_xml(fobj, fn, this_id, load_backup)
            except RepositoryError as err:
                logger.debug("Repo Exception: %s" % err)
                logger.error(
                    "Adding id: %s to Corrupt IDs will not attempt to re-load this session"
                    % this_id)
                self.incomplete_objects.append(this_id)
                raise

            except Exception as err:

                should_continue = self._handle_load_exception(
                    err, fn, this_id, load_backup)

                if should_continue is True:
                    has_loaded_backup = True
                    continue
                else:
                    logger.error(
                        "Adding id: %s to Corrupt IDs will not attempt to re-load this session"
                        % this_id)
                    self.incomplete_objects.append(this_id)
                    raise

            finally:
                fobj.close()

            if has_loaded_backup:
                self.objects[this_id]._setDirty()
            else:
                self.objects[this_id]._setFlushed()

        logger.debug("Finished 'load'-ing of: %s" % ids)