ملف فتح الملف وحذفه كعملية واحدة
-
20-09-2019 - |
سؤال
يرجى ملاحظة أن هذا ليس مكررًا ملف r/w locking و unlink. (الفرق - منصة. عمليات الملفات مثل القفل والحذف لها دلالات مختلفة تمامًا ، وبالتالي فإن الكبريت سيكون مختلفًا).
لدي مشكلة متابعة. أرغب في إنشاء سعة تخزين جلسة تستند إلى نظام الملفات حيث يتم تخزين كل بيانات جلسة في ملف بسيط يسمى مع معرفات الجلسة.
اريد اتباع واجهة برمجة التطبيقات: write(sid,data,timeout)
, read(sid,data,timeout)
, remove(sid)
حيث SID == اسم الملف ، أريد أيضًا أن يكون لدي نوع من GC الذي قد يزيل جميع جلسات التوقيت.
مهمة بسيطة جدًا إذا كنت تعمل مع عملية واحدة ولكنها ليست تافهة تمامًا عند العمل مع عمليات متعددة أو حتى على المجلدات المشتركة.
أبسط الحلول التي فكرت فيها هي:
write/read:
hanlde=CreateFile
LockFile(handle)
read/write data
UnlockFile(handle)
CloseHanlde(handle)
GC (for each file in directory)
hanlde=CreateFile
LockFile(handle)
check if timeout occured
DeleteFile
UnlockFile(handle)
CloseHanlde(handle)
لكن afiak لا أستطيع الاتصال DeleteFile
على ملف Locked Opended (على عكس Unix حيث لا يكون قفل الملفات إلزاميًا ، يُسمح بإلغاء الملفات المفتوحة.
ولكن إذا وضعت DeleteFile
قد يحدث سيناريو سيئ قفل حلقة سيئ
GC - CreateFile/LockFile/Unlock/CloseHandle,
write - oCreateFile/LockFile/WriteUpdatedData/Unlock/CloseHandle
GC - DeleteFile
هل لدى أي شخص فكرة عن كيفية حل هذه القضية؟ هل هناك أي حيل تسمح بدمج قفل الملف وإزالة الملفات أو إجراء عملية في ملف Atomic (Win32)؟
ملحوظات:
- لا أريد استخدام قاعدة البيانات ،
- أبحث عن حل لـ Win32 API لـ NT 5.01 وما فوق
شكرًا.
المحلول
لا أفهم حقًا كيف من المفترض أن يعمل هذا. ومع ذلك ، فإن حذف ملف يتم فتحه بواسطة عملية أخرى أمر ممكن. يجب أن تستخدم العملية التي تنشئ الملف علامة file_share_delete لسيطة dwSharemode لـ CreateFile (). ستنجح مكالمة حذف لاحقة (). لا يتم إزالة الملف فعليًا من نظام الملفات حتى يتم إغلاق المقبض الأخير.
نصائح أخرى
لديك حاليًا بيانات في السجل تسمح لـ GC بتحديد ما إذا كان السجل قد تم توقيته. ماذا عن تمديد معلومات التدبير المنزلي هذه مع علم "toiledwealreadytimeditout".
GC sets TooLateWeAlreadyTimedItOut = true
Release lock
<== writer comes in here, sees the "TooLate" flag and so does not write
GC deletes
بمعنى آخر ، نستخدم نوعًا من نهج القفل المتفائل. هذا يتطلب بعض التعقيد الإضافي في الكاتب ، لكنك الآن لا تعتمد على أي تجاعيد OS-SPECIFC.
لست واضحا ما يحدث في القضية:
GC checks timeout
GC deletes
Writer attempts write, and finds no file ...
كل ما خططت له لهذه الحالة يمكن أيضًا استخدامه في حالة "toiled"
تم تحريره لإضافة:
لقد قلت أنه من الصحيح أن يحدث هذا التسلسل:
GC Deletes
(Very slightly later) Writer attempts a write, sees no file, creates a new one
يمكن للكاتب أن يعامل علم "toiled" باعتباره مطابقًا لهذه الحالة. إنه يخلق فقط الجديد الملف ، باسم مختلف ، استخدم رقم الإصدار كجزء من اسمه. يتطلب فتح ملف جلسة أول مرة بحثًا عن الدليل ، ولكن يمكنك بعد ذلك تخزين الاسم الأخير في الجلسة.
هذا يفترض أنه لا يمكن أن يكون هناك سوى مؤشر ترابط كاتب واحد لجلسة معينة ، أو أنه يمكننا التوسط بين موضوعين للكاتب إنشاء الملف ، ولكن يجب أن يكون هذا صحيحًا بالنسبة لحالة GC/الكاتب البسيطة.
لنظام التشغيل Windows ، يمكنك استخدام file_flag_delete_on_close خيار CreateFile - سيؤدي ذلك إلى حذف الملف عند إغلاق المقبض. لكنني لست متأكدًا من أن هذا يرضي دلالاتك (لأنني لا أعتقد أنه يمكنك مسح سمة الحذف على قمة.
هنا فكرة أخرى. ماذا عن إعادة تسمية الملف قبل حذفه؟ لا يمكنك ببساطة إغلاق النافذة حيث تأتي الكتابة بعد أن تقرر حذف الملف ولكن ماذا لو قمت بإعادة تسمية الملف قبل حذفه؟ ثم عندما تأتي الكتابة سترى أن ملف الجلسة غير موجود ويعيد إنشائه.
الشيء الرئيسي الذي يجب وضعه في الاعتبار هو أنك ببساطة لا يمكنك إغلاق النافذة المعنية. IMHO هناك حلان:
- إضافة علامة مثل DJNA المذكورة أو
- تتطلب الحصول على كل جلسة تدعى Mutex والتي لها تأثير جانبي مؤسف في تكوينات التسلسل في الجلسة.
ما هو الجانب السلبي لوجود علم toilet؟ بمعنى آخر ، ما الخطأ إذا قمت بحذف الملف قبل الأوان؟ بعد كل نظامك يجب أن يتعامل مع الملف الذي لا يوجد ...