2013-02-12 20 views
9

Mam aplikację, która chce zachować wiele otwartych plików: okresowo odbiera żądanie klienta z napisem "dodaj dane do pliku X" i byłoby idealnie mieć już otwarty plik, a sekcja nagłówka pliku już przeanalizowany, tak aby ten zapis był szybki. Jednak przechowywanie wielu plików jest niezbyt przyjemne dla systemu operacyjnego i może stać się niemożliwe, jeśli wzrosną nasze potrzeby przechowywania danych.Jak buforować uchwyty plików?

Chciałbym więc, aby funkcja "daj mi ten uchwyt pliku, otwierając, jeśli nie jest buforowana", oraz proces do automatycznego zamykania plików, które nie zostały napisane przez, powiedzmy, pięć minut. Dla konkretnego przypadku buforowania uchwytów plików zapisywanych krótkimi kropkami, prawdopodobnie jest to wystarczające, , ale wydaje się, że jest to wystarczająco ogólny problem, że powinny istnieć funkcje takie jak "daj mi obiekt o nazwie X, z pamięci podręcznej, jeśli to możliwe "i" Teraz skończyłem z obiektem X, więc spraw, aby kwalifikowało się do eksmisji pięć: minut od teraz ".

core.cache wygląda to może być odpowiednie do tego celu, ale jest całkiem pozbawione documentation i source przewiduje żadnych szczególnych wskazówek o tym, jak z niego korzystać. Jego wygląd TTLCache wygląda obiecująco, ale nie jest jasne, jak go używać, ponieważ nie jest jasne, jak go używać, aby usunąć eksmitowane elementy, więc nie można zamknąć zasobu , gdy jestem gotowy na jego wygaśnięcie.

Mogę przetasować własne, ale istnieje wiele trudnych miejsc i jestem pewna, że ​​dostanę pewne pomyłki, więc mam nadzieję, że ktoś tam może wskazać mi implementację to funkcjonalność . Mój kod jest w clojure, ale oczywiście używanie biblioteki java byłoby całkowicie w porządku, jeśli jest tam, gdzie można znaleźć najlepszą implementację.

Odpowiedz

5

Zapoznaj się z Guava's cache implementation.

  • Można dostarczyć Callable (lub CacheLoader) metody get dla „czy uchwyt jest buforowane, zwraca go, inaczej otwarta, cache i odesłać go” semantyka
  • Można skonfigurować czasowe eksmisji takiego jak expireAfterAccess
  • można zarejestrować RemovalListener zamknąć uchwyty na usunięciu

Modyfikacja przykłady kodu z połączonego Guava Strona nieznacznie, używając CacheLoader:

LoadingCache<Key, Handle> graphs = CacheBuilder.newBuilder() 
    .maximumSize(100) // sensible value for open handles? 
    .expireAfterAccess(5, TimeUnit.MINUTES) 
    .removalListener(removalListener) 
    .build(
     new CacheLoader<Key, Handle>() { 
     public Handle load(Key key) throws AnyException { 
      return openHandle(key); 
     } 
     }); 

RemovalListener<Key, Handle> removalListener = 
    new RemovalListener<Key, Handle>() { 
    public void onRemoval(RemovalNotification<Key, Handle> removal) { 
     Handle h = removal.getValue(); 
     h.close(); // tear down properly 
    } 
    }; 

* ZASTRZEŻENIE * Nie używałem cache się w ten sposób, upewnij się przetestować to sensownie.

+0

To wygląda całkiem odpowiedni, dzięki! Martwi mnie tylko to, że wygląda na to, że można uzyskać element z pamięci podręcznej i zawiesić go na dłużej niż czas wygaśnięcia, aktywnie wykorzystując go cały czas. Jeśli kod wygaśnięcia przedmiotu oderwie go, staje się niebezpieczny. Czy znasz sposób, aby "sprawdzić obiekt" w pamięci podręcznej, tak aby nie został zburzony, dopóki nie zostanie ponownie sprawdzony? – amalloy

+0

Hm, myślę, że to zależy. Czy zdarza się, że ciągle piszesz do pliku przez> = 5 minut? Czy pamięć podręczna jest dostępna tylko z jednego żądania na raz? Zapoznaj się z dokumentacją tutaj: Eksmisja nie następuje automatycznie po wygaśnięciu, ale podczas odczytu/zapisu z/do pamięci podręcznej. Może to dobrze (jeśli masz jedną prośbę, która mogłaby napisać przez długi czas, to nie zostanie ona zerwana), może źle, ponieważ jest więcej niż jedna prośba o czas lub chcesz sprzątnąć klamki wcześniej/w tło ... –

+0

Zobacz tutaj: http://code.google.com/p/guava-libraries/wiki/CachesExplained#When_Does_Cleanup_Happen? –

0

OS mają pewne ograniczenia: Is there a limit on number of open files in Windows

SortedMap< Date, File > cache = new TreeMap<>(); 
cache.put(new Date(), file); 
Timer timer = new Timer(true); 
timer.scheduleAtFixedRate(task, 60*1000L, 60*1000L); 

Aby wyczyścić pamięć podręczną: usunąć najpierw, czy jest to wiek> 5 minut, aż powtórzyć pierwszy wiek> 5 minut.

Powiązane problemy