Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Как поставить блокировку на файл при записи xml?


Автор: x4444 5.4.2006, 19:46
серверная часть программы (сервлет) должна сохранять данные, которые ввел пользователь в xml файл.

условия такие, что одновременно на Tomcat могут быть запущены несколько Applications (однотипных), пишущих в один xml файл.

http://server/app1/servlet1
http://server/app2/servlet1
.
.
.

сейчас я пишу мотдом Transformer.transform(Sourse, Result)

Код

          Source source = new DOMSource(doc);
          Result result = new StreamResult(f);
          Transformer xformer = TransformerFactory.newInstance().newTransformer();
          xformer.transform(source, result);


т.е. никаких блокировок не ставлю
Совсем неуверен, что так оно будет безопасно.
Как правильно безопасно записать XML в файл?

Автор: LSD 5.4.2006, 22:27
Э-э-э, ну как бы тебе объяснить... Сделать потокобезопасный OutputStream, это не сложно, но это не гарантирует, что там будет корректный XML.
Наверно надо в твоем приложении делать синхронизацию, как только приложение хочет записать данные, оно захватывает блокировку, пишет их, а потом снимает ее.

Автор: x4444 6.4.2006, 12:28
Цитата(LSD @ 5.4.2006, 22:27)
Наверно надо в твоем приложении делать синхронизацию, как только приложение хочет записать данные, оно захватывает блокировку, пишет их, а потом снимает ее.


Сейчас я сделал свой синхронизированный метод addToXML() (в классе обрабатывающего сервлета) который делает следующее

1. parse XML файл в документ
2. добавляет новые ноды в документ
3. трансформирует документ в XML файл

Т.о. в рамках одного application (ввиду того, что обрабатывающий сервлет только один) стало безопасно. Но апликейшенов несколько, а файл один. Поэтому вполне возможно, что один application начал parse в то время как второй уже добавил ноды, но еще не записал.

Поэтому мне надо чтобы при начале выполнения метода addToXML на файл накладывался запрет на чтение и запись. т.е. мне нужно монопольно юзать файл. Т.е. это на уровне ОС должно происходить.

Рекомендуют смотреть в сторону java.nio.channels.FileLock, java.nio.channels.FileChannel , там есть методы lock(), tryLock()
Но как конкретно сделать еще не понял,

FileChannel можно получить из FileOutputStream методом getChannel(), и получив FileChannel можно попытаться наложить замок на файл ( tryLock() ).
Однако как подсунуть FileChannel трансформеру XML . У классов ветки Result (e.g. StreamResult) нет конструктора c параметром FileChannel.

Автор: LSD 6.4.2006, 21:57
А зачем тебе передавать Transformer-ру FileChannel? Передавай ему FileOutputStream.
Код
FileOutputStream out = new FileOutputStream("some.xml");
FileLock fileLock = out.getChannel().lock();
    
Result result = new StreamResult(out);
....
    
fileLock.release();
out.close();

Автор: x4444 16.4.2006, 17:14
я вот думаю в каком порядке делать снятие замка и закрытие стрима и канала

вроде как сначала закрыть стрим
потом сянять замок
и закрыть канал

правильно? 

Автор: LSD 16.4.2006, 20:04
Закрытие канала снимает блокировку, поэтому - вначале ставишь блокировку (shared - на чтение, exclusive - на запись), затем пишешь/читаешь данные, если писал выполняешь flush(), снимаешь блокировку, закрываешь поток.
Только учти одну вещь:
Цитата
Whether or not a lock actually prevents another program from accessing the content of the locked region is system-dependent and therefore unspecified. The native file-locking facilities of some systems are merely advisory, meaning that programs must cooperatively observe a known locking protocol in order to guarantee data integrity. On other systems native file locks are mandatory, meaning that if one program locks a region of a file then other programs are actually prevented from accessing that region in a way that would violate the lock. On yet other systems, whether native file locks are advisory or mandatory is configurable on a per-file basis. To ensure consistent and correct behavior across platforms, it is strongly recommended that the locks provided by this API be used as if they were advisory locks.


Под Windows во всяком случае, все нормально работает, за другие ОС не скажу. 

Автор: x4444 16.4.2006, 23:36
Непонятно почему, но не поучается наложить замок на FileInputStream.

получаю Exception: null

Код

import java.io.*;
import java.nio.*;
import java.nio.channels.*;

class TestLock {
    public static void main(String[] args) {
       try {
        FileInputStream fis = new FileInputStream("test.txt");
        FileChannel ch = fis.getChannel();
        FileLock fl = ch.lock();

        fl.release();
        fis.close();
      } catch (Exception e) {
        System.out.println("Exception: " + e.getMessage());
       }
    }
}


тот же самый код но с FileOutputStream работает нормально 

Автор: firedrago 17.4.2006, 01:53
а не проще ли создавать пустой лок файл
все остальные спят пока myLockFile.exists()....
как только лок файл удален - начинает работу следующий....
....я бы так сделал....наверное..... 

Автор: LSD 17.4.2006, 09:54
Цитата(x4444 @  17.4.2006,  00:36 Найти цитируемый пост)
Непонятно почему, но не поучается наложить замок на FileInputStream.

получаю Exception: null

Потому что ты пытаешься захватить exclusive блокировку у канала который read-only. Для read-only каналов ты можешь захватывать только shared блокировку:
Код
try
{
  FileInputStream fis = new FileInputStream("test.txt");
  FileChannel ch = fis.getChannel();
  FileLock fl = ch.lock(0L, Long.MAX_VALUE, true);
  fl.release();
  fis.close();
}
catch(Exception e)
{
  System.out.println("Exception: " + e.getMessage());
}

Shared блокировка совместима с другими shared блокировками, но не совместима с exclusive блокировками. Т.е. захватить несколько shared блокировок на один файл ты сможешь, но exclusive блокировка будет только одна - не будет никаких других блокировок на файл. 

Автор: Ortega 17.4.2006, 10:54
Цитата(LSD @  16.4.2006,  20:04 Найти цитируемый пост)
Под Windows во всяком случае, все нормально работает, за другие ОС не скажу.  

под Linux тоже работает, во всяком случае, exclusive 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)