Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]operacje na plikach
Forum PHP.pl > Forum > Przedszkole
gitbejbe
Witam.

Mam pewien problem, któremu nie mogę w żaden sposób zaradzić.

Mam dosyć mocno rozbudowany system cachowania oparty na plikach txt.
Mój skrypt obsługuje pobór informacji z urządzeń pomiarowych, które odpowiednio konwertuje i zapisuje do indywidualnego pliku cache takiego urządzenia na serwerze.

Nadmienie, ze wszystkie urządzenia wysyłają dane co 3 sekundy.

Stworzyłem sobie stronę na której zrobiłem podgląd skryptu obsługi danych przychodzących. Strona działa asynchronicznie(ajax) przez co widzę "na żywo" co się dzieje w plikach - czyli jakie informacje dochodzą z urządzeń.

Wszystko działa ok, po za jedną rzeczą. Czasami gdy zamknę te okno podglądu plików to dla niektórych plików cache kasuje się całą zawartość. Problem ten występuje sporadycznie, czasami jest ok a czasami np treść paru plików ulega wykasowaniu

Skrypt obsługujący pliki napisany jest tak, że przy zapisie danych pliki są blokowane do czasu zakończenia wszystkich operacji. Pliki zapisywane są z praw " w " - czyli do nadpisu, przy czym dokładnie sprawdzam, czy nowe dane zostały zapisane i czy nie wystapił przy tym jakiś błąd.


Zastanawiam się, czy jest taka możliwość, że gdy zamykam okno z podglądem całego procesu to tym samym jakiś skrypt moze się do końca nie wykonać przez co plik zostaje pusty ?
Problem pojawia się tylko w tym przypadku, robiłem testy gdzie urzadzenia wysyłały przez kilka godzin dane nawet co 0.10 sekundy i wszystko było ok.

EDIT

trochę źle przedstawiłem temat:

urzadzenia pomiarowe sa obecnie "wirtualne". Strona z podglądem o której wspomniałem uruchamia ajaxa, który symuluje wirtualne urzadzenie i wysyła dane POSTE'm do skryptu php. Php zwraca html'a z ważnymi dla mnie informacjami i tak wlasnie wygląda ten "podgląd". Czyli podsumowując, to ajax uruchamia skrypt php który cachuje dane.
Jeśli wyłącze ta strone z ajaxem, to dla niekórych plików kasuje sie treść.
!*!
Cytat
Zastanawiam się, czy jest taka możliwość, że gdy zamykam okno z podglądem całego procesu to tym samym jakiś skrypt moze się do końca nie wykonać przez co plik zostaje pusty ?


Cytat
Czyli podsumowując, to ajax uruchamia skrypt php który cachuje dane.


Skoro już znalazłeś winnego, to idź tą drogą i wyeliminuj błąd.
gitbejbe
testuje już ten skrypt pod każdym możliwym kątem i jak bym nie kombinował to ciągle jest lipa.

Do czego doszedłem ?

plik cache musi być nadpisywany, czyli dla fopen musze nadać prawo "w".

sprawdzam w skrypcie, czy treść, którą chce zapisać istnieje. Jeśli nie to zamykam plik bez zapisu i przerywam dalsze wykonywanie. Wszystko jest ok, jeśli ja z własnej reki nie przerw skryptu zamykając okno przeglądarki. Zaobserwowałem, ze nieważne jak to wszystko zabezpiecznie, to jeśli plik otwierany jest z prawem "w" to potrafi on nie zapisać się, jeśli podczas procesu zamknie się okno przeglądarki lub np zacznę bardzo szybko odświeżać stronę (przypomne, że każde takie odświeżenie wysyła aż 1000 zapytań ajax do php)

Poprawcie mnie jeśli się myle:

Jesli wchodze pod dany adres, to serwer najpierw otwiera odpowiednie pliki. Wczytuje z nich informacje php i na ich podsatwie wykonuje konkretne operacje. Czyli jeśli przerwe ten proces wczytywania pliku to skrypt nie wykona się, lub wykona się niekompletnie/źle ? Dlatego moje pliki cache stają sie sporadycznie puste ? Bo serwer nie zdążył wykonać np operacji zapisu do pliku ?

wydaje mi się, że to na pewno chodzi o to, ale wolałem zapytać. W zasadzie to nie jest problem bo przy normalnej pracy mojego skryptu gdy urzadzenia pomiarowe będą wysyłać informacje to raczej nic nie przerwie pracy serwera.
!*!
Skoro uruchamiasz ajax do podglądu, to czemu w tym samym procesie emulujesz urządzenie? Odpal skrypt emulatora np. z konsoli jako osobny proces i osobno skrypt od ajaxa, bo on ma być tylko podglądem i wtedy w nim sprawdzaj czy pliki cache istnieją oraz jaką ma wartość, bo zakładam że skoro istnieje to coś musi w nim być.

Cytat
Bo serwer nie zdążył wykonać np operacji zapisu do pliku ?

Jeśli ajax i emulator to ten sam proces, to teoretycznie tak. Trudno to ocenić bez kodu.
phpion
Wygląda mi to na sytuację, jaka zdarzała się z licznikami odwiedzin opartymi na plikach. One również czasem się czyściły. Czy zakładasz blokadę na plik (flock)?
gitbejbe
phpion

tak , zakładam/ściagam flock'i, sprawdzam czy funkcja file() pobiera tablice z pliku itd itp. Wszystko jest na cacy i działa jeśli ja w to nie ingeruje np poprzez bardzo szybkie odświeżanie przeglądarki. Mam też bardzo liczne raportowanie błędów i każdą możliwa kolizja jest od razu wyswietlana w postaci bledu. Moge uruchomić podgląd tych 1000 urządzeń w kilku oknach przegladarki - co oznacza, że wszystko będzie wykonywać się jeszcze częsciej i też jest ok - oczywiście wtedy zaczynają działac moje obsługi błedów bo kilka procesów chce wejść na jeden plik.


!*!

ajax wysyła mi dane POSTE'm do pliku php ze skryptem obsługi cachowania. W skrypcie php porobiłem specjalnie "echo" błedów jak i niektórych informacji, tak aby ajax mi te informacje zwrócił.

wybrałem ajaxa do uruchaminia skryptu bo to wszystko narazie fazy testów. W późniejszym czasie tego ajaxa zastąpią prawdziwe urzadzenia pomiarowe. Zamiast ajaxa użyłem wczesniej curla, który cyklicznie wysyłał informacje, ale teraz padło na ajaxa z przyczyn niezaleznych ode mnie - programiści C chcą widzieć co sie dzieje, bez instalowania np xamppa

kodu nie będe wklejał bo jest go od cholery, ale naprawde innego wytłumaczenia nie widze.

FINALNIE

schemat problemu:

->przychodzą mi dane z urządzenia pomiarowego
->skrypt je analizuje i przetwarza do odpowiedniej postaci
->jeśli wszystko ok to otwiera plik z prawami zapisu "w"
->jeśli plik nie jest zablokowany to zapisuje dane
->zamyka plik

no i w kroku zapisu danych się sypie

EDIT

chyba poradziłem ! ohmy.gif

chodziło o to, że w przestrzeni FOPEN wykonywałem jeszcze operacje na (duuużej)tablicy z danymi do zapisu i dopiero zapisywałem przetworzone dane. Czyli po otwarciu pliku do zapisu, skrypt musiał zmarnować jeszcze trochę czasu zanim został zapisany. Narazie testuje i jest ok, odświeżam przeglądarke i nci sie nie kasuje ! Czyli teoria o tym, że skrypt może nie zdążyć zapisac informacji jest prawdziwa!


EDIT 2

DZIAŁA : )

tak, chodziło o to co napisałem powyżej. Jeśli ktoś kiedyś będzie miał podobny problem do mojego lub będzie chciał zacząć pracowac na plikach, to przestrzegam, że w momencie otwarcia pliku przez fopen nie wykonujcie żadnych dodatkowych operacji oprócz zapisu. Nawet jesli blokujecie pliki itd ale wykonujecie obciążające operacji w momencie gdy plik jest otwarty z prawem "w", to usunie wam całą zawartosc pliku jesli skrypt nie zdąży się wykonać - np ktoś odświeży strone.

Dzieki za pomoc : ) Pozdrawiam
ctom
1000 urządzeń wyśle Ci dane co 3 sek. ? - chyba I/O będziesz miał kosmiczne nawet przy dyskach SSD

nie myślałeś by to zrobić w oparciu od noSQL - np. REDIS ?
com
dlaczego dalej upieracie się przy file z php4 jak w 5 wprowadzili o wiele lepszy mechanizm http://www.php.net/file_get_contents i http://www.php.net/manual/en/function.file-put-contents.php gdzie również możesz założyć LOCK_EX przy zapisie wink.gif

Albo tak jak zasugerował ctom REDIS
gitbejbe
com

znam tą funkcje ale file() pobiera mi treść od razu do tablicy i zwraca boolen jeśli plik jest pusty - a tego właśnie potrzebuje. Nie wiem jak to akurat ma się w file_get_content - nie czytałem dokumentacji. Chyba, że wydajnościowo jest spora różnica ?

ctom

nie wydaje mi się, moj skrypt - mimo, że jest mocno skomplikowany pod względem logicznym, obsługuje cachowanie takiego jednego urzadzenia średnio w 0.008sekundy. Aktualnie teraz przy testach jest tak, że na raz wysyła mi się 1000 urządzeń na raz i nie ma problemu. Jeśli będe miał już prawdziwe urządzenia to sprawa będzie bardziej dogodna, bo raczej wątpie aby więcej niz 100 urzadzeń wysłało dane w tym samym czasie
com
Cytat
On failure, file_get_contents() will return FALSE.
-gitbejbe-
no dobra, nie wątpie w to, ze zwraca wartość boolen, ale jaka jest znacząca różnica dla której lepiej korzystać z tej funkcji zamiast file() ? Dla mnie w sumie najistotniejsza jest wydajność, wiesz coś o tym ?

z tego co się domyślam:
file_get_content najpierw pobierana jest treść, którą dopiero później można przenieść do tablicy.
file() od razu pobiera tablice

jeśli chodzi o funkcje z php 4 a 5, to jeśli coś działa dobrze z 4 i nie jest pod flagą Deprecated to dlaczego mam tego nie używać ?

co do noSQL, mój skrypt wykonuje zbyt dużo operacji, dochodzi do tego spora złożoność danych i wykorzystanie do tego jakiejkolwiek bazy danych mija się z wydajnością. Nic nie przebije plików : ) a do tego co robie nadają się one idealnie (choć też jestem zwolennikiem bazowania)
ctom
to Twój projekt i mogę się mylić ale śmiem wątpić, że składowanie danych przez REDIS będzie mniej wydajne niż przy Twoim rozwiązaniu.

nie wiem jakie i ile danych ma jedna porcja ale robiłeś testy w szerszym zakresie czasowym ( chodzi mi o przyrost wielkości pliku i jego wpływ na wydajność całego rozwiązani).
-gitbejbe-
oczywiście

nie martw się : ) projekt został bardzo dobrze przemyślany pod każdym kątem. Pliki cache są przy każdym zapisie odpowiednio modyfikowane. Na potrzeby całej aplikacji składowane są różne ilości danych w pliku. Jest tutaj ogrom zależności i dlatego o wiele łatwiej i wydajniej robić to na plikach. Testy prowadze ciągle na 3 sekundach - bo to nasza minimalna ustalona wartość z jaką urządzenie moze wysyłać dane. Maksymalna wartość to jedna minuta. Zakres to po prostu wielokrotność 3 sekund aż do minuty.

rozmiar pliku jest zalezny od częstotliwości wysyłania danych. Maksymalna ilość linii = 1200 (3sekundy *20 = 60 (1 minuta) * godzina = 1200 linii), długość wiersza z reguły nie więcej niż 400znaków. rozmiar tych największych plików to coś koło 15kb. I mowa tutaj o plikach cache urzadzeń, które wysyłają dane co 3 sekundy. Jeśli wysyła rzadziej to plik automatycznie zajmuje mniej linijek.

Dane z pliku archiwizowane są do bazy zawsze co godzine(wyliczam z ilości modyfikacji pliku a nie od stałej godziny serwera) i kasowane z pliku. Zachodzi tutaj stosunek, w którym łatwo można ustalić co którą modyfikacje pliku robić archiwizacje. Proces jest mocno rozbudowany/zautomatyzowany i na pewno dobrze go tutaj nie przedstawie, a zresztą nie po to założyłem ten temat : )

REDIS to świetne narzędzie ale tutaj jestem pewniejszy plików. Po za tym dochodzą jeszcze do tego wykresy i inne pierdoły już w samej aplikacji po stronie klienta, które wymagają również szybkiego i cyklicznego dostępu do danych. Chcę ograniczyć do minimum zależność od bazy danych - która akurat tutaj służy mi tylko do archiwizacji.
-gitbejbe-
po za tym dodam jeszcze, średni czas całego wykonania skryptu na pliku zajmuje średnio 0,008sekundy. REDIS i żadna inna baza danych z pewnością nie wykona tego szybciej biorąc pod uwagę to, ile w miedzy czasie wykonuje operacji na danych w skrypcie. Nie wiem akurat jak to jest w noSQL ale w relacyjnych np biorąc takiego mySQL, samo połączenie z bazą trwa 0,025 sek ; ). więcej ? zapis danych do pliku średnio : 0.0006-7sek a do relacyjnej bazy danych : 0,026 (mowa tutaj o samym zwykłym najprostszym zapisie pakietu danych np 1000 znaków)
!*!
A co się stanie jak ilość urządzeń/emulatorów zwiększysz do 10000? Tak z ciekawości pytam wink.gif

@com - jeśli robisz odczyt/zapis to lepiej korzystać z file_get/put_contents i to sprawdza się tylko w tych prostych czynnościach, wszytko co było w PHP4 file, fopen, fwrite itd. ma określone zadanie np. wyciąganie poszczególnych linijek, buforowanie czy wrzucenie całości w tablicę.
gitbejbe
przy 10 000tyś fakt przeglądarka zmula i to mocno - tzn mój podgląd tego co się dzieje. Przyczyn jest kilka, po pierwsze komp (jest jaki jest, do wydajnych z pewnością nie nalezy - na finalną aplikacje czeka dedyk), po drugie wyświetlam na ekranie zbyt dużo(bardzooo dużo) szczegółowych danych przy kazdej wysyłce aby mogło to być wydajne (jest to potrzebne tylko dla mnie). Narazie kończe już prace nad stabilnością skryptu i zaczne zaraz robić prawidłowe raportowanie błędów w postaci zapisu krótkiego "loga" ze wszystkimi ewentualnymi błędami. Po za tym przy wyłączeniu wyswietlania komunikatów, danych itd chodzi całkiem przyzwoicie jak na taką ilość : ) Nie zapominajmy ze te 10 000tyś idzie na raz co 3 sekudny, a taka sytuacja w rzeczywistym korzystaniu z prawdziwych urzadzeń nigdy się nie zdarzy.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.