аналоги файловых функций для LOBов

tony2001

TeaM PHPClub
аналоги файловых функций для LOBов

Господа, я тут заморочился написанием патча, который добавит сабж в экстеншен oci8 (не факт, что его примут на "ура", но всё же...).

Есть некоторые вопросы, на которые не могу ответить сам:

1) должна ли функция $LOB->getLength() КАЖДЫЙ РАЗ обращаться к базе и спрашивать размер, если мы его уже знаем (собственно, он хранится у нас в дескрипторе).
т.е. должен ли я быть параноиком и считать, что размер может измениться в любой момент?
естественно, от этого будет зависеть быстродействие $LOB->feof(), $LOB->read(), $LOB->seek() etc.

имхо поведение функции должно быть таким же, как и у аналога.
но нигде не могу найти четкого ответа: как ведет себя fseek в этом случае?

2) какие еще будут предложения, кроме следующих методов объекта LOB:
eof(), seek(), read(), tell(), rewind(), truncate() (или erase()?), write(), getlength(), trim() и пары функций для работы с буфферингом (пока не разбирался в них).

замечания/предложения?
 

fisher

накатила суть
к списку функций я бы добавил что-нибудь типа strreplace для CLOB. но имхо большинство подобных вещей все же обычно решается через pl/sql+dbms_lob и использовать оси тут неэффективно. касательно #1 я бы был параноиком со всеми вытекающими. не уверен в правильности этого подхода, но можно поэкспериментировать именно с dbms_lob и посмотреть, какие там ньюансы при одновременных обращениях/изменениях.

если говорить про проблему в целом, то было бы конечно здорово иметь экстеншен с более продвинутым интерфейсом для работы с лобами, но лично я особого смысла не вижу. если не секрет, в какой задаче могут понадобиться такие расширения для пхп? большие тексты/картинки/медиа в лобы грузить - так вроде для этого такой интерфейс не нужен. а хочешь разрабатывать эффективные оракл-приложения - используй стандартные пакеты.
 

deek

Новичок
1) имхо, стоит обратить внимание на то, какой тип LOB`а используется. если это внутренний (internal) BLOB, CLOB, NCLOB, то он будет храниться в самом тейблспейсе, и, соответственно, для них полностью поддерживаются транзакции.

а если это FILE(BFILE), то тут да, каждый раз надо бы проверять длину, так как за этот файл отвечает ОС, под которой работает оракл.

могу где-то ошибиться для 9i, в 8i это верно.
 

tony2001

TeaM PHPClub
fisher
>если не секрет, в какой задаче могут понадобиться такие расширения для пхп?
на данный момент есть load() && writetofile(), а мне надо читать по кускам, поэтому и прицепил read(), но останавливаться на этом имхо нет смысла.

deek
звучит, в принципе, разумно.
единственное "но": хотелось бы, чтобы поведение повторяло поведение оригинальной fseek, чтобы не выдумывать своё.
собственно, вопрос "как ведет себя fseek в данном случае?" меня и беспокоит.
 

deek

Новичок
о какой "оригинальную fseek" ты говоришь?
поясни чуть подробнее, пожалуйста.
 

tony2001

TeaM PHPClub
man fseek
Код:
FSEEK(3)                                   Linux Programmer's Manual                                   FSEEK(3)

НАЗВАНИЕ
       fgetpos, fseek, fsetpos, ftell, rewind - меняют положение операции в потоке

СИНТАКСИС
       #include <stdio.h>

       int fseek(FILE *stream, long offset, int whence);
       long ftell(FILE *stream);
       void rewind(FILE *stream);
про эту.
 

deek

Новичок
под вечер начинаю плохо улавивать.

в man pages поведение fseek полностью расписано. ты имеешь в виду случай, когда fseek выходит за EOF?

кстати, а не думал добавить функции lock()/unlock() ? имхо, их наличие, если представлять LOB`ы файлами, полностью оправдано.
 

tony2001

TeaM PHPClub
>под вечер начинаю плохо улавивать.
я сам сейчас плохо формулирую вопрос =)

>в man pages поведение fseek полностью расписано.
>ты имеешь в виду случай, когда fseek выходит за EOF?
нет, я имею ввиду вот какой случай:
мне говорят $LOB->seek(-1,OCI_SEEK_END);, т.е. поставить на -1 байт от конца.
должен ли я в этом случае брать размер _опять_ из базы, предполагая, что он мог поменяться?
имхо нет, вряд ли fseek опять считает размер файла.

>кстати, а не думал добавить функции lock()/unlock() ?
>имхо, их наличие, если представлять LOB`ы файлами, полностью оправдано.
для начала я хочу сделать врапперы к функциям отсюда: http://docs.linux.cz/Oracle8/server/a58234/new_adva.htm из таблички "Table 7-1 OCI LOB and FILE Functions".
пока я не вижу там способа залочить блоб.
 

deek

Новичок
> имхо нет, вряд ли fseek опять считает размер файла.
да, fseek ничего не считает, он просто перемещает указатель.

> должен ли я в этом случае брать размер _опять_ из базы, предполагая, что он мог поменяться?
мне все же непонятно, зачем знать этот размер.

я почему спросил про lock()/unlock(). если эмулировать работу с файлами, то по полной программе. не залочен файл - обеспечение многопоточности ложится на пользователя. залочен - тогда уже на твой экстеншн.

> пока я не вижу там способа залочить блоб
есть смысл попробовать OCITransStart()/OCITransCommit()

и как раз нашлось на эту тему:
Large Objects: Advanced Topics: LOB Locators and Transaction Boundaries
 

deek

Новичок
хотя, все это лишнее, с lock()/unlock().

ничто не мешает заранее выбрать LOB локатор FOR UPDATE.
 

tony2001

TeaM PHPClub
>мне все же непонятно, зачем знать этот размер.
ээ.. например, при SEEK_END считается _от_конца_.

>я почему спросил про lock()/unlock().
>если эмулировать работу с файлами, то по полной программе.
согласен, но тогда можно говорить и о chmod, chown etc.
как ты понимаешь, не все можно реализовать.

>не залочен файл - обеспечение многопоточности ложится на пользователя.
>залочен - тогда уже на твой экстеншн.
поясни, плз. я не совсем понимаю.

ок, статью посмотрю.
 

deek

Новичок
проверил тут на досуге, да, fseek считает размер, по крайней мере, для этого примера:

Код:
#include <stdio.h>

int main(void)
{
    FILE *pFile1, *pFile2;
    char *pBuffer;
    
    pFile1 = fopen("test_seek", "w");
    pFile2 = fopen("test_seek", "r");
    
    fputs("0123456789", pFile1);
    fflush(pFile1);
    
    pBuffer = (char*) malloc(sizeof(char) * 2);
    
    fseek(pFile2, -2, SEEK_END);
    fread(pBuffer, sizeof(pBuffer), 1, pFile2);
    
    printf("%s\n", pBuffer);
    
    free(pBuffer);
    fclose(pFile1);
    fclose(pFile2);

    return 0;
}
если бы fseek(pFile2) не считал бы размер, на экран вместо строки "89" не вывелось бы ничего.

для пущей уверенности можно попробовать переделать пример для двух процессов.

> поясни, плз. я не совсем понимаю.
я теперь (когда выспался) уже тоже (=

наверное, про эти lock/unlock не стоит вообще думать, так как пользователю ничего не мешает самостоятельно делать коммиты, роллбэки, расставлять сейвпойнты между "файловыми" операциями с использованием твоего экстеншена.
 

tony2001

TeaM PHPClub
на данный момент работает так:
получается дескриптор, в котором отмечается длина ЛОБа и текущая позиция указателя.

при работе с этим ЛОБом длина меняется соот-вующим образом, т.е. при дописывании в конец - увеличивается, при вызове truncate() - уменьшается и т.п.
ессно, эти изменения вступают в силу после коммита.
в процессе работы длина лоба *не берется из оракла каждый раз*; доверяем сами себе и смотрим что записано в дескрипторе.

имхо логично?
возражения будут?
 
Сверху