Тема: assumeOwnershipOf() + abortTransaction() ???

Имею стабильный сбой при такой связке. Помогите найти проблему, плиз.
Запускаю транзакцию, использую assumeOwnershipOf() для группы 3Дсолидов (вытаскиваю их из блоков в Model), далее
модифицирую их. И иногда нужно выполнить abortTransaction(), чтобы вернуть все как было, вот тут-то и происходит сбой.
Подозреваю, что что-то не учитываю при assumeOwnershipOf().
Там в описании не очень понятно:
If all these conditions are met, then the ownership of all the entities is switched, the transaction for the prior owner block table records (BTRs) is closed, the entities are marked as modifed, and the change is recorded in the entities’ undo filers. Upon return, the entities will remain open, as it is the caller’s responsibility to close them after making any other desired changes....
If the caller cancels out of any or all of the entities after a successful completion of this call, then part of the immediate undo playback will include restoring the old owner, and modifying that old owner again.
If Undo is invoked, then each object will independently restore itself, so that multiple processing of the original and target BTRs will be avoided
Что-то как раз говорится про транзакцию и про то, что примитивы остаются открытыми, если так то как их закрывать,
ведь я отдавал функции только ObjectIds ?
Может есть у кого код с startTransaction() + assumeOwnershipOf() + abortTransaction() ?

Re: assumeOwnershipOf() + abortTransaction() ???

Готового примера нет, но перед тем как вызывать abortTransaction() нужно закрыть все примитивы участвующие в транзакции, старых владельцев и новых владельцев (используя метод close()). Если это не глюк в AutoCAD, то так должно работать.

Re: assumeOwnershipOf() + abortTransaction() ???

Может я где-нибудь здесь накосячил :
        pTrans = actrTransactionManager->startTransaction();  // начинаем транзакцию
        ...
        AcDbObjectId solId;  // заполняем ее AcDb3dSolid, который подвергнется FILLET
        AcDbBlockTable*        pBlockTable;
        AcDbBlockTableRecord*  pBTR=NULL;
        AcDbObjectIdArray toMove, idRefs;
        if () {  // solId находится в блоке
                toMove.append(solId);
                if (acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead) == Acad::eOk) {
                  if (pBlockTable->getAt(ACDB_MODEL_SPACE, pBTR,  AcDb::kForWrite) == Acad::eOk) {
                    pBlockTable->close();
                    es = pBTR->assumeOwnershipOf(toMove);    // вытаскиваем на поверхность
                    pBTR->getBlockReferenceIds(idRefs);
                    pBTR->close();
                    if ( Acad::eOk == acdbOpenObject( pEnt, solId, AcDb::kForWrite)) { //     acutPrintf("\n Trans !!!!");
                        pEnt = doBlockTransform (Ids, pEnt, true);    // трансформирует, чтоб тело стояло в том же месте, но в ModelSpace :)
                            // actrTransactionManager->addNewlyCreatedDBRObject(pEnt);  ???  - это вроде не надо
                        pEnt->close();
                    }
                    if ( Acad::eOk == acdbOpenObject( pEnt, solId, AcDb::kForRead)) { // acutPrintf("\n Trans !!!!");
                        pEnt->draw();        pEnt->close();    // отрисуем
                    }    // Обновим все вставки этого блока
                    for (int i=0; i < idRefs.length(); i++) {
                        AcDbObjectPointer<AcDbEntity> pEnt(idRefs[i],AcDb::kForWrite);
                        if (pEnt.openStatus() == Acad::eOk) {
                            pEnt->recordGraphicsModified();
                        }
                    }
                  }  // if open pBTR
                  else
                        pBlockTable->close();
                }    // if open pBlockTable
        } // for blocks
        // ----------- command FILLET ---------
            ads_name   sset,  first, nm;
            AcGePoint3dArray allPts;  // в нем лежат PickPoints для fillet
            if (Acad::eOk == acdbGetAdsName(first, solId)) {
                for (j=0; j<allPts.length(); j++){
                    cPt = transP(allPts[j], 0, 1, 0);    // WCS -> UCS
                    if (j == 0)
                        acedCommand( RTSTR, "FILLET",  RT3DPOINT, asDblArray( cPt ),  RTREAL, cRadius,  RTNONE);
                    else
                        acedCommand( RT3DPOINT, asDblArray( cPt ),  RTNONE);
                }
                acedCommand( RTSTR, "",   RTNONE);
            }
        // ------ заносим измененное тело назад в блок --------
        toMove.setLogicalLength(0);
        if () {  // solId находился в блоке
            if (acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead) == Acad::eOk) {
                dadId = Ids[Ids.length() - 2];  // это Id BlockReference в котором лежит наше тело
                    if ( Acad::eOk == acdbOpenObject( pEnt, dadId, AcDb::kForRead)) { //   acutPrintf("\n isA2= %s\n", pEnt->isA()->name());
                        btrId = AcDbObjectId::kNull;
                        AcDbBlockReference* pBl = AcDbBlockReference::cast(pEnt);
                        if (pBl)        btrId = pBl->blockTableRecord();
                        pEnt->close();    // закрываем
                        if (btrId !=  AcDbObjectId::kNull) {
                              if (acdbOpenObject( pBTR, btrId, AcDb::kForWrite) == Acad::eOk) {
                                toMove.append(solId);
                                es = pBTR->assumeOwnershipOf(toMove);
                                if ( Acad::eOk == acdbOpenObject( pEnt, solId, AcDb::kForWrite)) { //     acutPrintf("\n Trans !!!!");
                                    pEnt = doBlockTransformBack (Ids, pEnt, true);  // обратная  трансформация
                                    // actrTransactionManager->addNewlyCreatedDBRObject(pEnt); ??
                                    pEnt->close();
                                }   // Обновим все вставки этого блока
                                idRefs.setLogicalLength(0);
                                pBTR->getBlockReferenceIds(idRefs);
                                pBTR->close();
                                for (int i=0; i < idRefs.length(); i++) {
                                    AcDbObjectPointer<AcDbEntity> pEnt(idRefs[i],AcDb::kForWrite);
                                    if (pEnt.openStatus() == Acad::eOk) {
                                        pEnt->recordGraphicsModified();
                                    }
                                }
                                actrTransactionManager->queueForGraphicsFlush();
                                actrTransactionManager->flushGraphics();
                              }
                        }
                    } // open dadId
                }
        } // in block
        ...
        actrTransactionManager->abortTransaction();   // откат  и здесь сбой.
        Итого, отрывались 2 BTR (ModelSpace и Block с телом) и обе были closed().
        Также открывалось само тело, но тоже каждый раз делал для него close().

Re: assumeOwnershipOf() + abortTransaction() ???

На первый взгляд все нормально. Если хочешь, пришли мне проект целиком в архиве - потестирую.

Re: assumeOwnershipOf() + abortTransaction() ???

Весь проект на мегабайт вытянет, долго там концы искать. Наверно все таки плюнуть на assumeOwnershipOf() и работать с копией тела  clone(). А потом копию результата закинуть в блок
взамен исходного тела. Вот только это будет уже
другое тело, с другим ObjId, чего не хотелось бы...

Re: assumeOwnershipOf() + abortTransaction() ???

Еще вопросик в догонку, как опознать, что комманда acedCommand( RTSTR, "FILLET" ....) по какой-то причине (скажем не нашла по точке ни одного примитива) обругалась и досрочно закончила свое действие, а я не зная об этом все пытаюсь ей подсовывать аргументы для работы ?

Re: assumeOwnershipOf() + abortTransaction() ???

> serge
Если выкинуть файлы *.obj *.pch *.ncb *.idb, каталоги Release и Debug целиком, то в архиве наверняка и 100Kb не будет... Проверено опытным путем на относительно больших проектах с числом строк программ порядка миллиона.

> serge
Проверяй код возврата acedCommand и если он не RTNORM, то команда прервалась. Можно еще проверять значение системных переменных CMDACTIVE и CMDNAMES (посмотри их описание и поэкспериментируй.)  Кроме того передавай в acedCommnad глобальные имена команд (вместо "FILLET" пиши "_.FILLET")