जोड़ने के लिए खेद है पुराने धागे के लिए कुछ। और इतनी लंबी पोस्ट करने के लिए।
मैं केवल ताला जो लगभग intermittend सर्वर बूट के साथ किसी भी फाइल सिस्टम पर काम करना चाहिए, यहां तक कि एनएफएस पर और ग्राहक समय जगह में warps के अभाव में पूरी तरह से रेस स्थिति मुक्त rename()
करने के लिए एक ही रास्ता पता।
निम्नलिखित नुस्खा दौड़ की स्थिति मुक्त है इस अर्थ में कि किसी भी परिस्थिति में डेटा खो नहीं जा सकता है। इसे ताले की भी आवश्यकता नहीं है और उन ग्राहकों द्वारा किया जा सकता है जो सहयोग नहीं करना चाहते हैं सिवाय इसके कि वे सभी एक ही एल्गोरिदम का उपयोग करते हैं।
यह इस शर्त में मुक्त स्थिति नहीं है कि, अगर कुछ गंभीरता से टूट जाता है, तो सब कुछ साफ-सुथरा राज्य में छोड़ दिया जाता है। इसमें थोड़ी सी अवधि भी है, जहां न तो स्रोत और न ही गंतव्य उनके स्थान पर मौजूद हैं, हालांकि स्रोत अभी भी किसी अन्य नाम के आसपास है। और यह उन मामलों के खिलाफ कठोर नहीं है जहां एक हमलावर नुकसान को उकसाता है (rename()
अपराधी है, आंकड़े जाओ)।
एस स्रोत है, डी गंतव्य, पी (एक्स) dirname(x)
है, सी (एक्स, वाई) x/y
पथ संयोजन
- जाँच लें कि गंतव्य मौजूद नहीं है। बस यह सुनिश्चित करने के लिए कि हम व्यर्थ में अगले कदम नहीं करते हैं। = सी (पी (डी), यादृच्छिक)
- mkdir (टी), अगर यह पिछले चरण
- खुला (सी (टी करने के लिए लूप विफल रहता है, "ताला"), O_EXCL:
- एक शायद अनूठा नाम टी बनाने), इस rmdir विफल रहता है (टी) पिछले चरण
- नाम बदलने (एस, सी (टी, "tmp" करने के लिए त्रुटियों और पाश अनदेखी))
- लिंक (सी (टी, "tmp"), डी)
- अनलिंक (सी (टी, "tmp"))
- अनलिंक (सी (टी, "ताला"))
- rmdir (टी)
एल्गोरिथ्म safe_rename(S,D)
समझाया:
समस्या यह है कि हम यकीन है कि वहाँ कोई रेस स्थिति है, न तो स्रोत पर और न ही गंतव्य पर बनाना चाहते हैं। यह माना जाता है कि, (लगभग) प्रत्येक चरण के बीच कुछ भी हो सकता है, लेकिन अन्य सभी प्रक्रियाएं दौड़ की स्थिति मुक्त नाम करते समय सटीक उसी एल्गोरिदम का पालन करती हैं। इसमें यह भी शामिल है कि अस्थायी निर्देशिका टी को कभी भी छुआ नहीं जाता है, यह सुनिश्चित करने के अलावा (यह एक मैन्युअल प्रक्रिया है) कि निर्देशिका का उपयोग करने की प्रक्रिया मर गई है और पुनरुत्थान नहीं किया जा सकता है (जैसे पुनर्स्थापना के बाद एक वीएम हाइबरनेट जारी रखना)।
rename()
ठीक से करने के लिए, हमें छिपाने के लिए कुछ जगह चाहिए। इसलिए हम एक निर्देशिका को एक तरह से बनाते हैं जो सुनिश्चित करता है कि कोई और (जो एक ही एल्गोरिदम का पालन कर रहा है) गलती से इसका उपयोग करेगा।
हालांकि mkdir()
एनएफएस पर परमाणु होने की गारंटी नहीं है। इसलिए हमें यह सुनिश्चित करने की ज़रूरत है कि हमारे पास कुछ गारंटी है कि हम निर्देशिका में अकेले हैं। यह लॉकफाइल पर O_EXCL
है। यह है - कड़ाई से बोलना - लॉकिंग नहीं, यह एक सैमफोर है।
ऐसे दुर्लभ मामलों के अलावा, mkdir()
आमतौर पर परमाणु है। इसके अलावा हम निर्देशिका के लिए कुछ क्रिप्टोग्राफ़िक रूप से सुरक्षित यादृच्छिक नाम का उपयोग कर सकते हैं, यह सुनिश्चित करने के लिए कुछ GUID, होस्टनाम और पीआईडी जोड़ें कि यह बहुत ही असंभव है कि कोई और मौका से वही नाम चुनता है। हालांकि यह प्रमाणित करने के लिए कि एल्गोरिदम सही है, हमें lock
नामक इस फ़ाइल की आवश्यकता है।
अब हमारे पास अधिकतर खाली निर्देशिका है, हम सुरक्षित रूप से rename()
स्रोत को सुरक्षित कर सकते हैं। यह सुनिश्चित करता है कि जब तक हम unlink()
नहीं करेंगे तब तक कोई भी स्रोत को बदल देता है। (ठीक है, सामग्री बदल सकती है, यह कोई समस्या नहीं है।)
अब link()
चाल को यह सुनिश्चित करने के लिए लागू किया जा सकता है कि हम गंतव्य को ओवरराइट नहीं करते हैं।
बाद में unlink()
शेष स्रोत पर दौड़ की स्थिति मुक्त किया जा सकता है। बाकी सफाई है।
केवल एक ही समस्या छोड़ दिया है:
मामले में link()
विफल रहता है हम पहले से ही स्रोत चले गए हैं। उचित सफाई के लिए हमें इसे वापस ले जाने की जरूरत है। यह safe_rename(C(T,"tmp"),S)
पर कॉल करके किया जा सकता है। यदि यह विफल रहता है, तो हम जितना भी कर सकते हैं, उतना ही हम कर सकते हैं जितना हम कर सकते हैं (unlink(C(T,"lock"))
, rmdir(T)
) और व्यवस्थापक द्वारा मैन्युअल क्लीनअप के लिए मलबे को पीछे छोड़ दें।
अंतिम नोट:
मलबे मामले में साफ करने के लिए मदद करने के लिए, आप संभवतः tmp
की तुलना में कुछ बेहतर फ़ाइल नाम का उपयोग कर सकते हैं। नाम चुपचाप चुनना कुछ हद तक हमलों के खिलाफ एल्गोरिदम को भी कठोर कर सकता है।
और यदि आप कहीं फ़ाइलों के ट्रेन लोड को स्थानांतरित कर रहे हैं तो आप पाठ्यक्रम की निर्देशिका का पुन: उपयोग कर सकते हैं।
हालांकि, मैं मानता हूं कि यह एल्गोरिदम सादा ओवरकिल है और O_EXCL
rename()
पर कुछ गुम है।
शायद आपको एक लंबित लॉकिंग (एक रैपर) नाम बदलने के बजाय एक स्पष्ट लॉकिंग तंत्र का उपयोग करने पर विचार करना चाहिए। यदि 'बी' बनाता है जो आपके नियंत्रण में एक प्रोग्राम है, तो आप संभवतः इंटरप्रोसेस सिंक्रनाइज़ेशन प्राइमेटिव का उपयोग कर सकते हैं। –