ไม่มีการระบุเหตุการณ์ที่ไม่ได้ระบุ


11

ฉันกำลังดูไฟล์สำหรับการเปลี่ยนแปลงโดยใช้ inotify เหตุการณ์ (มันเกิดขึ้นจาก Python โทรเข้า libc)

สำหรับไฟล์บางช่วงgit cloneผมเห็นบางสิ่งบางอย่างที่แปลก: ผมเห็นIN_CREATEเหตุการณ์และฉันเห็นทางlsว่าไฟล์มีเนื้อหา แต่ผมไม่เคยเห็นหรือIN_MODIFY IN_CLOSE_WRITEนี่เป็นสาเหตุให้ฉันมีปัญหาเนื่องจากฉันต้องการตอบกลับIN_CLOSE_WRITEในไฟล์: โดยเฉพาะเพื่อเริ่มต้นการอัปโหลดเนื้อหาไฟล์

แฟ้มที่มีพฤติกรรมผิดปกติอยู่ใน.git/objects/packไดเรกทอรีและพวกเขาสิ้นสุดในหรือ.pack .idxไฟล์อื่น ๆ ที่คอมไพล์สร้างมีเชนมากกว่าปกติIN_CREATE-> IN_MODIFY-> IN_CLOSE_WRITE(ฉันไม่ได้ดูIN_OPENเหตุการณ์)

นี่คือ Docker บน MacOS แต่ฉันได้เห็นหลักฐานของ Docker บน Linux ในระบบรีโมตแล้วดังนั้นความสงสัยของฉันคือ MacOS นั้นไม่เกี่ยวข้องกัน ฉันเห็นสิ่งนี้หากกำลังดูและgit cloneอยู่ในคอนเทนเนอร์นักเทียบท่าเดียวกัน

คำถามของฉัน:

  • เหตุใดเหตุการณ์เหล่านี้จึงหายไปในไฟล์เหล่านี้

  • สิ่งที่สามารถทำได้เกี่ยวกับมันได้หรือไม่ โดยเฉพาะฉันจะตอบสนองต่อความสมบูรณ์ของการเขียนไฟล์เหล่านี้ได้อย่างไร? หมายเหตุ: นึกคิดฉันต้องการตอบสนองเมื่อการเขียนเป็น "เสร็จสิ้น" เพื่อหลีกเลี่ยงความจำเป็น / (ไม่ถูกต้อง) การอัปโหลดการเขียน "ยังไม่เสร็จ"


แก้ไข: การอ่านhttps://developer.ibm.com/tutorials/l-inotify/ดูเหมือนว่าสิ่งที่ฉันเห็นมีความสอดคล้องกับ

  • ไฟล์ชั่วคราวแยกต่างหากที่มีชื่อเหมือนtmp_pack_hBV4Alzกำลังสร้างแก้ไขและปิด
  • สร้างฮาร์ดลิงก์ไปยังไฟล์นี้โดยใช้.packชื่อสุดท้าย
  • tmp_pack_hBV4Alzชื่อเดิมจะถูกลบ

ฉันคิดว่าปัญหาของฉันซึ่งพยายามใช้ inotify เป็นตัวเรียกให้อัปโหลดไฟล์จากนั้นลดการสังเกตว่า.packไฟล์นั้นเป็นการเชื่อมโยงอย่างหนักไปยังไฟล์อื่นและการอัปโหลดในกรณีนี้คืออะไร


คำตอบอาจจะอยู่ที่ไหนสักแห่งที่นี่ ...
choroba

@choroba คุณอาจจะถูกต้อง ... ฉันเห็นการอ้างอิงจำนวนมากไปยัง mmap และ inotify ไม่ได้รายงานการเข้าถึง mmap ให้กับไฟล์
Michal Charemza

1
BTW ปัญหาดั้งเดิมที่คุณพยายามแก้ไข (ด้วย inotify) คืออะไร? อาจมีวิธีแก้ปัญหาที่มีประสิทธิภาพมากกว่านี้ซึ่งพยายามเดาว่ากระบวนการ Git กำลังทำ / เก็บไว้ในที่เก็บข้อมูลหรือไม่?
kostix

@kostix นี่เป็นส่วนหนึ่งของgithub.com/uktrade/mobius3การซิงค์โฟลเดอร์ภายในบ้านของผู้ใช้จากตู้คอนเทนเนอร์ที่ใช้ JupyterLab หรือ RStudio ใน AWS Fargate ไปยังและจาก S3 และในโฟลเดอร์โฮมเหล่านั้นอาจมีโฟลเดอร์. git ฉันรู้ว่าวิธีแก้ปัญหา inotify จะไม่ "แข็งแกร่ง - ทนทาน" ... แต่ฉันหวังว่ามันจะ "แข็งแกร่งเพียงพอ"
Michal Charemza

1
@tink ดูเหมือนว่าคำตอบที่ยอมรับคือแพตช์บนเคอร์เนล Linux หรือไม่ มันจะใช้งานได้ฉันสงสัยโดยทั่วไป แต่ในกรณีของฉันใน Fargate ฉันไม่สามารถควบคุมมันได้ (และฉันยอมรับว่าฉันกลัวผลที่ตามมาเล็กน้อยของการพึ่งพาเคอร์เนลที่ได้รับการติดตั้งในระยะยาวแม้ว่าฉันจะมีพลังนั้น ... )
Michal Charemza

คำตอบ:


5

หากต้องการตอบคำถามแยกต่างหากสำหรับgit2.24.1 บน Linux 4.19.95:

  • เหตุใดเหตุการณ์เหล่านี้จึงหายไปในไฟล์เหล่านี้

คุณไม่เห็นIN_MODIFY/ IN_CLOSE_WRITEเหตุการณ์เพราะgit cloneจะพยายามใช้ฮาร์ดลิงก์สำหรับไฟล์ภายใต้.git/objectsไดเรกทอรี เมื่อโคลนผ่านเครือข่ายหรือข้ามขอบเขตของระบบไฟล์เหตุการณ์เหล่านี้จะปรากฏขึ้นอีกครั้ง

  • สิ่งที่สามารถทำได้เกี่ยวกับมันได้หรือไม่ โดยเฉพาะฉันจะตอบสนองต่อความสมบูรณ์ของการเขียนไฟล์เหล่านี้ได้อย่างไร? หมายเหตุ: นึกคิดฉันต้องการตอบสนองเมื่อการเขียนเป็น "เสร็จสิ้น" เพื่อหลีกเลี่ยงความจำเป็น / (ไม่ถูกต้อง) การอัปโหลดการเขียน "ยังไม่เสร็จ"

ในการตรวจจับการแก้ไขฮาร์ดลิงก์คุณต้องตั้งค่าตัวจัดการสำหรับCREATEเหตุการณ์inotify ซึ่งติดตามและติดตามลิงก์เหล่านั้น โปรดทราบว่าไฟล์ธรรมดาCREATEอาจหมายถึงไฟล์ที่ไม่ได้สร้างไว้ จากนั้นไปที่IN_MODIFY/ IN_CLOSE_WRITEถึงไฟล์ใด ๆ ที่คุณต้องเรียกใช้การกระทำเดียวกันในไฟล์ที่เชื่อมโยงทั้งหมดเช่นกัน เห็นได้ชัดว่าคุณต้องลบความสัมพันธ์นั้นในDELETEเหตุการณ์

วิธีที่ง่ายและมีประสิทธิภาพมากขึ้นอาจเป็นเพียงการแฮชไฟล์ทั้งหมดเป็นระยะและตรวจสอบว่าเนื้อหาของไฟล์มีการเปลี่ยนแปลงหรือไม่


การแก้ไข

หลังจากตรวจสอบgitซอร์สโค้ดอย่างใกล้ชิดและทำงานgitด้วยstraceฉันพบว่าgitใช้ไฟล์หน่วยความจำที่แมป แต่ส่วนใหญ่ใช้สำหรับอ่านเนื้อหา ดูการใช้งานxmmapที่มีการเรียกใช้ด้วยเสมอPROT_READเท่านั้น . ดังนั้นคำตอบก่อนหน้าของฉันด้านล่างไม่ใช่คำตอบที่ถูกต้อง อย่างไรก็ตามเพื่อวัตถุประสงค์ในการให้ข้อมูลฉันยังต้องการเก็บไว้ที่นี่:

  • คุณไม่เห็นIN_MODIFYเหตุการณ์เนื่องจากpackfile.cใช้mmapสำหรับการเข้าถึงไฟล์และinotifyไม่รายงานการแก้ไขสำหรับmmapไฟล์ ed

    จากinotify manpage :

    API inotify ไม่รายงานการเข้าถึงไฟล์และการแก้ไขที่อาจเกิดขึ้นเนื่องจาก mmap (2), msync (2) และ munmap (2)


กลไกการตรวจจับการเปลี่ยนแปลงของฉันขึ้นอยู่กับIN_CLOSE_WRITEซึ่งฉันคิดว่าจะยังคงถูกกระตุ้นเมื่อปิดไฟล์ที่เขียนขึ้นเพื่อใช้mmapเพราะไฟล์จะต้องถูกเปิดในโหมดเขียนหรือไม่?
Michal Charemza

ฉันต้องตรวจสอบสิ่งนี้ แต่ฉันสงสัยว่าไฟล์ที่แม็พหน่วยความจำจะไม่ทริกเกอร์เหตุการณ์ที่ไม่ถูกต้องเลย เหตุการณ์ที่เข้ามาส่วนใหญ่จะเชื่อมโยงกับสถานะของ file descriptor แต่เมื่อคุณmmapมีบางสิ่งที่ไฟล์อาจไม่เป็นระเบียบ ตัวอย่างเช่นคุณยังสามารถเขียนไปยังไฟล์อธิบายเมื่อคุณมีการแม็พไฟล์ลงในหน่วยความจำ
Ente

เกาที่ฉันเพิ่งทดสอบการใช้งานตัวอย่างนี้และฉันจะได้รับCLOSE_WRITE_CLOSEแม้ว่าฉันจะลบcloseและmunmapในตอนท้าย มีการขุดลึกลงไปในการดำเนินงานที่เกิดขึ้นจริงคอมไพล์แล้ว ..
Ente

อืมฉันกำลังดิ้นรนนิดหน่อยในการทบทวนปัญหาของคุณอีกครั้ง ในการทดสอบของฉันด้วยinotifywaitและgit clone(2.24.1) ฉันจะได้รับOPEN-> CLOSE_NOWRITE,CLOSEสำหรับ*.idxไฟล์ บางทีคุณอาจจะลืมที่จะตั้งค่าการจัดการสำหรับCLOSE_NOWRITE,CLOSE? หมายเหตุ: คุณจะได้รับ*NOWRITE*เนื่องจากการเขียนทั้งหมดที่เกิดขึ้นผ่านการแมปหน่วยความจำคือ
Ente

ใช่มีCLOSE_NOWRITE: ปัญหาคือฉันไม่เห็นIN_CLOSE_WRITEและฉันต้องการที่จะตอบสนองต่อไฟล์ "การเปลี่ยนแปลง" เพื่อเรียกการอัปโหลด แต่ไม่สนใจไฟล์ "อ่าน" หมายเหตุฉันคิดว่าจริง ๆ แล้วตอนนี้ข้อ จำกัด mmap + inotify เป็นบิตของปลาเฮอริ่งแดง ฉันคิดว่าปัญหาคือไฟล์.pack/ .idxไฟล์ถูกสร้างขึ้นในขั้นต้นเป็นฮาร์ดลิงก์ไปยังไฟล์อื่นและทริกเกอร์เท่านั้นIN_CREATE(และOPEN-> CLOSE_NOWRITEจะเกิดขึ้นในภายหลังเมื่อ git อ่านไฟล์)
Michal Charemza

2

ฉันอาจคาดเดาได้ว่า Git ส่วนใหญ่ใช้การปรับปรุงไฟล์อะตอมมิกซึ่งทำดังนี้:

  1. เนื้อหาของไฟล์ถูกอ่านในหน่วยความจำ (และแก้ไข)
  2. เนื้อหาที่แก้ไขจะถูกเขียนลงในไฟล์แยกต่างหาก (โดยปกติจะอยู่ในไดเรกทอรีเดียวกับไฟล์ต้นฉบับและมีชื่อแบบสุ่ม ( mktemp-style)
  3. ไฟล์ใหม่จะถูกrename(2)d -d เหนือไฟล์ต้นฉบับ การดำเนินการนี้รับประกันได้ว่าผู้สังเกตการณ์ทุกคนพยายามเปิดไฟล์โดยใช้ชื่อจะได้รับเนื้อหาเก่าหรือใหม่

การอัปเดตดังกล่าวถูกมองinotify(7)ว่าเป็นmoved_toเหตุการณ์ - เนื่องจากไฟล์ "ปรากฏขึ้นอีกครั้ง" ในไดเรกทอรี


อาสำหรับไฟล์บางไฟล์ฉันคิดว่ามันทำอย่างนี้: ฉันเห็นสิ่งต่าง ๆIN_MOVED_FROMและIN_MOVED_TOเหตุการณ์ อย่างไรก็ตามฉันไม่เห็นสิ่งนี้เกิดขึ้นสำหรับไฟล์.packและ.idx
Michal Charemza

ไฟล์แพ็คอาจมีขนาดใหญ่ (อย่างน้อยหลายกิกะไบต์มากถึง 2GiB อย่างน้อยฉันก็เชื่อ) การควงพวกมันโดยใช้การอัปเดตอะตอมมิกอาจถูกห้ามในพื้นที่เก็บข้อมูลดังนั้นจึงอาจมีการอัปเดตโดยใช้กลยุทธ์อื่น
kostix

2

จากคำตอบที่ได้รับการยอมรับฉันคิดว่าอาจมีความแตกต่างในเหตุการณ์ตามโปรโตคอลที่ใช้ (เช่น ssh หรือ https)

คุณสังเกตเห็นพฤติกรรมเดียวกันเมื่อทำการมอนิเตอร์การโคลนจากระบบไฟล์โลคัลด้วย--no-hardlinksตัวเลือกหรือไม่?

$ git clone git@github.com:user/repo.git
# set up watcher for new dir
$ git clone --no-hardlinks repo new-repo

พฤติกรรมที่คุณสังเกตเห็นในการใช้งานการทดสอบทั้งโฮสต์ Linux และ Mac อาจช่วยลดปัญหาที่เปิดอยู่ซึ่งเป็นสาเหตุhttps://github.com/docker/for-mac/issues/896แต่เพิ่มกรณีที่ไม่น่าสนใจ


2

มีความเป็นไปได้อีกอย่างหนึ่ง (จากที่มนุษย์ไม่ได้ระบุไว้):

โปรดทราบว่าคิวเหตุการณ์สามารถล้นได้ ในกรณีนี้เหตุการณ์จะหายไป แอปพลิเคชันที่แข็งแกร่งควรจัดการกับความเป็นไปได้ของเหตุการณ์ที่สูญหายไปอย่างสง่างาม ตัวอย่างเช่นอาจจำเป็นต้องสร้างแอปพลิเคชันแคชบางส่วนหรือทั้งหมดใหม่ (วิธีหนึ่งที่ง่าย แต่อาจมีราคาแพงคือการปิดตัวระบุไฟล์ inotify ล้างแคชสร้างตัวบ่งชี้ไฟล์ inotify ใหม่จากนั้นสร้างรายการเฝ้าดูและแคชใหม่สำหรับวัตถุที่จะตรวจสอบ)

และในขณะที่git cloneสามารถสร้างการไหลของเหตุการณ์ที่หนักหน่วงเหตุการณ์นี้สามารถเกิดขึ้นได้

วิธีหลีกเลี่ยงปัญหานี้:

  1. เพิ่มบัฟเฟอร์การอ่านลอง fcntl (F_SETPIPE_SZ) (วิธีนี้เป็นการเดาฉันไม่เคยลอง)
  2. อ่านเหตุการณ์ในบัฟเฟอร์ขนาดใหญ่ในเธรดเฉพาะประมวลผลเหตุการณ์ในเธรดอื่น

2

บางทีคุณอาจทำผิดพลาดเหมือนฉันเมื่อหลายปีก่อน ฉันใช้การบอกกล่าวเพียงสองครั้งเท่านั้น ครั้งแรกที่รหัสของฉันทำงาน ต่อมาฉันไม่ได้มีแหล่งที่มานั้นและเริ่มต้นอีกครั้ง แต่คราวนี้ฉันหายไปจากเหตุการณ์และไม่รู้ว่าทำไม

ปรากฎว่าเมื่อฉันอ่านเหตุการณ์ฉันกำลังอ่านเหตุการณ์เล็ก ๆ ฉันแยกวิเคราะห์สิ่งที่ฉันคาดหวังโดยคิดว่าเป็นแบบนั้นทั้งหมด ในที่สุดฉันค้นพบว่ามีข้อมูลที่ได้รับมากกว่านั้นและเมื่อฉันเพิ่มรหัสเล็กน้อยเพื่อแยกวิเคราะห์กิจกรรมทั้งหมดที่ได้รับจากการอ่านครั้งเดียวไม่มีเหตุการณ์ใดหายไปอีก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.