2010-12-08 11 views
5

मेरे पास एक निर्देशिका है जिसमें क्लाइंट्स को दी गई डेटा फाइलें हैं, कहें, /srv/data। अपडेट की श्रृंखला बनाते समय, मैं /srv/data_tmp पर काम कर रहा हूं, और ऑपरेशन के अंत में, मैं data पर data_tmp के साथ परमाणु रूप से प्रतिस्थापित करना चाहता हूं। जब गंतव्य एक मौजूदा निर्देशिका है तो File.renameTo() हमेशा मेरे लिए झूठा रिटर्न देता है। मैं यह कैसे कर सकता हूँ?जावा पर किसी अन्य के साथ एक निर्देशिका को परमाणु रूप से कैसे बदलता है?

+0

क्या आपके पास अंतर्निहित फ़ाइल सिस्टम पर कोई बाधा है। जाहिर है, अगर यह एफएटी है, तो फ़ाइल सिस्टम इसका समर्थन नहीं करने के बाद से कोई रास्ता नहीं है। क्या आप जानते हैं कि दो निर्देशिका एक ही भौतिक मात्रा पर हैं या नहीं? क्या आप नए जेडीके 7 java.nio.file एपीआई का उपयोग कर सकते हैं या क्या इसे जेडीके <= 6 पर काम करना है? –

+1

मुझे नहीं लगता कि शब्द की सख्त भावना में, दो फ़ाइल चालन संचालन "परमाणु रूप से" किया जा सकता है। कुछ फाइल सिस्टम कुछ [परमाणु संचालन] (http://www.softpanorama.org/Internals/Filesystems/ntfs.shtml) की गारंटी देते हैं, लेकिन मुझे ओएस से अनुरोध करने के किसी भी तरीके से पता नहीं है कि कई एफएस क्रियाएं सभी के लिए परमाणु रूप से की जाती हैं प्रक्रियाओं; निश्चित रूप से जावा में नहीं। – maerics

+0

@ माइक: मैं एचएफएस +, एक्सटी 3 या एनटीएफएस का उपयोग करूँगा, कभी भी एफएटी नहीं। इसे जेडीके 6 के साथ काम करना चाहिए। –

उत्तर

1

मुझे डर है कि आप नहीं कर सकते हैं। कम से कम एसओ स्तर पर नहीं। इसलिए यदि आप अपने जावा एप्लिकेशन के संदर्भ में "परमाणु" का प्रबंधन करते हैं, तो आपको वास्तविक फाइल सिस्टम स्तर पर हस्तक्षेप करने वाली किसी अन्य "दुष्ट" प्रक्रिया के बारे में कोई गारंटी नहीं है।

यदि मैं आप थे, तो मैं this article पढ़ूंगा (काफी पुराना है, लेकिन आपको कुछ विचार देना चाहिए) और फिर देखें कि क्या आप more modern version पर सुझाए गए दृष्टिकोण को पोर्ट कर सकते हैं या नहीं।

ओह, प्रतीक्षा करें, किसी ने पहले ही this किया है!

और जाहिरा तौर पर अपने the first one to ask here नहीं हैं, या तो

बेस्ट ऑफ लक ...

+0

अपाचे कॉमन्स लेनदेन मुझे करने की अनुमति देता है यह बहुत ही साफ तरीके से है, यद्यपि केवल मेरे जावा ऐप के संदर्भ में। जो अब मेरे लिए पर्याप्त है। आपके लिंक के लिए धन्यवाद! –

1

आप /srv/data निर्देशिका को एक प्रतीकात्मक लिंक (या junction in Windows XP) के साथ प्रतिस्थापित कर सकते हैं, और उचित होने पर लिंक के लक्ष्य को बदल सकते हैं। हालांकि आप जावा 6 एपीआई के साथ ऐसा करने में सक्षम नहीं होंगे - आपको लाइब्रेरी पर भरोसा करना होगा या कमांड लाइन कमांड लिखना होगा।

एनबी: मैं उस ऑपरेशन की परमाणुता के बारे में कुछ भी गारंटी नहीं देता हूं।

+0

पर होंगी प्रतीकात्मक लिंक दृष्टिकोण दिलचस्प है, लेकिन आप गलत कह रहे हैं कि आप फ़ाइल को किसी फ़ाइल में पहले से मौजूद नहीं कर सकते हैं। यदि दोनों ए और बी '/ home/me' में मौजूद हैं, तो यह सफलतापूर्वक बी (ओवर मैक ओएस एक्स/एचएफएस +) पर बी को ओवरराइट करता है: 'नई फ़ाइल ("/home/me/a ")। RenameTo (नई फ़ाइल ("/home/me/b ")' –

+0

ओह, ठीक है। इसकी उम्मीद नहीं थी। –

1

लिनक्स rename सिस्टम कॉल यह (rename सिस्टम कॉल केवल एक खाली निर्देशिका अधिलेखित कर सकते हैं) की अनुमति नहीं है, इसलिए मुझे शक है यह लिनक्स पर जावा में करने के लिए संभव है।

+0

क्या नाम 'नाम बदलें' पर कॉल किया गया है? और यदि ऐसा है, तो ओवरराइटिंग के मामले में भी? –

+0

हां, लेकिन [मैन पेज के अनुसार) ] (http://linux.die.net/man/2/rename) "जब ओवरराइटिंग शायद एक खिड़की होगी जिसमें पुरानीपथ और न्यूपैथ दोनों नाम का नाम बदल रहे हैं।" –

0

इस लक्ष्य को प्राप्त, "सिमलिंक" और "का नाम बदलकर" के संयोजन का उपयोग एक मध्यवर्ती tmp के साथ पूरी तरह संभव है निर्देशिका। निम्न उदाहरण खोल में है, लेकिन आप आसानी अंतर्निहित कॉल का उपयोग करने के लिए यहाँ कार्यक्षमता उसका अनुवाद कर सकें:

mkdir -p tmp/real_dir1 tmp/real_dir2 
touch tmp/real_dir1/a tmp/real_dir2/a 
# start with ./target_dir pointing to tmp/real_dir1 
ln -s tmp/real_dir1 target_dir 
# create a symlink named target_dir in tmp, pointing to real_dir2 
ln -sf tmp/real_dir2 tmp/target_dir 
# atomically mv it into ./ replacing ./target_dir 
mv tmp/target_dir ./ 

उदाहरण यहां से ली गई है: http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/

यह करने पर निर्भर करता (छद्म कोड में):

mkdir('./tmp'); 
mkdir('./tmp/real_dir1'); 
mkdir('./tmp/real_dir2'); 
symlink('./tmp/real_dir1', './target_dir') 
symlink('./tmp/real_dir2', './tmp/target_dir') 
rename('./tmp/target_dir', './target_dir') 

अंतिम नाम यहां परमाणु है, इसलिए कार्रवाई या तो निर्देशिका का उपयोग कर किसी भी प्रक्रिया के बिंदु से पूरी तरह विफल हो जाएगी या विफल हो जाएगी, कार्रवाई परमाणु है।

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

  • कोई संबंधित समस्या नहीं^_^