2010-08-10 15 views
5

में एक फ़ाइल लॉक बना रहा है, मैं MATLAB में फ़ाइल लॉक को परमाणु रूप से बनाने के लिए एक सरल पहले से लागू समाधान की तलाश में हूं।परमाणु रूप से MATLAB (फ़ाइल mutex)

कुछ की तरह:

file_lock('create', 'mylockfile'); %this will block until it creates the lock file. 
file_lock('remove', 'mylockfile'); %this will remove the lock file: 

यह सवाल पहले से ही कई बार कहा गया है, कुछ प्रस्तावित समाधान विचारों (जैसे जावा FileLock का उपयोग कर के रूप में), साथ, लेकिन मैं एक साधारण पहले से ही लागू किया समाधान नहीं मिला।

क्या आप इस तरह के एक लागू समाधान के बारे में जानते हैं?

नोट्स:

+3

मैं एक गीला कंबल होने के लिए नफरत है, लेकिन यह एक में सही पाने के लिए बहुत मुश्किल है सामान्य रूप से, विशेष रूप से नेटवर्क फ़ाइलों के लिए। फ़ाइल लॉकिंग अत्यधिक प्रणाली निर्भर है। कोई आसान, पहले से लागू समाधान नहीं होगा जो टूटा नहीं है। (ऐसा कुछ लिखना मुश्किल नहीं है जो "अधिकतर काम करता है"; ऐसा कुछ लिखना मुश्किल है जो उत्पादन में असफल नहीं होगा।) चलो एक पल वापस कदम: आप किस तक पहुंच को सिंक्रनाइज़ करने की कोशिश कर रहे हैं? क्या यह फ़ाइल सामग्री है, या फाइलें कुछ अन्य संसाधनों का प्रतिनिधित्व करती हैं? आप किस प्लेटफॉर्म को लक्षित कर रहे हैं? आपको "सही" कैसे बहिष्कार की आवश्यकता है? –

उत्तर

0

एक नई फ़ाइल में लिखें, तो यह नाम बदलें। नामकरण एक परमाणु ऑपरेशन है, और सभी नई सामग्री एक बार में दिखाई देगी।

+0

यह विचार http://groups.google.com/group/comp.soft-sys.matlab/browse_thread/thread/eb4ebeb8700ea440/13bd6710e8429a70?lnk=raot में भी प्रस्तावित किया गया था, लेकिन यह पता चला है कि यूनिक्स का नाम परमाणु नहीं है (सबसे पहले यह dest फ़ाइल को हटा देता है, फिर स्रोत फ़ाइल का नाम बदलता है), और मैटलैब यूनिक्स में यूनिक्स के नाम का उपयोग करता है, इसलिए यह समाधान न तो काम करता है। –

+0

बस उस धागे को पढ़ें। सर्वसम्मति यह प्रतीत होती है कि MatLab की 'movefile' कमांड केवल एक ही नाम 'नाम' कॉल से अधिक है, इसलिए 'movefile' परमाणु नहीं है। एसयूएस स्पष्ट है कि 'नाम बदलें' यूनिक्स पर परमाणु है (बेशक, यदि आप एक यूनिक्स-जैसे क्लोन का उपयोग कर रहे हैं जो कि एक अलग कहानी की कल्पना का पालन नहीं करता है)। http://opengroup.org/onlinepubs/007908775/xsh/rename.html –

0

अंत में मैंने लगातार दो परीक्षणों (movefile, और स्थानांतरित फ़ाइल की सामग्री को सत्यापित करने के आधार पर एक कार्यान्वयन किया)।

बहुत अच्छी तरह से लिखा नहीं है, लेकिन यह मेरे लिए अभी काम करता है।

+++++ 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

मुझे लगता है कि यदि कोई कार्यकर्ता 'movefile' से पहले बाधित है तो आपको कोई समस्या है। –

5

मैं के संयोजन के लिए एक बहुत सरल समाधान पर बसे गया है एकाधिक कार्यकर्ता थ्रेड से संदेशों को एक फ़ाइल में त्रुटि/लॉगिंग करना। हर बार जब मैं उस फ़ाइल को लिखना चाहता हूं, तो मैं पहले थ्रेड की अपनी अस्थायी फ़ाइल में आउटपुट लिखता हूं। इसके बाद, मैं उस अस्थायी फ़ाइल को झुंड का उपयोग करके "मास्टर" लॉग फ़ाइल में जोड़ता हूं। यहाँ कुछ विवरण पर छोड़ा जा रहा है, विचार है:

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); 

जानकारी के लिए झुंड आदमी पृष्ठ देखें, लेकिन कॉल ऊपर लॉगफ़ाइल पर एक विशेष ताला प्राप्त है, ताला के तहत प्रदान की कमान चल रहा है, और फिर इसे जारी ।

यह स्पष्ट रूप से केवल तभी काम करता है जब आप उस प्रणाली पर हों जिसमें झुंड (लिनक्स/ओएस एक्स, और उसमें केवल कुछ प्रकार के फाइल सिस्टम हैं) और आप कुछ ऐसा कर रहे हैं जो कमांड लाइन से किया जा सकता है, लेकिन मैं शर्त लगाता हूं कि यह एक बहुत ही सामान्य उपयोग-मामला है।

+0

बस सोच रहा है, आप अस्थायी फ़ाइल बनाने के चरण के माध्यम से क्यों जाते हैं? क्यों न सिर्फ सिस्टम की तरह कुछ ('flock -x logfile -c' 'echo errormessage >> logfile' '') क्यों? धन्यवाद – Grittathh

+0

कोई विशेष कारण नहीं - आपके दृष्टिकोण को ठीक काम करना चाहिए। मुझे लगता है कि मेरे कुछ मूल कार्यों ने लॉग इन करने के लिए फ़ाइल नाम लिया, इसलिए यह मुझे बिना परिवर्तन किए उन्हें उपयोग करने देता है, लेकिन मुझे लगता है कि यह ज्यादातर vestigial है, मुझे लगता है। एकमात्र असली चाल फ्लॉक कॉल करने के लिए सिस्टम() का उपयोग कर रही है। –

1

निर्भर करता है जो जावा संस्करण पर आप का उपयोग कर रहे शायद यह काम करेंगे (से अनूदित 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 

प्रयोग होगा:

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) 

मैं आईओ के लिए obj रैपिंग पैटर्न की तरह ताकि रिलीज भी अपवादों में हो सकता है

संपादित करें: फ़ाइल रेफरी को चारों ओर रखा जाना चाहिए और मैन्युअल रूप से बंद होना चाहिए या आप इसे संपादित करने में सक्षम नहीं होंगे। इसका मतलब है कि यह कोड केवल शुद्ध लॉक फ़ाइलों के लिए वास्तव में उपयोगी है, मुझे लगता है।

0

आप केवल ओएस एक्स और लिनक्स (नहीं Windows) पर चलाने के लिए की जरूरत है, तो आप निम्न का उपयोग कर सकते हैं:

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

ध्यान दें कि इस तरह के दृष्टिकोण नेटवर्क किए गए फाइल सिस्टम पर सुरक्षित हैं या नहीं, इस बारे में बहुत सी चर्चा है। लॉकफाइल मैन पेज का कहना है कि यह "एनएफएस-प्रतिरोधी" है, लेकिन मुझे यकीन नहीं है कि इसका मतलब क्या है :) या क्या इसमें इस बारे में सभी चिंताओं को शामिल किया गया है (वे काफी जटिल हो जाते हैं!) – nonagon

संबंधित मुद्दे