2009-01-06 18 views
11

यह शायद पिछली पोस्ट के समान है, लेकिन मैं स्थानीय रूप से नेटवर्क पर लॉकिंग के उपयोग के बारे में विशिष्ट होना चाहता हूं। मैं एक साझा स्थान पर एक फाइल लिखना चाहता हूं, इसलिए यह नेटवर्क पर जा सकता है (निश्चित रूप से एक विंडोज नेटवर्क, शायद मैक)। मैं अन्य लोगों को इस फाइल के किसी हिस्से को पढ़ने से रोकना चाहता हूं, जबकि इसे लिखा जा रहा है। यह एक अत्यधिक समवर्ती प्रक्रिया नहीं होगी, और फाइलें आम तौर पर 10 एमबी से कम होंगी।नेटवर्क पर जावा फ़ाइल लॉकिंग

मैंने FileLock प्रलेखन और File दस्तावेज पढ़ा है और कुछ हद तक उलझन में है, जो सुरक्षित है और क्या नहीं है। मैं इसके भाग के बजाए पूरी फाइल को लॉक करना चाहता हूं।

क्या मैं FileChannel.tryLock() का उपयोग कर सकता हूं, और यह नेटवर्क पर सुरक्षित है, या यह नेटवर्क के प्रकार पर निर्भर करता है? क्या यह एक मानक विंडोज नेटवर्क पर काम करेगा (यदि ऐसी कोई चीज है)।

यदि यह काम नहीं करता है, तो शून्य बाइट फ़ाइल या निर्देशिका को लॉक फ़ाइल के रूप में बनाने की सबसे अच्छी बात है, और फिर मुख्य फ़ाइल लिखें। वह File.createNewFile() प्रलेखन कहता है कि फ़ाइल लॉकिंग के लिए इसका उपयोग क्यों न करें? मैं सराहना करता हूं कि यह दौड़ की स्थिति के अधीन है, और आदर्श नहीं है।

उत्तर

5

यह किसी नेटवर्क फ़ाइल सिस्टम पर विश्वसनीय रूप से नहीं किया जा सकता है। जब तक आपका एप्लिकेशन एकमात्र एप्लिकेशन है जो फ़ाइल तक पहुंचता है, तो किसी भी प्रकार की सहकारी लॉकिंग प्रक्रिया को कार्यान्वित करना सर्वोत्तम होता है (संभवतः फ़ाइल खोलने पर नेटवर्क फाइल सिस्टम में लॉक फ़ाइल लिखना)। हालांकि, अनुशंसित नहीं होने का कारण यह है कि यदि आपकी प्रक्रिया दुर्घटनाग्रस्त हो जाती है या नेटवर्क नीचे चला जाता है या कोई अन्य समस्या होती है, तो आपका आवेदन एक गंदे, गंदे राज्य में आता है।

3

आपके पास एक खाली फ़ाइल हो सकती है जो आप जिस सर्वर पर लिखना चाहते हैं उस पर झूठ बोल रही है।

जब आप सर्वर पर लिखना चाहते हैं तो आप टोकन पकड़ सकते हैं। केवल तभी जब आपके पास टोकन होता है तो आपको सर्वर पर झूठ बोलने वाली किसी भी फाइल को लिखना चाहिए।

जब आप फ़ाइल ऑपरेशन के साथ तैयार हों या अपवाद फेंक दिया गया तो आपको टोकन जारी करना होगा।

सहायक वर्ग

private FileLock lock; 

private File tokenFile; 

public SLTokenLock(String serverDirectory) { 
    String tokenFilePath = serverDirectory + File.separator + TOKEN_FILE; 
    tokenFile = new File(tokenFilePath); 
} 

public void catchCommitToken() throws TokenException { 
    RandomAccessFile raf; 
    try { 
     raf = new RandomAccessFile(tokenFile, "rw"); //$NON-NLS-1$ 
     FileChannel channel = raf.getChannel(); 
     lock = channel.tryLock(); 

     if (lock == null) { 
      throw new TokenException(CANT_CATCH_TOKEN); 
     } 
    } catch (Exception e) { 
     throw new TokenException(CANT_CATCH_TOKEN, e); 
    } 
} 

public void releaseCommitToken() throws TokenException { 
    try { 
     if (lock != null && lock.isValid()) { 
      lock.release(); 
     } 
    } catch (Exception e) { 
     throw new TokenException(CANT_RELEASE_TOKEN, e); 
    } 
} 

आपका संचालन की तरह लग सकता है तो

try { 
     token.catchCommitToken(); 

     // WRITE or READ to files inside the directory 
    } finally { 
     token.releaseCommitToken(); 
    } 
1

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

नकारात्मकता यह है कि अतिरिक्त आईओ के बिना छिपाने और/या नामकरण के लिए आपको देशी ओएस कमांड का उपयोग करने की आवश्यकता हो सकती है, लेकिन ऐसा करने की प्रक्रिया काफी सरल और निर्धारक होना चाहिए।

4

मुझे यह बग रिपोर्ट मिली जो बताती है कि क्यों फ़ाइल लॉकिंग के बारे में नोट File.createNewFile दस्तावेज़ में जोड़ा गया था।

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4676183

इसमें कहा गया है:

आप से पहले deleteOnExit के रूप में फ़ाइल को चिह्नित लागू createNewFile लेकिन फ़ाइल पहले से मौजूद हैं, तो आप आप का निर्माण नहीं किया एक फ़ाइल को हटाने का जोखिम हो सकता है और किसी को एल्स लॉक छोड़ना! दूसरी तरफ, यदि आप फ़ाइल बनाने के बाद फ़ाइल को चिह्नित करते हैं, तो आप परमाणुता खो देते हैं: यदि प्रोग्राम चिह्नित होने से पहले प्रोग्राम से बाहर निकलता है, तो यह हटा नहीं जाएगा और लॉक "wedged" होगा।

तो यह की तरह मुख्य कारण ताला() है कि आप अगर JVM अप्रत्याशित रूप से समाप्त हो जाता है इससे पहले कि आप इसे हटा करने का मौका दिया अनाथ ताला फाइलों के साथ खत्म हो सकता है File.createNewFile साथ हतोत्साहित किया जाता है लग रहा है। यदि आप अनाथ लॉक फाइलों से निपट सकते हैं तो इसे सरल लॉकिंग तंत्र के रूप में इस्तेमाल किया जा सकता है। हालांकि, मैं बग रिपोर्ट की टिप्पणियों में सुझाई गई विधि की अनुशंसा नहीं करता क्योंकि इसमें टाइमस्टैम्प मूल्य को पढ़ने/लिखने और समाप्त होने वाले लॉक को पुनः प्राप्त करने के आसपास दौड़ की स्थिति है।

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