Ehcache диск магазина нечистого отключения - PullRequest
6 голосов
/ 03 марта 2010

Я использую кеш с сохранением дискового хранилища. При повторном запуске приложения я получаю следующую ошибку:

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

Есть ли способ исправить это, кроме явного вызова net.sf.ehcache.CacheManager.shutdown() где-нибудь в приложении?

Конфигурация кэша:

<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>

Код для тиражирования вопроса:

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"));
    }
}

Ответы [ 3 ]

13 голосов
/ 06 марта 2010

Попробуйте установить системное свойство: net.sf.ehcache.enableShutdownHook = истина

Итак, вы можете добавить следующую строку в начало вашей программы: System.setProperty("net.sf.ehcache.enableShutdownHook","true");

Или из командной строки передать свойство: java -Dnet.sf.ehcache.enableShutdownHook=true ...

Обратите внимание, веб-сайт ehcache упоминает о некоторой осторожности при использовании этой ловушки отключения Завершение работы Ehcache

Когда будет запущен крюк отключения, а когда нет

Отключающий крюк срабатывает, когда:

  • программа существует нормально. например Вызывается System.exit (), или последний поток, не являющийся демоном, завершает работу
  • Виртуальная машина прервана. например CTRL-C. Это соответствует kill -SIGTERM pid или kill -15 pid в системах Unix.

Отключающий крюк не будет работать, когда:

  • Виртуальная машина прерывается
  • Сигнал SIGKILL отправляется процессу виртуальной машины в системах Unix. например убить -SIGKILL pid или kill -9 pid
  • В системах Windows отправляется вызов TerminateProcess.

Надеюсь, что это работает:)

2 голосов
/ 03 марта 2010

Как вы останавливаете свое приложение?

Посмотрев на код Ehcache, он регистрирует хук отключения JVM Runtime.getRuntime().addShutdownHook, который закрывает кеш при выходе из JVM. Если JVM убита или аварийно завершает работу, ловушка отключения не будет вызываться.

Обновить RE ваш комментарий:

Вот комментарий из DiskStore dispose method:

Завершает работу хранилища дисков при подготовке к отключению кэша.

Если произойдет сбой виртуальной машины, ловушка отключения не будет запущена. Файл данных и индексный файл будут не синхронизированы. При инициализации мы всегда удаляем индексный файл после того, как прочитали элементы, чтобы он имел нулевую длину. При грязном перезапуске он все равно останется, и файл данных будет автоматически удален, тем самым сохраняя безопасность.

Итак, если вы воссоздаете кеш в другом модульном тесте. Поскольку shutdownHook не запустился, индексный файл будет равен 0. Ehcache считает, что индекс поврежден. Я бы отключил кэш, используя аннотацию @After JUnit в каждом из ваших модульных тестов. Или разделите кэш по всем тестам, но, думаю, это не даст вам отдельных тестов.

0 голосов
/ 06 октября 2015

Для тех из нас, кто использует Ehcache с Spring 3.1+ и java config, вы должны использовать:

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

и (при условии, что вы также используете не-Spring Spring ApplicationContext, включите там ловушку отключения, чтобы заставить бин изящно уничтожиться:

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

см. это для получения дополнительной информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...