Zapisywanie danych do pliku - reopen

Odpowiedz Nowy wątek
2020-05-02 05:12

Rejestracja: 5 lat temu

Ostatnio: 10 godzin temu

0

Cześć,
na stronie: https://gist.github.com/kevinkreiser/39f2e39273c625d96790 znalazłem przykładowy projekt klasy log-a, który m.in. zapisuje błędy do pliku.
Mam kilka pytań do tego projektu, a raczej do klasy ofstream:

  1. przy zapisywaniu danych do pliku funkcja log na końcu wywołuje inną funkcję nazwaną reopen(), której celem jest zamknięcie i ponowne otworzenie pliku co jakiś czas (jeśli minie 300 sekund). Moje pytanie jest takie czy to na pewno jest potrzebne? Czy to nie jest tak, że przy zapisaniu danych do pliku jest on zamykany automatycznie?
  2. plik otwierany jest tylko w funkcji reopen. Czy może mi ktoś potwierdzić lub sprostować, że klasa ofstream działa mniej więcej tak (głównie chodzi mi o punkt c):
    a) tworząc obiekt typu ofstream i wywołując funkcję open() (ewentualnie wywołując odpowiedni konstruktor) obiekt otwiera plik i jednocześnie zapamiętuje nazwę pliku podaną jako argument;
    b) po zakończeniu zapisywania danych przy pomocy operatora "<<" plik automatycznie jest zamykany
    c) gdy chcemy ponownie zapisać coś do pliku przy pomocy operatora "<<" plik jest ponownie automatycznie otwierany (nie musimy ponownie używać funkcji open())? Pytam pod kątem otwarcia pliku za pomocą konstruktora/funkcji open() jedynie w konstruktorze klasy Log-a.
  3. Powyższe pytanie wynika m.in. z obawy czy: jeśli program działa przez godzinę i w tym czasie zapisuje dane do pliku a ktoś wyłączy prąd - to czy plik zostanie utracony jeśli nie wywołaliśmy funkcji close()?
  4. Czy aby zapisywanie do pliku było "thread-safe" wystarczy przed zapisem jedynie zablokować mutex? Czy może warto jeszcze o czymś pamiętać?
    Jak w ogóle oceniacie ten projekt?

Z góry dziękuję za wyjaśnienie - kluczowy kod z projektu poniżej.

    virtual void log(const std::string& message) {
      lock.lock();
      file << message;
      file.flush();
      lock.unlock();
      reopen();
    }
   protected:
    void reopen() {
      //TODO: use CLOCK_MONOTONIC_COARSE
      //check if it should be closed and reopened
      auto now = std::chrono::system_clock::now();
      lock.lock();
      if(now - last_reopen > reopen_interval) {
        last_reopen = now;
        try{ file.close(); }catch(...){}
        try {
          file.open(file_name, std::ofstream::out | std::ofstream::app);
          last_reopen = std::chrono::system_clock::now();
        }
        catch(std::exception& e) {
          try{ file.close(); }catch(...){}
          throw e;
        }
      }
      lock.unlock();
    }
edytowany 2x, ostatnio: Kofcio, 2020-05-02 05:23

Pozostało 580 znaków

2020-05-03 15:14

Rejestracja: 2 lata temu

Ostatnio: 16 godzin temu

0

Tam jest użyta funkcja flush, która zapisuje dane.
Ponowne otwieranie pliku jest moim zdaniem ze względu na to, że plik log może zostać usunięty z zewnątrz lub może wystąpić jakiś błąd w związku z zapisem do tego pliku.


Za­pra­szam na blo­ga

Pozostało 580 znaków

2020-05-03 16:38

Rejestracja: 1 rok temu

Ostatnio: 10 godzin temu

1

Pewnie chodzi o uwzględnienie rotacji logów.
Logrotate co zadany czas zmienia nazwę pliku, ale jeśli jest on otwarty to proces nadal może do niego pisać. Robiąc co jakiś czas reopen mamy gwarancję, że będziemy pisać do "aktualnego" logu.

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0