Puncte:3

Sistemul de fișiere „just la timp” folosind inotifywait și mkfifo

drapel ru

Scriu niște middleware brut - practic, am un cod vechi care trebuie să deschidă 100.000 de fișiere numai pentru citire, așteptându-mă să fie toate într-un singur folder. Nu scrie niciodată. Este multiproces, astfel încât poate încerca să deschidă ~ 30 de fișiere în același timp. În mod vechi, ar trebui să copiez de fapt fișierele în acel folder (sau să folosesc linkuri, NFS etc.). De remarcat, nu am capacitatea de a schimba acest cod vechi - este doar un binar.

Am un cod nou, elegant, care poate prelua un fișier aproape instantaneu. Vreau să leg aceste lucruri împreună, astfel încât atunci când vechiul cod încearcă să deschidă fișierul, acesta rulează de fapt, în timp real, noul cod.

Așa că m-am gândit la mkfifo și inotifywait. În loc de un folder de 100.000 de fișiere, pot crea un folder de 100.000 de conducte numite. Până acum, bine. Codul moștenit merge pentru a deschide fișierele, fără să știe că acestea sunt într-adevăr numite conducte. Problema este că nu știu în ce ordine urmează codul moștenit pentru a deschide fișierele (frumos, nu?). Așa că aș dori să declanșez conducta numită WRITE (din noul meu cod elegant) atunci când codul moștenit intră pentru citire. Nu pot genera 100.000 de scrieri și să le blochez pe toate. Așa că m-am gândit că hei - inotifywait are sens. De fiecare dată când moștenirea deschide conducta, declanșează un eveniment de citire, care poate fi apoi folosit pentru a genera pipe writer în fundal. Problema este.. inotifywait nu declanșează evenimentul de citire decât după ce scriitorul a fost generat!

Aveți vreo idee despre cum să rezolvați asta? Practic - vreau să interceptez un fișier deschis, bloc pentru câteva sute de ms în timp ce recuperez conținutul fișierului, apoi returnez acel conținut. În mod ideal, nu trebuie să creez un sistem de fișiere FUSE personalizat pentru a face acest lucru... este doar un fișier deschis doar pentru citire. Problema este că trebuie să ruleze rapid și în paralel... și nu știu ce fișiere vor fi deschise în ce ordine. Trebuie să fie un mod rapid și murdar!

Mulțumesc anticipat pentru timpul acordat tuturor.

EDIT - pentru mai multe detalii. Practic, am un cod moștenit care vrea să încarce un folder plin de fișiere PNG. Vreau ca acele fișiere PNG să provină de fapt de la un server web care returnează fișiere DICOM. Acest lucru necesită o conversie urâtă etc. Codul de încărcare PNG moștenit este foarte inflexibil.. se așteaptă ca aceste lucruri să fie fișiere. Deci, practic, vreau să interceptez fopenul codului de încărcare PNG și să rulez mai întâi următoarele patru linii de pseudocod bash. The $URL_FOR_DICOM de mai jos poate fi derivat din $LADY_LOADED.png nume de fișier.

wget -q -O $LAZY_LOADED.dcm $URL_FOR_DICOM
dcmj2pnm --write-png $LAZY_LOADED.dcm $LAZY_LOADED.png
rm $LAZY_LOADED.dcm
converti $LAZY_LOADED.png -redimensionare 1024x1024^ -centrul de gravitație -extent 1024x1024 $LAZY_LOADED.png

Deci, atunci când încărcătorul PNG încearcă să se încarce $LAZY_LOADED.png (care este de fapt un FIFO), ar fi populat folosind cele de mai sus, declanșate în mod ideal de inotify. Nu pot face acest lucru în avans, deoarece setul de date este masiv - ca aproape de 0,5 PB.. deci nu pot avea oa doua copie în jur, am nevoie să fie încărcat din mers de pe serverul web.

EDITARE 2- când încercați ifnotifywait pe o conductă numită, blochează ORICE evenimente (inclusiv deschidere, acces, citire etc.) până când conducta numită este deschisă pentru scriere și citire... (adică nu există nicio modalitate de a detecta că cititorul este gata). .idei? Un alt utilizator a avut o problemă similară Aici fara solutie :(

Puncte:3
drapel ca

Dacă aveți nevoie să fie „rapid și paralel”, vă rugăm să încercați din greu să nu reinventați roata: sistemul de fișiere din kernel și pagecache sunt specific reglat pentru a fi foarte rapid, mult mai rapid decât „sistemul de fișiere în spațiul utilizator” personalizat.

Aveți mai multe opțiuni mai bune:

  • copiați fișierul într-o locație temporară;
  • chiar mai bine, mai degrabă copierea lor, folosește link-uri soft sau hard;
  • exportați-le printr-o montură NFS doar pentru citire

În cele din urmă, rețineți că inotify este a cel mai bun efort cadru pentru a livra evenimente de fișier. În cazul unei sarcini grele, notificările pot fi pierdute, mai ales dacă utilizați o legare de limbaj de nivel înalt (de exemplu: python).

EDITAȚI | ×: deci doriți să interceptați citirile pentru conversia de fișiere din mers.Când citiți dintr-o țeavă goală, codul dvs. moștenit se va bloca, deci inotifywait va afișa evenimentul READ numai după ce ați scris ceva în același canal. Pentru a evita problema, ar trebui să încercați să ascultați evenimente OPEN (în loc să citiți). O altă opțiune este să utilizați LD_PRELOAD pentru a înlocui apelul de sistem open() clasic cu o versiune personalizată care va converti fișierul după cum este necesar.

drapel ru
Multumesc pentru raspunsul foarte rapid - problema pe care o am este...sursa nu sunt fișiere. Sursa este un serviciu web care returnează imagini, care trebuie convertite, redimensionate și decupate. Nu am cum să am suficient spațiu pentru a copia totul (300 de terabytes în realitate).. așa că trebuie făcut „just la timp”. În mod ideal, aș putea doar link-ul simbolic către directorul sursă al serviciului web.. dar... acestea sunt pe o altă mașină și, de asemenea, într-un format binar proprietar de furnizor, accesibil doar de serviciul web. Vreo idee??
drapel ru
Am adăugat câteva informații mai sus la întrebarea principală - vă mulțumesc din nou
shodanshok avatar
drapel ca
@mohotmoz Mi-am editat răspunsul adăugând detalii suplimentare.
drapel ru
mulțumesc mult! deci când încerc să ascult pentru TOATE evenimentele.. nu apare nimic decât după ce deschid conducta de la celălalt capăt. când încerc doar evenimente OPEN.. încă nu funcționează : ( nimic până când deschid conducta de la celălalt capăt și încep să scriu. Altcineva a avut această problemă: https://stackoverflow.com/questions/67639932/how-can-i-use-inotify-to-tell-when-a-named-pipe-is-opened
shodanshok avatar
drapel ca
@mohotmoz bine, așa că se pare că inotify nu funcționează pe o conductă neconectată - ceea ce este un rezultat rezonabil. Dacă da, și presupunând că nu puteți modifica codul moștenit, trebuie să deschideți (și să păstrați deschis) capătul conductei sau să supraîncărcați funcția open() prin LD_PRELOAD
Nonny Moose avatar
drapel gb
Ați prezentat ideea LD_PRELOAD ca pe o idee ulterioară, dar ar putea fi calea de urmat aici. Cu siguranță mult mai ușor decât să încerci să faci o copiere just-in-time.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.