2010-03-03 28 views
5

Używam pamięci podręcznej z utrwalaniem magazynu dysków. Na kolejnych powtórek aplikacji Dostaję następujący błąd:Magazyn dysku Ehcache nieczytelne zamknięcie

net.sf.ehcache.store.DiskStore deleteIndexIfCorrupt 
WARNING: The index for data file MyCache.data is out of date, 
probably due to an unclean shutdown. Deleting index file MYCache.index 

Czy istnieje jakiś sposób, aby ustalić, że oprócz wyraźnie nazywając net.sf.ehcache.CacheManager.shutdown() gdzieś w aplikacji?

konfiguracja skrzynki:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation="ehcache.xsd" 
      updateCheck="true" monitoring="autodetect"> 

    <diskStore path="C:\work"/> 

    <cacheManagerEventListenerFactory class="" properties=""/> 

    <cacheManagerPeerProviderFactory 
      class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" 
      properties="peerDiscovery=automatic, 
         multicastGroupAddress=230.0.0.1, 
         multicastGroupPort=4446, timeToLive=1" 
      propertySeparator="," 
      /> 

    <cacheManagerPeerListenerFactory 
      class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/> 

    <defaultCache 
      maxElementsInMemory="1" 
      eternal="false" 
      timeToIdleSeconds="0" 
      timeToLiveSeconds="86400" 
      overflowToDisk="true" 
      diskSpoolBufferSizeMB="1" 
      maxElementsOnDisk="10000" 
      diskPersistent="true" 
      diskExpiryThreadIntervalSeconds="120" 
      memoryStoreEvictionPolicy="LFU" 
      /> 

</ehcache> 

kod do replikowania problem:

import java.util.ArrayList; 
import java.util.List; 

import net.sf.ehcache.Cache; 
import net.sf.ehcache.CacheManager; 
import net.sf.ehcache.Element; 

public class CacheTest { 
    static CacheManager manager = new CacheManager(CacheTest.class 
      .getResource("ehcache.xml")); 
    static Cache cache; 

    public static void main(String[] args) { 

     // Get a default instance 
     manager.addCache("test"); 
     cache = manager.getCache("test"); 

     // Generate some junk so that the 
     // cache properly flushes to disk 
     // as cache.flush() is not working 
     List<String> t = new ArrayList<String>(); 
     for (int i = 0; i < 1000; i++) 
      t.add(null); 
     // Oddly enough fewer elements 
     // do not persist to disk or give 
     // an error 
     for (int i = 0; i < 100000; i++) { 
      cache.put(new Element(i, t)); 
     } 
     cache.flush(); 

     if (cache.get("key1") == null) { 
      System.out.println("key1 not found in cache!"); 
      cache.put(new Element("key1", "value1")); 
     } 

     System.out.println(cache.get("key1")); 
    } 
} 

Odpowiedz

12

Spróbuj ustawić właściwość systemową: net.sf.ehcache.enableShutdownHook = true

Tak, albo można dodać następującą linię na początku programu: System.setProperty("net.sf.ehcache.enableShutdownHook","true");

OR, z wiersza poleceń, aby przekazać właściwość: java -Dnet.sf.ehcache.enableShutdownHook=true ...

Uwaga, witryna ehcache wspomina o pewnej ostrożności podczas używania haka zamknięcia: Shutting Down Ehcache

When a shutdown hook will run, and when it will not

The shutdown hook runs when:

  • a program exists normally. e.g. System.exit() is called, or the last non-daemon thread exits
  • the Virtual Machine is terminated. e.g. CTRL-C. This corresponds to kill -SIGTERM pid or kill -15 pid on Unix systems.

The shutdown hook will not run when:

  • the Virtual Machine aborts
  • A SIGKILL signal is sent to the Virtual Machine process on Unix systems. e.g. kill -SIGKILL pid or kill -9 pid
  • A TerminateProcess call is sent to the process on Windows systems.

Mam nadzieję, że działa :)

+0

. Dzięki! :) – Tomasz

2

Jak ty zatrzymanie aplikacji?

Od sprawdzania kodu Ehcache, rejestruje on hak zamykający JVM Runtime.getRuntime().addShutdownHook, który zamyka pamięć podręczną przy wyjściu JVM. Jeśli JVM zostanie zabity lub ulegnie awarii, hak zamykający nie zostanie wywołany.

Aktualizacja RE komentarz:

Oto komentarz z metody DiskStore dispose:

Shuts down the disk store in preparation for cache shutdown

If a VM crash happens, the shutdown hook will not run. The data file and the index file will be out of synchronisation. At initialisation we always delete the index file after we have read the elements, so that it has a zero length. On a dirty restart, it still will have and the data file will automatically be deleted, thus preserving safety.

Dlatego, jeśli odtworzenie Cache w innej badanej jednostki. Ponieważ shutdownHook nie zostałby uruchomiony, plik indeksu będzie wynosił 0. Ehcache uważa, że ​​indeks jest uszkodzony. W każdym z twoich testów jednostkowych zamknęłbym pamięć podręczną za pomocą adnotacji JUnit @After. Lub udostępnij pamięć podręczną we wszystkich testach, ale domyślam się, że nie dałoby to odosobnionych testów.

+0

Używam go jako część testu Junit4. Błąd pojawia się podczas kolejnego uruchomienia testu. Mogę dostarczyć próbkę kodu do replikacji, jeśli to pomaga. – Tomasz

+0

Zaktualizowałem pytanie na podstawie Twojego komentarza. –

+0

nop, wciąż otrzymuje ten sam błąd, nawet jeśli działa z wiersza polecenia w działającym słoiku. – Tomasz

0

Dla tych z nas, używając ehcache z wiosny 3.1 i nowsze i java config, trzeba użyć:

@Bean(destroyMethod = "shutdown") 
public net.sf.ehcache.CacheManager ehCacheManager() { .. } 

i (zakładając, że jesteś również przy użyciu niezwiązanego z siecią kontekstu aplikacji Spring Application, włącz hak zamknięcia, aby spowodować zniszczenie fasoli:

context = new AnnotationConfigApplicationContext(AppConfig.class); 
((AbstractApplicationContext) context).registerShutdownHook(); 

, aby uzyskać więcej informacji, zobacz this.