Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> реализовать cache для Object на ФС 
V
    Опции темы
Metal_Heart
Дата 7.11.2009, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


а почему бы и нет?
**


Профиль
Группа: Участник
Сообщений: 728
Регистрация: 31.3.2005
Где: Москва

Репутация: 4
Всего: 12



Добрый день, товарищи!

Задали мне тестовую задачку - реализовать cache для Object на файловой системе с ограничением на размер кэша.
Для справки: размер объектов можно получить с помощью вот этой утилиты: sizeof

Но как же выгрузить объект в файл, чтоб освободить занимаемую им память, а затем, при надобности, подгрузить его в память обратно?
Это ведь задачка, на мой взгляд, не на простую сериализацию.
Я не сомневаюсь, что если и найдется такое решение, то придеться бороться с фрагментацией.

Пожалуйста, не обсуждайте здесь само задание.
Мне нужна ваша помощь в том, как реализовать поставленную задачу или доказать, что решения не существует.

Спасибо за внимание!


--------------------
 не стыдно учиться, а стыдно не учиться 
PM ICQ   Вверх
COVD
Дата 7.11.2009, 15:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Metal Heart Вы ведь легко могли бы сохранить обьект в базе данных и при необходимости извлечь. База данных - это тот же файл, только операции с обьектами (поиск, удаление, вставка) база выполняет сама. Ваше задание выглядит как создание специализированной базы данных. Или как HashMap, но не в памяти, а на диске .

В качестве основы для этого удобен RandomAccessFile. Вы записываете в файл обьекты и запоминаете позицию каждого обьекта и его длину. И храните эти параметры в памяти. Удаление обьекта - это удаление только ключей в памяти. Дефрагментация файла - это создание нового файла, куда копируются только "живые" обьекты из старого.
PM MAIL   Вверх
Metal_Heart
Дата 7.11.2009, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


а почему бы и нет?
**


Профиль
Группа: Участник
Сообщений: 728
Регистрация: 31.3.2005
Где: Москва

Репутация: 4
Всего: 12



COVD, спасибо!
База данных - хорошее решение, о котором я даже и не подумал!
Но я пожалуй остановлюсь на 2м варианте, потому как его реализация мне интереснее.


--------------------
 не стыдно учиться, а стыдно не учиться 
PM ICQ   Вверх
Metal_Heart
Дата 9.11.2009, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


а почему бы и нет?
**


Профиль
Группа: Участник
Сообщений: 728
Регистрация: 31.3.2005
Где: Москва

Репутация: 4
Всего: 12



Дошли, таки руки, реализовал я этот swap:
Код

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

/**
 * User: Metal_Heart
 * License: GPLv2
 */

public class SwapFile extends SwapParent
{
public static final String SWAP_NAME1       = "cache.swap";
public static final String SWAP_NAME2       = "cache2.swap";
public static final String EXCEP_SWAP       = "Can't create swap-file";
private static String      swapFile         = SWAP_NAME1;
private static boolean     flagInit         = false;
private static Vector      deletedKey       = new Vector();
 
private static Map<Object, Id> storageID = new HashMap<Object, Id>();
private static int    sizeL2    = DEFAULT_SIZE_SWAP;
private static int    nonfreeL2 = 0;


 /**
  *  Meta-information about saved objects
  *  pos and length - place in the swap-file
  */
protected static class Id{
 public int  pos;
 public int  length;
}
 
public static int freeMemory(){return sizeL2-nonfreeL2;}
public static boolean setSizeSwap(int size){
 if(size<MIN_SIZE_OBJECT) return false;
 if(!Utils.checkChangeSize(sizeL2, nonfreeL2, size)) return false;
 sizeL2=size;
 return true;
}


 /**
  * Clear swap
  */
public synchronized static void clear(){storageID.clear();deletedKey.clear();}


 /**
  *  Read and remove keyed object from Swap
  *  (synchronized method)
  */
public static Object read(Object key) throws Exception{
 if(!flagInit) deleteSwapFiles();
 Object o = reader(key, swapFile);  //it's synchronized method
 deletedKey.add(key);          
return o;
}


 /**
  *  Put keyed object to Swap
  *  (synchronized method)
  */
public static void write(Object key, Object ob) throws Exception{
 if(!flagInit) deleteSwapFiles();
 int n = Utils.objectToBytes(ob).length;
 if(n>freeMemory()) defragmentationSwap();
 if(n>freeMemory()) throw new Exception(EXCEP_NOT_MEMORY);
 storageID.put(key, writer(ob, swapFile));   //it's synchronized method
 nonfreeL2+=n;
}


protected static void deleteSwapFiles() throws Exception {
 deleteSwapFile(SWAP_NAME1);
 deleteSwapFile(SWAP_NAME2);
 flagInit=true;
}

private static void deleteSwapFile(String filename) throws Exception {
 File f = new File(filename);
 if(f.exists()) f.delete();
 if(!f.createNewFile()) throw new Exception(EXCEP_SWAP+": "+filename);
 f.deleteOnExit();
}



private synchronized static Object reader(Object key, String fileName) throws Exception{
 Id id = storageID.get(key);
 ByteBuffer bb = ByteBuffer.allocate(id.length);
 RandomAccessFile file = new RandomAccessFile(fileName, "rw");
 FileChannel fc = file.getChannel();
 fc.position(id.pos);

 int nread;
 do{nread = fc.read(bb);} while(nread != -1 && bb.hasRemaining());
return Utils.byteToObject(bb.array());
}


 
private synchronized static Id writer(Object ob, String fileName) throws Exception{
 RandomAccessFile file = new RandomAccessFile(fileName, "rw");
 Id id = new Id();
 id.pos = (int)file.getChannel().size();
 byte[] bs = Utils.objectToBytes(ob);
 id.length = bs.length;

 ByteBuffer outbb = ByteBuffer.wrap(bs);
 FileChannel fc = file.getChannel();
 fc.position(id.pos);
 while (outbb.hasRemaining()) fc.write(outbb);
 outbb.rewind();
 file.close();

return id; 
}



private static void defragmentationSwap() throws Exception {
String s;
if(SWAP_NAME1.equals(swapFile)) s=SWAP_NAME2; else s=SWAP_NAME1;

 for(Object key : storageID.keySet()){
   boolean b = false;
   for (Object delKey : deletedKey) {
     if(delKey != key) continue;
     b = true;
     nonfreeL2-= storageID.get(key).length;    if(nonfreeL2<0)nonfreeL2=0;
     break;
   }
   if(!b) writer(reader(key, swapFile), s);  //write to new swap-file 
 }
 for(Object delKey : deletedKey) storageID.remove(delKey);

 deletedKey.clear();
 deleteSwapFile(swapFile);  //remove previous swap-file
 swapFile=s;
}


 /**
  *  it's for debug
  */
protected static void dumpSwap() throws Exception {
 System.out.println("dumpSwap\n--------------------");
 for(Object key : storageID.keySet())
    System.out.println("Object["+key+"] = "+ reader(key, swapFile)+": \t"+storageID.get(key).pos+"; "+storageID.get(key).length);
 System.out.println("--------------------\n\n\n");
}

}


класс-помощник:
Код

import java.io.*;

/**
 * User: Metal_Heart
 * License: GPLv2
 */
public class Utils {

public static byte[] objectToBytes(Object ob) throws Exception{
 ByteArrayOutputStream out = new ByteArrayOutputStream();
 ObjectOutputStream ostream = new ObjectOutputStream(out);
 ostream.writeObject(ob);
 ostream.flush();
 ostream.close();

 byte[] bs = out.toByteArray();
 out.close();
return bs;
}


public static Object byteToObject(byte[] bs) throws IOException, ClassNotFoundException {
 ByteArrayInputStream in = new ByteArrayInputStream(bs);
 ObjectInputStream istream = new ObjectInputStream(in);
 Object o = istream.readObject();
 istream.close();
 in.close();
return o;
}


public static boolean checkChangeSize(int oldSize, int nonFree, int newSize){
 return newSize >= oldSize || newSize >= (oldSize - nonFree);
}

}


если что, пишите, рад буду помочь! 


--------------------
 не стыдно учиться, а стыдно не учиться 
PM ICQ   Вверх
Metal_Heart
Дата 9.11.2009, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


а почему бы и нет?
**


Профиль
Группа: Участник
Сообщений: 728
Регистрация: 31.3.2005
Где: Москва

Репутация: 4
Всего: 12



Кстати, этот swap я реализовал в виде статического класса и сделал я это интуитивно.
Лично мне писать статические классы - не очень привычно, не люблю я их, зато с другой стороны, риск получить сообщение типа такого:
Цитата

Вы не использовали предоставленный Вам ОБЪЕКТ в течение ранее оговоренного времени, поэтому мы со своей стороны вынуждены прибегнуть к помощи коллекторной службы: GC
несколько меньше  smile 

Вопрос, прав ли я, используя для кэша реализацию на статическом классе?

Это сообщение отредактировал(а) Metal_Heart - 9.11.2009, 18:20


--------------------
 не стыдно учиться, а стыдно не учиться 
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0452 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.