Re[31]: Объектные базы как они есть
От: BaZa  
Дата: 22.04.05 17:02
Оценка:
AR>Впрочем, я не такой уж эксперт по VDS и могу ошибаться. Пусть BaZa меня поправит, если это так.

Готов ответить практически на любые конкретные вопросы по bilink и/или рассказать с самого начала (тока это очень много).
Может быть пример выложить....

to AR: кстати в комментарий к Вашему рисунку:

есть объект А — у него есть bilink на другой объект Б, который не знает о том, что на него может ссылаться А.
Если бы было по-другому, то возникли бы проблемы при удалении. Поэтому обычно используется механизм, при котором bilink есть у обоих объектов (это улучшает скорость и работу с памятью). Т.е на 2 объекта 2 bilink в обе стороны.

Это на первый взгляд может показаться не очень удобно, но на практике дает значительный выигрыш.
Re[32]: Объектные базы как они есть
От: stalcer Россия  
Дата: 26.04.05 05:40
Оценка:
Здравствуйте, BaZa, Вы писали:

BZ>Поэтому обычно используется механизм, при котором bilink есть у обоих объектов (это улучшает скорость и работу с памятью). Т.е на 2 объекта 2 bilink в обе стороны.

BZ>Это на первый взгляд может показаться не очень удобно, но на практике дает значительный выигрыш.

Я насколько понимаю, bilink — это маленький объект — логический указатель на связь. Их по одному в каждом объекте.
Вопрос: есть ли что то общее, т.е. какой-то объект-связь, на который эти bilink'и указывают (в оперативной памяти (кэше), имеется ввиду). Или же это просто перекрестные ссылки.

И как реализован алгоритм измнения связей, т.е. как связь с обоих концов поддерживается в согласованном состоянии. Это больше интересует для случая, когда в одном из объектов мы меняем связь, а другой в это время в кэш еще не подгружен.
http://www.lmdinnovative.com (LMD Design Pack)
Re[33]: Объектные базы как они есть
От: BaZa  
Дата: 05.05.05 16:08
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Я насколько понимаю, bilink — это маленький объект — логический указатель на связь.


просто указатель на связь

S>Их по одному в каждом объекте.


только если связь одна и она "одна к одному"

S>Вопрос: есть ли что то общее, т.е. какой-то объект-связь, на который эти bilink'и указывают (в оперативной памяти (кэше), имеется ввиду). Или же это просто перекрестные ссылки.


Скорее всего нет (непонятно зачем это нужно)

Билинк на одной стороне указывает на билинк на другой стороне

S>И как реализован алгоритм измнения связей, т.е. как связь с обоих концов поддерживается в согласованном состоянии.



// реализация функций bilink выглядит примернт так:

#ifdef VPP_VTPCLS
DEFINE_BiLink_to_BiLink(Author,Document);
DEFINE_BiLinkVstr_to_BiLink(Folder,Document);
#endif

static int ___dummy1 = BiLink_to_BiLink(Author,Document)::
        add(&Author::document,&Document::author);

// add - стандартный метод bilink

static int ___dummy2 = BiLinkVstr_to_BiLink(Folder,Document)::
        add(&Folder::documents,&Document::folder);


S>Это больше интересует для случая, когда в одном из объектов мы меняем связь, а другой в это время в кэш еще не подгружен.


прелесть в том, что это можно сделать самому при необходимости.
Re[34]: Объектные базы как они есть
От: stalcer Россия  
Дата: 11.05.05 06:03
Оценка:
Здравствуйте, BaZa, Вы писали:

BZ>просто указатель на связь


Пусть так.

S>>Их по одному в каждом объекте.


BZ>только если связь одна и она "одна к одному"


Конечно. Я это забыл уточнить.

S>>Вопрос: есть ли что то общее, т.е. какой-то объект-связь, на который эти bilink'и указывают (в оперативной памяти (кэше), имеется ввиду). Или же это просто перекрестные ссылки.


BZ>Скорее всего нет (непонятно зачем это нужно)


BZ>Билинк на одной стороне указывает на билинк на другой стороне


Ээээ. Билинк на одной стороне должен уж тогда указывать на объект с другой стороны, а не на билинк.

S>>И как реализован алгоритм измнения связей, т.е. как связь с обоих концов поддерживается в согласованном состоянии.


BZ>
BZ>// реализация функций bilink выглядит примернт так:

BZ>#ifdef VPP_VTPCLS
BZ>DEFINE_BiLink_to_BiLink(Author,Document);
BZ>DEFINE_BiLinkVstr_to_BiLink(Folder,Document);
BZ>#endif

BZ>static int ___dummy1 = BiLink_to_BiLink(Author,Document)::
BZ>        add(&Author::document,&Document::author);

BZ>// add - стандартный метод bilink

BZ>static int ___dummy2 = BiLinkVstr_to_BiLink(Folder,Document)::
BZ>        add(&Folder::documents,&Document::folder); 
BZ>


Ну я же просил реализацию, а не заголовки .

S>>Это больше интересует для случая, когда в одном из объектов мы меняем связь, а другой в это время в кэш еще не подгружен.


BZ>прелесть в том, что это можно сделать самому при необходимости.


Меня интересует, вобщем, всего один вопрос: Как сделать так, чтобы не нужно было зря подгружать объекты при изменении связей.
Причем вся прелесть в том, что это должно работать автоматически.
http://www.lmdinnovative.com (LMD Design Pack)
Re[35]: Объектные базы как они есть
От: BaZa  
Дата: 11.05.05 09:53
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Ээээ. Билинк на одной стороне должен уж тогда указывать на объект с другой стороны, а не на билинк.


"Снаружи" это выглядит как будто связывается два билинка, что внутри сказать сложно...


// чтобы определить билинки и отношения м/у ними, сначала определим bilinks:
class B; // mandatory forward declaration
class A: public PObject {
public:
BiLink<B> toB; // attribute must be public
BiLinkVstr<B> B_Vstr; // attribute must be public
...
};
class B: public PObject {
public:
BiLink<A> toA; // attribute must be public
BiLinkVstr<A> A_Vstr; // attribute must be public
...
};

//определяем инициализацию этих связей
//типа:

static int dummy1 =
BiLink_to_BiLink<A,B>::add(&A::toB,&B::toA);
static int dummy2 =
BiLinkVstr_to_BiLinkVstr<A,B>::add(&A::B_Vstr,&B::A_Vstr);



S>Ну я же просил реализацию, а не заголовки .


Извиняюсь

Вот add, remove, replace: (для)


#ifndef CXXCLS_TEMPLATE_BILINKVS_C
#define CXXCLS_TEMPLATE_BILINKVS_C

template<class X>
void BiLinkVstr<X>::add(X* relative)
{
    dirty();
    add_bilink_to((PObject*)relative);
        if(relative) {
            PObject *bilinkvsPObject = (PObject *)relative;
                char* relTop = (char *)bilinkvsPObject -
                                bilinkvsPObject->whatSlot()->oOffset;
                PObject *p=(PObject *)(BiLinkVstr<X> *)BILINK_ATTR(relTop,
                                get_offsetB(bilinkvsPObject));
                bilink_dynamic_call_add_bilink_to(p,this);
        }
}


template<class X>
void BiLinkVstr<X>::replace(o_u4b i, X* newRelative)
{
    dirty();
        if (!!uvstr[i]) {
            PObject *bilinkvsPObject = (PObject *)relative(i);
                char* relTop = (char *)bilinkvsPObject -
                                bilinkvsPObject->whatSlot()->oOffset;
                PObject *p=(PObject *)(BiLinkVstr<X> *)BILINK_ATTR(relTop,
                                get_offsetB(bilinkvsPObject));
                bilink_dynamic_call_remove_link_to(p,this);
        }
        uvstr[i] =  (Link<PObject>) (PObject*) newRelative;
        if(newRelative) {
                PObject *bilinkvsPObject = (PObject *)newRelative;
                char* relTop = (char *)bilinkvsPObject -
                                bilinkvsPObject->whatSlot()->oOffset;
                PObject *p=(PObject *)(BiLinkVstr<X> *)BILINK_ATTR(relTop,
                                get_offsetB(bilinkvsPObject));
                bilink_dynamic_call_add_bilink_to(p,this);
        }
}


template<class X>
void BiLinkVstr<X>::remove(X* oldRelative)
{
    dirty();
        o_4b i = locate_index_of((PObject*)oldRelative);
        if ( i >= 0 ){
            PObject *bilinkvsPObject = (PObject *)oldRelative;
                char* relTop = (char *)bilinkvsPObject -
                               bilinkvsPObject->whatSlot()->oOffset;
                PObject *p=(PObject *)(BiLinkVstr<X> *)BILINK_ATTR(relTop,
                                get_offsetB(bilinkvsPObject));
                bilink_dynamic_call_remove_link_to(p,this);
                shift_over_index(i);
        }
}


#endif


S>Меня интересует, вобщем, всего один вопрос: Как сделать так, чтобы не нужно было зря подгружать объекты при изменении связей.

S>Причем вся прелесть в том, что это должно работать автоматически.

вообще это сделано Versant и они код этот не открывают (просто говорится, что это сделано хорошо).
Я понимаю, что вообще есть желание контролировать этот процесс, но, хотя add, remove, replace приведены выше, add_bilink_to, и все, что глубже закрыто...

дело в том, что лично я сам пишу больше на Java, (Versant VDS Java API) а там этого нет (и ненужно понятно почему)
Re[36]: Объектные базы как они есть
От: stalcer Россия  
Дата: 12.05.05 05:31
Оценка:
Здравствуйте, BaZa, Вы писали:

S>>Меня интересует, вобщем, всего один вопрос: Как сделать так, чтобы не нужно было зря подгружать объекты при изменении связей.

S>>Причем вся прелесть в том, что это должно работать автоматически.

BZ>вообще это сделано Versant и они код этот не открывают (просто говорится, что это сделано хорошо).


Вай, вай. Редиски. И в Bold этот код закрыт.

BZ>дело в том, что лично я сам пишу больше на Java, (Versant VDS Java API) а там этого нет (и ненужно понятно почему)


И почему же . Грузить лишние объекты всегда плохо.
http://www.lmdinnovative.com (LMD Design Pack)
Re[37]: Объектные базы как они есть
От: BaZa  
Дата: 13.05.05 13:11
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Здравствуйте, BaZa, Вы писали:


S>>>Меня интересует, вобщем, всего один вопрос: Как сделать так, чтобы не нужно было зря подгружать объекты при изменении связей.

S>>>Причем вся прелесть в том, что это должно работать автоматически.

BZ>>вообще это сделано Versant и они код этот не открывают (просто говорится, что это сделано хорошо).


S>Вай, вай. Редиски. И в Bold этот код закрыт.


Хм... если это действительно нужно (или просто очень хочется), то я могу попробовать (!) попростить показать код/объяснить как работает в деталях... (?)

BZ>>дело в том, что лично я сам пишу больше на Java, (Versant VDS Java API) а там этого нет (и ненужно понятно почему)


S>И почему же . Грузить лишние объекты всегда плохо.


Я имел ввиду, что в Java все построено на ссылках, поэтому подразумевается, что все такие механизмы нужно писать руками. (а может это просто дискриминация Java )
Re[38]: Объектные базы как они есть
От: stalcer Россия  
Дата: 14.05.05 05:27
Оценка:
Здравствуйте, BaZa, Вы писали:

S>>Вай, вай. Редиски. И в Bold этот код закрыт.


BZ>Хм... если это действительно нужно (или просто очень хочется), то я могу попробовать (!) попростить показать код/объяснить как работает в деталях... (?)


Спасибо. Сильно напрягаться не стоит . А вообще, было бы интересно...
http://www.lmdinnovative.com (LMD Design Pack)
Re: Объектные базы как они есть
От: GlebZ Россия  
Дата: 14.05.05 09:57
Оценка: 1 (1)
Нашел занятный документик. The Lorel Query Language for Semistructured Data. Дюже мне он сильно понравился. Очень гарный язычок.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[20]: Объектные базы как они есть
От: vdimas Россия  
Дата: 17.05.05 17:18
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Здравствуйте, eao197, Вы писали:


E>>Нет, это проблема, только если выбранная коллекция требует для своего изменения полной загрузки себя в память. Например, если коллекция -- это вектор (непрерывная последовательность ссылок). А если коллекция -- это дерево, то в память нужно будет загрузить только вершину и те промежуточные узлы, которые ведут к модифицируемому узлу. И если речь идет о B+ дереве, например, то изятие одного элемента из дерева в несколько миллионов элементов потребует доступа всего к нескольким узлам (страницам) дерева.


S>Я о чем и говорю: коллекции в таком случае должны быть построены так, чтобы не нужно было подгружать ее вообще. Может быть даже просто запоминать все изменения в какой-то другой структуре, для того чтобы когда коллекция реально потребуется — загрузить ее (коллекцию) и скорректировать.


S>Тут еще фишка в том, что в большинстве случаев коллекции — маленькие и без разницы грузить ее всю или только часть. Это все равно одно обращение к базе. А вот если совсем не грузить , это да, это хорошо.


S>А еще может быть и обратная ситуация. Когда коллекция уже загружена, и из нее, например, удаляем объект. Или еще круче: делаем просто Clear(). И прикинь, что для этого необходимо будет подгрузить все соответствующие children объекты, чтобы изменить в них ссылки.


S>А ведь и та и другая ситуация может быть с равной вероятностью. И придумать алгоритм, который бы не грузил лишнее в обоих случаях — вот хитрая задачка.


Да нет, не очень хитрая.
Во-первых, подобные коллекции должны быть весьма специализированными коллециями.
Во-вторых, все коллекции подчиненных объектов одной связи (напр. документ->история) должны архитектурно отделяться в отдельную сущность. Т.е. если документу потребовалось обратиться к собственонй истории, то он должен попросить ее у внешней сущности.

Коллекция подчиненных ссылок может быть загружена (т.е. загружены как минимум все ключи), так и нет. В первом случае мы делаем изменения в коллекции и синхронизируем с БД, во втором — прямо пихаем изменения в БД (если не требуется предварительное чтение, а зачастую именно так).

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

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

Дополнительные бенефиты:
— мы можем поднять всю историю по документу не поднимая сам документ (!!!)
— к внешним сущностям удобно прикручивать всякие навороты, например различные стратегии кеширования. Это принципиально трудноуправляемо (трудноконтролируемо), если сами объекты заведуют своими подчиненными коллекциями.
— в связях многие-ко-многим мы исключаем избыточность взаимных коллекций (берем во внимание, что конкретная колекция — это лишь интерфейс к сущности, обслуживающей связь, который "выглядит" как коллекция).

и т.д.
Re[35]: Объектные базы как они есть
От: vdimas Россия  
Дата: 17.05.05 17:32
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Ну я же просил реализацию, а не заголовки .


А зачем тебе реализация?

У меня, например, единица вхождения многие-ко-многим представлена примерно так:
(схематично)


class ManyToManyLinkEntry<T1, T2> {
    ObjectRef<T1> obj;
    Collection<T2> collection;
}


obj — это lazy ref, инициализируется ключем объекта (либо самим объектом, если тот уже в кеше)
collection — ничем не инициализируется, пустая. Инициализируется при первом обращении (это приведены private поля).

Предполагаю выложить свои наработки рядом с RFD, как высокоуровневое расширение, тогда и будет реализация
Re[6]: Объектные базы как они есть
От: vdimas Россия  
Дата: 17.05.05 17:36
Оценка:
Здравствуйте, Михаил, Вы писали:

М>Здравствуйте, vdimas, Вы писали:


М>Это почти ObjectStore. С нормальным С++. И с транзакциями.

М>Правда, с SQL там туговато...

А как с быстродействием и надежностью?
Re[21]: Объектные базы как они есть
От: stalcer Россия  
Дата: 19.05.05 06:43
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Во-вторых, все коллекции подчиненных объектов одной связи (напр. документ->история) должны архитектурно отделяться в отдельную сущность. Т.е. если документу потребовалось обратиться к собственонй истории, то он должен попросить ее у внешней сущности.


Пусть так. Значит есть некий класс, который как бы является интерфейсом к ассоциации в целом. Т.е. позволяет создавать новые экземпляры ассоциации (т.е. связи), и удалять их. Т.е. связывать и развязывать объекты. Внутри этого класса есть глобальный список всех Entry. Так?
Каждая Entry — это связь.

Здесь можно по разному сделать:

1) Каждая Entry — это связь ровно между двумя объектами. Независимо от того, "один к одному", "один ко многим" или "многие ко многим".
2) Каждая Entry — это как ты написал здесь
Автор: vdimas
Дата: 17.05.05
. Т.е. (ключ + коллекция ключей) для один ко многим. Ну и соответственно (ключ + ключ) для один к одному. Или я неправильно понял?

V>Коллекция подчиненных ссылок может быть загружена (т.е. загружены как минимум все ключи), так и нет. В первом случае мы делаем изменения в коллекции и синхронизируем с БД, во втором — прямо пихаем изменения в БД (если не требуется предварительное чтение, а зачастую именно так).


Эээ. Я принципиально все изменения делаю в кэше. Сброс только потом, т.е. не сразу. Так что, как раз интересует, как это сделать, если коллекция не загружена.

V>Вопрос о синхронизации отпадает сам собой, если все эти коллекции управляются внешней сущностью, и являются, по-сути, лишь интерфейсом-фильтром к ней, т.е. не хранят собственную копию набора ключей/ссылок.


Т.е у тебя нет перектрестных ссылок в самих объектах. Но, какие-то ссылки в самих объектах есть? Например, ссылка на соответствующий Entry? Или же Entry ты ищешь ассоциативно, по id объекта.

V>- в связях многие-ко-многим мы исключаем избыточность взаимных коллекций (берем во внимание, что конкретная колекция — это лишь интерфейс к сущности, обслуживающей связь, который "выглядит" как коллекция).


Ну, имхо, в связях многие ко многим избыточности коллекций (если они сделаны в лоб, т.е. в обоих объектах по коллекции) как раз и нет.
Понимаешь, меня интересует не просто как сделать. Сделать-то я могу. Меня интересует алгоритм, который был бы эффективен по памяти и по скорости работы одновременно.

Вот, например, проанализируй, насколько твоя внешняя сущность (т.е. всякие Entry) занимает больше памяти, чем просто перекрестные ссылки. Особенно для случая "один к одному"?
И если в самих объектах ты не хранишь ссылок вообще (ну, там на Entry, например), то сколько индексов тебе надо построить в памяти, чтобы для всех возможных действий ассоциативный доступ к Entry (или к нескольким Entry) производился по индексу (хеш таблице).
http://www.lmdinnovative.com (LMD Design Pack)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.