Тема: Почему при программной очистке файла его размер увеличивается?

Всем доброго времени суток
Интересная проблема.
Есть несколько своих объектов + данные в NOD
Есть собственная команда очистки чертежа, которая удаляет все свои объекты + разделы NOD.
Но после выполнения этой команды и сохраения чертежа размер файла не уменьшается а... возрастает
Команда очитки работает корректно, посокольку после ее работы просмаотриваю чертеж с помощью ARXDBG - исходных объектов нет
Файл уменьшвется только после вызова команды "_PURGE".
Вопрос: в чем дело?

Re: Почему при программной очистке файла его размер увеличивается?

> Roman
А purge что-то находит? Видимо ты все-таки не все удалил.

Re: Почему при программной очистке файла его размер увеличивается?

Находит размерный стиль и слой

Re: Почему при программной очистке файла его размер увеличивается?

В NOD создаю свой раздел а в нем вложенные разделы. Было подозрение что забываю удалить вложенные но проверил, все удаляется.

Re: Почему при программной очистке файла его размер увеличивается?

А если после твоей команды сделать "save as"? Размер такой же или уменьшился?
Также надо помнить, что начиная с версии 2004 акад компрессирует свои файлы. Чем-то вроде зипа. Поэтому размер может быть разным.

Re: Почему при программной очистке файла его размер увеличивается?

Размер такой же.
Использую ACAD 2002.

Re: Почему при программной очистке файла его размер увеличивается?

В разделы NOD записываются объекты-потомки AcDbObject
В методах dwgIn \Out которых используются

inline Acad::ErrorStatus
readItem(void* buf, Adesk::UInt32 cnt);
writeItem(const void* buf, Adesk::UInt32 cnt);

Возможно ли, что после удалении объекта, данные которые он записал остаются в файле?  И только purge их может удалить окончательно.
Других причин поведения описанного в теме, больше не вижу

Re: Почему при программной очистке файла его размер увеличивается?

> Roman
Как удаляешь, erase'ом? Вызваешь ли у dictionary remove? Кто является владельцем (parent) удаляемых объектов?
Подозреваю такую ситуацию (если parent - NOD). При вызове метода erase какого-либо объекта, реально ведь объект не удаляется, а только помечается как удаленный. Возможно, дикшенери (NOD) фильтрует помеченные объекты и не показывает их, но сохраняет в файле. И только purge реально их вычищает.
По идее, при вызове метода remove у NOD'а, тот удалит у себя объект (хотя сам объект останется, более того, даже не будет помечен как удаленный). Но при записи в файл, объект не сохранится, так как у него не будет parent'a.

Re: Почему при программной очистке файла его размер увеличивается?

Вызывается erase на каждом ключе раздела, а потом erase на всем разделе.
А вот насчет

И только purge реально их вычищает.

ты бесспорно прав.

Re: Почему при программной очистке файла его размер увеличивается?

> Roman
Вообще-то PURGE чистит только из определнных таблиц (слои, типы линий, блоки и т.д.). В них, как я понял, ты ничего не пишешь. Поэтому эффект непонятен. Попробуй выполнить команду _WBLOCK * - интересно изменится размер или нет. Ну и еще интересно взглянуть на кусок кода, который выполнеят удаление. Есть еще очень полезный метод у класса AcDbDatabase. Называется purge(). Он из переданного массива AcDbObjectIdArray выкидывает те объекты, на которые есть ссылки в чертеже. Занеси в этот массив все объекты которые удалил, выполни purge() и посмотри осталось ли в нем что-то.

Re: Почему при программной очистке файла его размер увеличивается?

Тут только что еще один интересный фокус вылез:
1. Вызываю свою команду
2. Вызываю "purge"
3. Просто закрываю появившеясе окно
И.. о чудо, при сохранении размер файла уменьшился, чего от него и ожидалось
Если 2, 3 не не выполнять - размер файла не изменяется.
Вот код очистки объекта из словаря

Acad::ErrorStatus eraseKeyFromNode(const CString &dictName, const CString &keyName)
{
    Closer<AcDbDictionary> nod;
    Acad::ErrorStatus es = acdbCurDwg()->getNamedObjectsDictionary(nod, AcDb::kForWrite);
    if(es != Acad::eOk) return es;
    AcDbObjectId objectId;
    es = nod->remove(dictName, objectId);
    nod.close();
    if(es != Acad::eOk) return es;
    Closer<AcDbDictionary> root_param;
    es = root_param.open(objectId, AcDb::kForRead);
    if(es != Acad::eOk) return es;
    es = root_param->getAt(keyName, objectId);
    root_param.close();
    if(es != Acad::eOk) return es;
    Closer<CMyDwgArchive> pArchive;
    es = pArchive.open(objectId, AcDb::kForWrite);    
    if(es != Acad::eOk) return es;
    
    return pArchive->erase();
}

Closer - Это мой клас-шаблон выполняющий закрытие объекта, которым владеет в деструкторе

Re: Почему при программной очистке файла его размер увеличивается?

Как я понял ты не удаляешь из базы root_param (nod->remove() удаляет только из AcDbDictionary, но в dwg оставляет - читаем справку). Так должно быть?

Re: Почему при программной очистке файла его размер увеличивается?

Это экспериментальный код с последним изменением по совету >Ведмедь.
Вот так функция выглядит сейчас:
root_param также удаляется, но другой функцией.
Это служебные функции нижнего уровня:

Acad::ErrorStatus eraseKeyFromNode(const CString &dictName, const CString &keyName)
{
    Closer<AcDbDictionary> nod;
    Acad::ErrorStatus es = acdbCurDwg()->getNamedObjectsDictionary(nod, AcDb::kForWrite);
    if(es != Acad::eOk) return es;
    AcDbObjectId objectId;
    es = nod->getAt(dictName, objectId);
    nod.close();
    if(es != Acad::eOk) return es;
    Closer<AcDbDictionary> root_param;
    es = root_param.open(objectId, AcDb::kForRead);
    if(es != Acad::eOk) return es;
    es = root_param->remove(keyName, objectId);
    root_param.close();
    if(es != Acad::eOk) return es;
    Closer<CMyDwgArchive> pArchive;
    es = pArchive.open(objectId, AcDb::kForWrite);    
    if(es != Acad::eOk) return es;
    
        return pArchive->erase();
}
Acad::ErrorStatus eraseRootKeyFromNode(const CString &dictName)
{
    Closer<AcDbDictionary> nod;
    Acad::ErrorStatus es = acdbCurDwg()->getNamedObjectsDictionary(nod, AcDb::kForRead);    
    if(es != Acad::eOk) return es;
    AcDbObjectId objectId;
    es = nod->remove(dictName, objectId);
    nod.close();
    if(es != Acad::eOk) return es;
    Closer<AcDbDictionary> root_param;
    es = root_param.open(objectId, AcDb::kForWrite);
    if(es != Acad::eOk) return es;
    return root_param->erase();    
}

Вызов в команде выглядит так:

eraseKeyFromNode(consts::DocumentVarsRootDict, "Key1");
eraseKeyFromNode(consts::DocumentVarsRootDict, "Key2");
eraseKeyFromNode(consts::DocumentVarsRootDict, "Key3");
eraseRootKeyFromNode(consts::DocumentVarsRootDict);

"Key_" привел для примера, фактические имена немножко другие, здесь это не важно. Разделов всегда 3, имена их фиксированные.

Re: Почему при программной очистке файла его размер увеличивается?

Первое, что приходит на ум - вместо AcDb::kForRead во второй функции должно быть AcDb::kForWrite

Re: Почему при программной очистке файла его размер увеличивается?

P.S.: Все функции возвращают Acad::eOk?

Re: Почему при программной очистке файла его размер увеличивается?

> Roman
Если ты удалешь все скопом, то достаточно удалить объект верхнего уровня. В твоем случае это root_param. Просто вызываешь для него erase. Он удалится из nod, а также удалятся все объекты, которыми он владеет.

Re: Почему при программной очистке файла его размер увеличивается?

> Exhumer
Это теоретически. Практически может быть не так. Особенно в AutoCAD 2002.

> Roman
Появилась еще одна идея. Какое у тебя значение системной переменной ISAVEPERCENT ? По умолчанию оно 50. Установи ее в 0 и попробуй сохранить чертеж.

Re: Почему при программной очистке файла его размер увеличивается?

Александр Ривилис пишет:

Практически может быть не так

Как такое может быть? Если удален владелец, то и все его объекты удаляться. Точно также если в базу объект добавить, но владельца ему не прописать.

Re: Почему при программной очистке файла его размер увеличивается?

При полном сохранении - да. Тогда AutoCAD просматривает все связи и сохраняет только то, что имеет владельца. А при частичном - совершенно необязательно. Они могут оставаться в dwg, хотя обратиться к ним будет видимо невозможно (может быть только напрямую по метке).

Re: Почему при программной очистке файла его размер увеличивается?

> Александр Ривилис
Интересно. А откуда дровишки, если не секрет? Экспериментально такое поведение, полагаю, выявить крайне затруднительно.

Re: Почему при программной очистке файла его размер увеличивается?

> Exhumer
Посмотри описание переменной  ISAVEPERCENT. Ну и кое-что с сайта ADN.

Re: Почему при программной очистке файла его размер увеличивается?

> Александр Ривилис
Там действительно ошибка :(

> Александр Ривилис
Помогло сразу.
Как я и думал, данные просто оставались в файле.
Самое интересное что вызов команды purge также помогал (см. как описано > Roman (2006-08-15 19:10:50)
Большое спасибо всем за советы и подсказки

Re: Почему при программной очистке файла его размер увеличивается?

> Roman
Ну и отлично. Приятно, что удалось докопаться до истины. А вот почему помогает вызов purge - понятия не имею. Из спортивного интереса повтори тоже самое и перед запуском purge включи все реакторы в ARXDBG. Может это подскажет, что же такое делает purge, даже если ее сразу завершить.

Re: Почему при программной очистке файла его размер увеличивается?

Уже из чисто спортивного интереса.
Включил реакторы - но ничего не увидел :(
Установил:
purge лежит в AcPurge.arx, подгрузка которого выполняется автоматически.