atomically creating a file lock in MATLAB (file mutex)

后端 未结 5 779
伪装坚强ぢ
伪装坚强ぢ 2021-01-18 18:24

I am looking for a simple already implemented solution for atomically creating a file lock in MATLAB.

Something like:

file_lock(\'create\', \'mylockf         


        
相关标签:
5条回答
  • 2021-01-18 18:46

    At the end I did one implementation based on two consecutive tests (movefile, and verify the contents of the moved file).

    not very well written, but it works for now for me.

    +++++ file_lock.m ++++++++++++++++++++++++

    function file_lock(op, filename)
    %this will block until it creates the lock file:
    %file_lock('create', 'mylockfile') 
    %
    %this will remove the lock file:
    %file_lock('remove', 'mylockfile')
    
    
    % todo: verify that there are no bugs
    
    filename = [filename '.mat'];
    
    if isequal(op, 'create')
      id = [tempname() '.mat'] 
      while true
        save(id, 'id');
        success = fileattrib(id, '-w');
        if success == 0; error('fileattrib'); end
    
        while true
          if exist(filename, 'file');        %first test
            fprintf('file lock exists(1). waiting...\n');
            pause(1); 
            continue;
          end
          status = movefile(id, filename);   %second test
          if status == 1; break; end
          fprintf('file lock exists(2). waiting...\n');
          pause(1);
        end
    
        temp = load(filename, 'id');         % third test.
        if isequal(id, temp.id); break; end
    
        fprintf('file lock exists(3). waiting...\n');
        pause(1)
      end
    
    elseif isequal(op, 'remove')
      %delete(filename);
      execute_rs(@() delete(filename));
    
    else
      error('invalid op');
    end
    
    
    
    function execute_rs(f)
    while true
      try 
        lastwarn('');
        f();
        if ~isequal(lastwarn, ''); error(lastwarn); end  %such as: Warning: File not found or permission denied 
        break;
      catch exception
        fprintf('Error: %s\n.Retrying...\n', exception.message);
        pause(.5);
      end
    end
    

    ++++++++++++++++++++++++++++++++++++++++++

    0 讨论(0)
  • I've settled on a pretty simple solution for combining error/logging messages from multiple worker threads into a single file. Every time I want to write to that file, I first write the output to the thread's own temporary file. Next, I append that temporary file to the "master" log file using flock. Skipping over some details here, the idea is:

    fid=fopen(threadtemp, 'w');
    fprintf(fid, 'Error message goes here');
    fclose(fid);
    
    runme = sprintf('flock -x %s -c ''cat %s >> %s''', LOGFILE, threadtemp, LOGFILE);
    system(runme);
    

    See the flock man page for details, but the call above is acquiring an eXclusive lock on the logfile, running the provided Command under the lock, and then releasing it.

    This obviously only works if you're on a system which has flock (Linux/OS X, and only certain types of file systems at that) and you're doing something that can be done from the command line, but I'd bet that it's a pretty common use-case.

    0 讨论(0)
  • 2021-01-18 18:50

    If you only need to run on OS X and Linux (not Windows), you can use the following:

    pathLock='/tmp/test.lock'
    
    % Try to create and lock this file.
    % In my case I use -r 0 to avoid retrying
    % You could use -r -1 to retry forever, or for a particular amount of time,
    % etc, see `man lockfile` for details.
    if ~system(sprintf('lockfile -r 0 %s',pathLock))
        % We succeeded, so perform some task which needs to be serialized.
        % runSerializedTask()
        % Now remove the lockfile
        system(sprintf('rm -f %s',pathLock));
    end
    
    0 讨论(0)
  • 2021-01-18 18:53

    Depending on which Java version you're using, perhaps this will work (translated from: http://www.javabeat.net/2007/10/locking-files-using-java/)

    classdef FileLock < handle
        properties (Access = private)
            fileLock = []
            file
        end
    
        methods
            function this = FileLock(filename)
                this.file = java.io.RandomAccessFile(filename,'rw');
                fileChannel = this.file.getChannel();
                this.fileLock = fileChannel.tryLock();
            end
    
            function val = hasLock(this)
                if ~isempty(this.fileLock) && this.fileLock.isValid()
                    val = true;
                else
                    val = false;
                end
            end
    
            function delete(this)
                this.release();
            end
    
            function release(this)
                if this.hasLock
                    this.fileLock.release();
                end
                this.file.close
            end
        end
    end
    

    Usage would be:

    lock = FileLock('my_lock_file');
    if lock.hasLock
        %// do something here
    else
        %// I guess not
    end
    %// Manually release the lock, or just delete (or let matlab clean it up)
    

    I like the obj wrapping pattern for IO so that releasing happens even in exceptions

    EDIT: The file ref must be kept around and manually closed or you won't be able to edit this. That means this code is only really useful for pure lock files, I think.

    0 讨论(0)
  • 2021-01-18 19:05

    Write to a new file, then rename it. Renaming is an atomic operation, and all the new content will become visible at once.

    0 讨论(0)
提交回复
热议问题